From c11bc0e9b371f737362038666037ee506dc1ba4d Mon Sep 17 00:00:00 2001 From: "jk7744.park" Date: Mon, 26 Oct 2015 15:46:01 +0900 Subject: [PATCH] tizen 2.4 release --- .gitignore | 39 + LICENSE | 70 + README | 75 + automated-tests/.gitignore | 5 + .../.gitignore-with-autogenerated-files | 4 + .../.gitignore-without-autogenerated-files | 3 + automated-tests/CMakeLists.txt | 13 + automated-tests/README.md | 221 + automated-tests/build.sh | 50 + automated-tests/coverage.sh | 30 + automated-tests/execute.sh | 106 + automated-tests/packaging/core-dali-tests.spec | 51 + automated-tests/scripts/add_all_smack_rule.sh | 26 + automated-tests/scripts/add_smack_rule.sh | 28 + automated-tests/scripts/add_style.pl | 30 + automated-tests/scripts/all_smack.rule | 28 + automated-tests/scripts/autocompletion.sh | 18 + automated-tests/scripts/init.sh | 10 + automated-tests/scripts/retriever.sh | 212 + automated-tests/scripts/summarize.pl | 109 + automated-tests/scripts/tcbuild.sh | 215 + automated-tests/scripts/tcheadgen.sh | 71 + automated-tests/scripts/tcpackageslistsgen.sh | 72 + automated-tests/scripts/tctestsgen.sh | 66 + automated-tests/src/CMakeLists.txt | 6 + automated-tests/src/common/assert.h | 82 + automated-tests/src/common/signal-helper.h | 1082 +++ automated-tests/src/common/testcase.h | 18 + automated-tests/src/dali-devel/CMakeLists.txt | 67 + .../src/dali-devel/tct-dali-devel-core.cpp | 40 + automated-tests/src/dali-devel/utc-Dali-Actor.cpp | 131 + automated-tests/src/dali-devel/utc-Dali-Atlas.cpp | 191 + .../src/dali-devel/utc-Dali-Constrainer.cpp | 546 ++ .../src/dali-devel/utc-Dali-Context.cpp | 134 + .../src/dali-devel/utc-Dali-CullFace.cpp | 83 + .../src/dali-devel/utc-Dali-DistanceField.cpp | 68 + .../src/dali-devel/utc-Dali-Geometry.cpp | 670 ++ automated-tests/src/dali-devel/utc-Dali-Hash.cpp | 61 + .../src/dali-devel/utc-Dali-HitTestAlgorithm.cpp | 417 + .../src/dali-devel/utc-Dali-Material.cpp | 1169 +++ automated-tests/src/dali-devel/utc-Dali-Mutex.cpp | 138 + .../src/dali-devel/utc-Dali-PropertyBuffer.cpp | 491 ++ .../src/dali-devel/utc-Dali-Renderer.cpp | 1077 +++ .../src/dali-devel/utc-Dali-Sampler.cpp | 448 + .../src/dali-devel/utc-Dali-Scripting.cpp | 1039 +++ automated-tests/src/dali-devel/utc-Dali-Shader.cpp | 315 + .../src/dali-devel/utc-Dali-WeakHandle.cpp | 378 + automated-tests/src/dali-internal/CMakeLists.txt | 57 + .../src/dali-internal/tct-dali-internal-core.cpp | 40 + .../utc-Dali-Internal-FixedSizeMemoryPool.cpp | 146 + .../utc-Dali-Internal-FrustumCulling.cpp | 383 + .../dali-internal/utc-Dali-Internal-Handles.cpp | 70 + .../utc-Dali-Internal-Image-Culling.cpp | 847 ++ .../utc-Dali-Internal-ImageFactory.cpp | 621 ++ ...utc-Dali-Internal-MemoryPoolObjectAllocator.cpp | 183 + .../utc-Dali-Internal-ResourceClient.cpp | 1022 +++ automated-tests/src/dali/CMakeLists.txt | 118 + .../dali-test-suite-utils.cpp | 304 + .../dali-test-suite-utils/dali-test-suite-utils.h | 375 + .../dali/dali-test-suite-utils/mesh-builder.cpp | 90 + .../src/dali/dali-test-suite-utils/mesh-builder.h | 38 + .../dali-test-suite-utils/test-application.cpp | 206 + .../dali/dali-test-suite-utils/test-application.h | 109 + .../dali-test-suite-utils/test-gesture-manager.cpp | 103 + .../dali-test-suite-utils/test-gesture-manager.h | 93 + .../dali-test-suite-utils/test-gl-abstraction.cpp | 107 + .../dali-test-suite-utils/test-gl-abstraction.h | 1999 +++++ .../test-gl-sync-abstraction.cpp | 136 + .../test-gl-sync-abstraction.h | 112 + .../dali/dali-test-suite-utils/test-harness.cpp | 301 + .../src/dali/dali-test-suite-utils/test-harness.h | 109 + .../dali-test-suite-utils/test-intrusive-ptr.h | 60 + .../dali-test-suite-utils/test-native-image.cpp | 40 + .../dali/dali-test-suite-utils/test-native-image.h | 56 + .../test-platform-abstraction.cpp | 333 + .../test-platform-abstraction.h | 236 + .../test-render-controller.cpp | 60 + .../dali-test-suite-utils/test-render-controller.h | 54 + .../dali/dali-test-suite-utils/test-touch-utils.h | 78 + .../test-trace-call-stack.cpp | 128 + .../dali-test-suite-utils/test-trace-call-stack.h | 106 + automated-tests/src/dali/tct-dali-core.cpp | 40 + automated-tests/src/dali/utc-Dali-Actor.cpp | 2910 +++++++ .../src/dali/utc-Dali-AlphaFunction.cpp | 252 + automated-tests/src/dali/utc-Dali-AngleAxis.cpp | 115 + automated-tests/src/dali/utc-Dali-Animation.cpp | 8925 ++++++++++++++++++++ automated-tests/src/dali/utc-Dali-Any.cpp | 345 + automated-tests/src/dali/utc-Dali-BaseHandle.cpp | 535 ++ automated-tests/src/dali/utc-Dali-BufferImage.cpp | 515 ++ automated-tests/src/dali/utc-Dali-CameraActor.cpp | 1552 ++++ .../src/dali/utc-Dali-ConnectionTracker.cpp | 210 + automated-tests/src/dali/utc-Dali-Constrainer.cpp | 134 + automated-tests/src/dali/utc-Dali-Constraint.cpp | 1206 +++ .../src/dali/utc-Dali-ConstraintFunction.cpp | 347 + .../src/dali/utc-Dali-ConstraintSource.cpp | 146 + automated-tests/src/dali/utc-Dali-Constraints.cpp | 402 + automated-tests/src/dali/utc-Dali-CustomActor.cpp | 2011 +++++ automated-tests/src/dali/utc-Dali-Degree.cpp | 99 + .../src/dali/utc-Dali-EncodedBufferImage.cpp | 882 ++ .../src/dali/utc-Dali-FrameBufferImage.cpp | 260 + automated-tests/src/dali/utc-Dali-Gesture.cpp | 85 + .../src/dali/utc-Dali-GestureDetector.cpp | 439 + automated-tests/src/dali/utc-Dali-Handle.cpp | 760 ++ .../src/dali/utc-Dali-HoverProcessing.cpp | 1286 +++ automated-tests/src/dali/utc-Dali-Image.cpp | 399 + automated-tests/src/dali/utc-Dali-ImageActor.cpp | 1653 ++++ automated-tests/src/dali/utc-Dali-IntrusivePtr.cpp | 461 + automated-tests/src/dali/utc-Dali-KeyEvent.cpp | 271 + automated-tests/src/dali/utc-Dali-Layer.cpp | 581 ++ .../src/dali/utc-Dali-LocklessBuffer.cpp | 117 + .../src/dali/utc-Dali-LongPressGesture.cpp | 82 + .../src/dali/utc-Dali-LongPressGestureDetector.cpp | 1454 ++++ automated-tests/src/dali/utc-Dali-MathUtils.cpp | 319 + automated-tests/src/dali/utc-Dali-Matrix.cpp | 802 ++ automated-tests/src/dali/utc-Dali-Matrix3.cpp | 384 + automated-tests/src/dali/utc-Dali-MeshMaterial.cpp | 136 + automated-tests/src/dali/utc-Dali-NativeImage.cpp | 214 + .../src/dali/utc-Dali-NinePatchImages.cpp | 333 + .../src/dali/utc-Dali-ObjectRegistry.cpp | 358 + automated-tests/src/dali/utc-Dali-PanGesture.cpp | 147 + .../src/dali/utc-Dali-PanGestureDetector.cpp | 2517 ++++++ automated-tests/src/dali/utc-Dali-Path.cpp | 396 + automated-tests/src/dali/utc-Dali-PinchGesture.cpp | 107 + .../src/dali/utc-Dali-PinchGestureDetector.cpp | 1379 +++ automated-tests/src/dali/utc-Dali-Pixel.cpp | 206 + .../src/dali/utc-Dali-PropertyArray.cpp | 221 + automated-tests/src/dali/utc-Dali-PropertyMap.cpp | 275 + .../src/dali/utc-Dali-PropertyNotification.cpp | 879 ++ .../src/dali/utc-Dali-PropertyTypes.cpp | 129 + .../src/dali/utc-Dali-PropertyValue.cpp | 1242 +++ automated-tests/src/dali/utc-Dali-Quaternion.cpp | 1118 +++ automated-tests/src/dali/utc-Dali-Radian.cpp | 150 + automated-tests/src/dali/utc-Dali-Random.cpp | 58 + automated-tests/src/dali/utc-Dali-Rect.cpp | 312 + automated-tests/src/dali/utc-Dali-RenderTask.cpp | 3456 ++++++++ .../src/dali/utc-Dali-RenderTaskList.cpp | 170 + .../src/dali/utc-Dali-ResourceImage.cpp | 491 ++ automated-tests/src/dali/utc-Dali-ShaderEffect.cpp | 949 +++ .../src/dali/utc-Dali-SignalTemplates.cpp | 2228 +++++ .../src/dali/utc-Dali-SignalTemplatesFunctors.cpp | 513 ++ automated-tests/src/dali/utc-Dali-Stage.cpp | 1323 +++ automated-tests/src/dali/utc-Dali-TapGesture.cpp | 86 + .../src/dali/utc-Dali-TapGestureDetector.cpp | 1387 +++ .../src/dali/utc-Dali-TouchEventCombiner.cpp | 902 ++ .../src/dali/utc-Dali-TouchProcessing.cpp | 1368 +++ automated-tests/src/dali/utc-Dali-TypeRegistry.cpp | 1749 ++++ automated-tests/src/dali/utc-Dali-Uint16Pair.cpp | 200 + automated-tests/src/dali/utc-Dali-Vector.cpp | 1371 +++ automated-tests/src/dali/utc-Dali-Vector2.cpp | 609 ++ automated-tests/src/dali/utc-Dali-Vector3.cpp | 660 ++ automated-tests/src/dali/utc-Dali-Vector4.cpp | 667 ++ automated-tests/src/dali/utc-Dali-WheelEvent.cpp | 278 + automated-tests/style/back_top.png | Bin 0 -> 1122 bytes automated-tests/style/blue.jpg | Bin 0 -> 954 bytes automated-tests/style/gray.jpg | Bin 0 -> 866 bytes automated-tests/style/jquery.min.js | 4 + automated-tests/style/orange.jpg | Bin 0 -> 934 bytes automated-tests/style/popup.js | 1215 +++ automated-tests/style/red.jpg | Bin 0 -> 937 bytes automated-tests/style/summary.xsl | 352 + automated-tests/style/testresult.xsl | 571 ++ automated-tests/style/tests.css | 195 + automated-tests/tcbuild | 1 + automated-tests/templates/tct-package/README | 43 + automated-tests/templates/tct-package/inst.sh | 37 + build/scripts/dali_env | 602 ++ build/scripts/generate-shader-strings.pl | 390 + build/tizen/.gitignore | 21 + build/tizen/Makefile.am | 59 + build/tizen/configure.ac | 117 + build/tizen/dali-core.pc.in | 12 + build/tizen/dali-core/Makefile.am | 159 + build/tizen/dali-core/linker-test.cpp | 55 + dali.manifest | 5 + dali/.gitignore | 1 + dali/devel-api/animation/path-constrainer.cpp | 74 + dali/devel-api/animation/path-constrainer.h | 136 + dali/devel-api/common/hash.cpp | 61 + dali/devel-api/common/hash.h | 48 + dali/devel-api/common/map-wrapper.h | 47 + dali/devel-api/common/mutex.cpp | 66 + dali/devel-api/common/mutex.h | 92 + dali/devel-api/common/ref-counted-dali-vector.h | 73 + dali/devel-api/common/set-wrapper.h | 45 + dali/devel-api/events/hit-test-algorithm.cpp | 45 + dali/devel-api/events/hit-test-algorithm.h | 163 + dali/devel-api/file.list | 55 + dali/devel-api/images/atlas.cpp | 87 + dali/devel-api/images/atlas.h | 156 + dali/devel-api/images/distance-field.cpp | 256 + dali/devel-api/images/distance-field.h | 50 + dali/devel-api/object/property-buffer.cpp | 83 + dali/devel-api/object/property-buffer.h | 183 + dali/devel-api/object/type-registry-helper.h | 90 + dali/devel-api/object/weak-handle.cpp | 135 + dali/devel-api/object/weak-handle.h | 220 + dali/devel-api/rendering/cull-face.cpp | 37 + dali/devel-api/rendering/cull-face.h | 58 + dali/devel-api/rendering/geometry.cpp | 104 + dali/devel-api/rendering/geometry.h | 192 + dali/devel-api/rendering/material.cpp | 165 + dali/devel-api/rendering/material.h | 307 + dali/devel-api/rendering/renderer.cpp | 98 + dali/devel-api/rendering/renderer.h | 157 + dali/devel-api/rendering/sampler.cpp | 96 + dali/devel-api/rendering/sampler.h | 187 + dali/devel-api/rendering/shader.cpp | 64 + dali/devel-api/rendering/shader.h | 153 + dali/devel-api/scripting/scripting.cpp | 681 ++ dali/devel-api/scripting/scripting.h | 292 + dali/integration-api/bitmap.cpp | 330 + dali/integration-api/bitmap.h | 348 + dali/integration-api/context-notifier.h | 55 + dali/integration-api/core.cpp | 163 + dali/integration-api/core.h | 437 + dali/integration-api/debug.cpp | 324 + dali/integration-api/debug.h | 489 ++ dali/integration-api/events/event.cpp | 38 + dali/integration-api/events/event.h | 74 + dali/integration-api/events/gesture-event.cpp | 41 + dali/integration-api/events/gesture-event.h | 75 + dali/integration-api/events/gesture-requests.h | 178 + dali/integration-api/events/hover-event-integ.cpp | 43 + dali/integration-api/events/hover-event-integ.h | 62 + dali/integration-api/events/key-event-integ.cpp | 55 + dali/integration-api/events/key-event-integ.h | 115 + .../events/long-press-gesture-event.cpp | 39 + .../events/long-press-gesture-event.h | 75 + .../events/multi-point-event-integ.cpp | 70 + .../events/multi-point-event-integ.h | 101 + dali/integration-api/events/pan-gesture-event.cpp | 41 + dali/integration-api/events/pan-gesture-event.h | 87 + .../integration-api/events/pinch-gesture-event.cpp | 44 + dali/integration-api/events/pinch-gesture-event.h | 79 + dali/integration-api/events/tap-gesture-event.cpp | 40 + dali/integration-api/events/tap-gesture-event.h | 83 + dali/integration-api/events/touch-data.h | 105 + .../events/touch-event-combiner.cpp | 384 + dali/integration-api/events/touch-event-combiner.h | 174 + dali/integration-api/events/touch-event-integ.cpp | 43 + dali/integration-api/events/touch-event-integ.h | 62 + dali/integration-api/events/wheel-event-integ.cpp | 55 + dali/integration-api/events/wheel-event-integ.h | 111 + dali/integration-api/file.list | 61 + dali/integration-api/gesture-manager.h | 66 + dali/integration-api/gl-abstraction.h | 381 + dali/integration-api/gl-defines.h | 827 ++ dali/integration-api/gl-sync-abstraction.h | 80 + dali/integration-api/image-data.cpp | 83 + dali/integration-api/image-data.h | 197 + dali/integration-api/input-options.cpp | 108 + dali/integration-api/input-options.h | 151 + dali/integration-api/lockless-buffer.cpp | 100 + dali/integration-api/lockless-buffer.h | 113 + dali/integration-api/platform-abstraction.h | 245 + dali/integration-api/profiling.cpp | 157 + dali/integration-api/profiling.h | 71 + dali/integration-api/render-controller.h | 61 + dali/integration-api/resource-cache.h | 86 + dali/integration-api/resource-declarations.h | 67 + dali/integration-api/resource-policies.h | 48 + dali/integration-api/resource-request.h | 203 + dali/integration-api/resource-types.h | 239 + dali/integration-api/system-overlay.cpp | 65 + dali/integration-api/system-overlay.h | 104 + dali/internal/common/blending-options.cpp | 317 + dali/internal/common/blending-options.h | 129 + dali/internal/common/buffer-index.h | 33 + dali/internal/common/core-impl.cpp | 469 + dali/internal/common/core-impl.h | 320 + dali/internal/common/fixed-size-memory-pool.cpp | 181 + dali/internal/common/fixed-size-memory-pool.h | 109 + dali/internal/common/image-attributes.cpp | 247 + dali/internal/common/image-attributes.h | 312 + dali/internal/common/image-sampler.cpp | 129 + dali/internal/common/image-sampler.h | 68 + dali/internal/common/internal-constants.cpp | 27 + dali/internal/common/internal-constants.h | 36 + .../internal/common/memory-pool-object-allocator.h | 125 + dali/internal/common/message-buffer.cpp | 175 + dali/internal/common/message-buffer.h | 156 + dali/internal/common/message.h | 872 ++ dali/internal/common/owner-container.h | 178 + dali/internal/common/owner-pointer.h | 230 + dali/internal/common/shader-data.h | 167 + dali/internal/common/shader-saver.h | 60 + dali/internal/common/text-vertex-2d.h | 46 + dali/internal/common/type-abstraction-enums.h | 41 + dali/internal/common/type-abstraction.h | 102 + .../actor-attachment-declarations.h | 43 + .../actor-attachments/actor-attachment-impl.cpp | 66 + .../actor-attachments/actor-attachment-impl.h | 119 + .../actor-attachments/camera-attachment-impl.cpp | 333 + .../actor-attachments/camera-attachment-impl.h | 299 + .../actor-attachments/image-attachment-impl.cpp | 346 + .../actor-attachments/image-attachment-impl.h | 297 + .../renderable-attachment-impl.cpp | 56 + .../actor-attachments/renderable-attachment-impl.h | 99 + .../actor-attachments/renderer-attachment-impl.cpp | 85 + .../actor-attachments/renderer-attachment-impl.h | 120 + dali/internal/event/actors/actor-declarations.h | 46 + dali/internal/event/actors/actor-impl.cpp | 4113 +++++++++ dali/internal/event/actors/actor-impl.h | 1856 ++++ dali/internal/event/actors/camera-actor-impl.cpp | 802 ++ dali/internal/event/actors/camera-actor-impl.h | 288 + .../event/actors/custom-actor-internal.cpp | 54 + dali/internal/event/actors/custom-actor-internal.h | 273 + dali/internal/event/actors/image-actor-impl.cpp | 573 ++ dali/internal/event/actors/image-actor-impl.h | 364 + dali/internal/event/actors/layer-impl.cpp | 568 ++ dali/internal/event/actors/layer-impl.h | 338 + dali/internal/event/actors/layer-list.cpp | 263 + dali/internal/event/actors/layer-list.h | 167 + dali/internal/event/animation/animation-impl.cpp | 936 ++ dali/internal/event/animation/animation-impl.h | 481 ++ .../animation/animation-playlist-declarations.h | 39 + .../event/animation/animation-playlist.cpp | 109 + dali/internal/event/animation/animation-playlist.h | 108 + .../event/animation/animator-connector-base.h | 96 + dali/internal/event/animation/animator-connector.h | 370 + dali/internal/event/animation/constrainer.cpp | 114 + dali/internal/event/animation/constrainer.h | 174 + dali/internal/event/animation/constraint-base.cpp | 234 + dali/internal/event/animation/constraint-base.h | 238 + dali/internal/event/animation/constraint-impl.h | 578 ++ .../event/animation/constraint-source-impl.h | 78 + dali/internal/event/animation/key-frame-channel.h | 206 + dali/internal/event/animation/key-frames-impl.cpp | 164 + dali/internal/event/animation/key-frames-impl.h | 358 + .../event/animation/linear-constrainer-impl.cpp | 227 + .../event/animation/linear-constrainer-impl.h | 257 + .../event/animation/path-constrainer-impl.cpp | 260 + .../event/animation/path-constrainer-impl.h | 229 + dali/internal/event/animation/path-impl.cpp | 527 ++ dali/internal/event/animation/path-impl.h | 288 + dali/internal/event/animation/progress-value.h | 219 + .../event/animation/property-constraint-ptr.h | 41 + .../internal/event/animation/property-constraint.h | 221 + .../event/animation/property-input-accessor.h | 227 + .../event/animation/property-input-indexer.h | 167 + .../event/common/complete-notification-interface.h | 63 + dali/internal/event/common/connectable.h | 60 + dali/internal/event/common/demangler.cpp | 166 + dali/internal/event/common/demangler.h | 54 + .../event/common/event-thread-services.cpp | 32 + dali/internal/event/common/event-thread-services.h | 101 + .../internal/event/common/notification-manager.cpp | 194 + dali/internal/event/common/notification-manager.h | 102 + dali/internal/event/common/object-connector.h | 137 + dali/internal/event/common/object-impl-helper.h | 322 + dali/internal/event/common/object-impl.cpp | 1288 +++ dali/internal/event/common/object-impl.h | 556 ++ .../internal/event/common/object-registry-impl.cpp | 102 + dali/internal/event/common/object-registry-impl.h | 147 + dali/internal/event/common/projection.cpp | 115 + dali/internal/event/common/projection.h | 52 + .../internal/event/common/property-buffer-impl.cpp | 554 ++ dali/internal/event/common/property-buffer-impl.h | 283 + .../event/common/property-conditions-impl.cpp | 40 + .../event/common/property-conditions-impl.h | 106 + dali/internal/event/common/property-helper.h | 103 + dali/internal/event/common/property-input-impl.h | 387 + dali/internal/event/common/property-metadata.h | 260 + .../event/common/property-notification-impl.cpp | 243 + .../event/common/property-notification-impl.h | 225 + .../event/common/property-notification-manager.cpp | 80 + .../event/common/property-notification-manager.h | 95 + dali/internal/event/common/property-notifier.h | 75 + dali/internal/event/common/stage-def.h | 38 + dali/internal/event/common/stage-impl.cpp | 635 ++ dali/internal/event/common/stage-impl.h | 503 ++ dali/internal/event/common/system-overlay-impl.cpp | 152 + dali/internal/event/common/system-overlay-impl.h | 142 + .../internal/event/common/thread-local-storage.cpp | 123 + dali/internal/event/common/thread-local-storage.h | 165 + dali/internal/event/common/type-info-impl.cpp | 677 ++ dali/internal/event/common/type-info-impl.h | 318 + dali/internal/event/common/type-registry-impl.cpp | 316 + dali/internal/event/common/type-registry-impl.h | 222 + dali/internal/event/effects/shader-declarations.h | 37 + dali/internal/event/effects/shader-effect-impl.cpp | 515 ++ dali/internal/event/effects/shader-effect-impl.h | 240 + dali/internal/event/effects/shader-factory.cpp | 172 + dali/internal/event/effects/shader-factory.h | 113 + dali/internal/event/events/actor-gesture-data.cpp | 116 + dali/internal/event/events/actor-gesture-data.h | 104 + dali/internal/event/events/actor-observer.cpp | 126 + dali/internal/event/events/actor-observer.h | 128 + dali/internal/event/events/event-processor.cpp | 263 + dali/internal/event/events/event-processor.h | 107 + .../event/events/gesture-detector-impl.cpp | 253 + dali/internal/event/events/gesture-detector-impl.h | 266 + .../event/events/gesture-event-processor.cpp | 311 + .../event/events/gesture-event-processor.h | 258 + dali/internal/event/events/gesture-processor.cpp | 236 + dali/internal/event/events/gesture-processor.h | 175 + .../event/events/hit-test-algorithm-impl.cpp | 655 ++ .../event/events/hit-test-algorithm-impl.h | 147 + .../event/events/hover-event-processor.cpp | 422 + dali/internal/event/events/hover-event-processor.h | 91 + dali/internal/event/events/key-event-processor.cpp | 52 + dali/internal/event/events/key-event-processor.h | 79 + .../events/long-press-gesture-detector-impl.cpp | 178 + .../events/long-press-gesture-detector-impl.h | 193 + .../event/events/long-press-gesture-processor.cpp | 331 + .../event/events/long-press-gesture-processor.h | 144 + .../event/events/multi-point-event-util.cpp | 120 + .../internal/event/events/multi-point-event-util.h | 66 + .../event/events/pan-gesture-detector-impl.cpp | 603 ++ .../event/events/pan-gesture-detector-impl.h | 318 + .../event/events/pan-gesture-processor.cpp | 607 ++ dali/internal/event/events/pan-gesture-processor.h | 295 + .../event/events/pinch-gesture-detector-impl.cpp | 112 + .../event/events/pinch-gesture-detector-impl.h | 146 + .../event/events/pinch-gesture-processor.cpp | 272 + .../event/events/pinch-gesture-processor.h | 137 + .../event/events/tap-gesture-detector-impl.cpp | 183 + .../event/events/tap-gesture-detector-impl.h | 195 + .../event/events/tap-gesture-processor.cpp | 297 + dali/internal/event/events/tap-gesture-processor.h | 146 + .../event/events/touch-event-processor.cpp | 429 + dali/internal/event/events/touch-event-processor.h | 101 + .../event/events/wheel-event-processor.cpp | 164 + dali/internal/event/events/wheel-event-processor.h | 79 + dali/internal/event/images/atlas-impl.cpp | 292 + dali/internal/event/images/atlas-impl.h | 209 + dali/internal/event/images/bitmap-compressed.cpp | 75 + dali/internal/event/images/bitmap-compressed.h | 114 + dali/internal/event/images/bitmap-external.cpp | 60 + dali/internal/event/images/bitmap-external.h | 106 + dali/internal/event/images/bitmap-packed-pixel.cpp | 151 + dali/internal/event/images/bitmap-packed-pixel.h | 189 + dali/internal/event/images/buffer-image-impl.cpp | 231 + dali/internal/event/images/buffer-image-impl.h | 216 + .../event/images/context-recovery-interface.h | 71 + .../event/images/encoded-buffer-image-impl.cpp | 85 + .../event/images/encoded-buffer-image-impl.h | 106 + .../event/images/frame-buffer-image-impl.cpp | 134 + .../event/images/frame-buffer-image-impl.h | 124 + dali/internal/event/images/image-connector.cpp | 82 + dali/internal/event/images/image-connector.h | 88 + dali/internal/event/images/image-factory-cache.cpp | 83 + dali/internal/event/images/image-factory-cache.h | 134 + dali/internal/event/images/image-factory.cpp | 519 ++ dali/internal/event/images/image-factory.h | 245 + dali/internal/event/images/image-impl.cpp | 140 + dali/internal/event/images/image-impl.h | 191 + dali/internal/event/images/native-image-impl.cpp | 78 + dali/internal/event/images/native-image-impl.h | 91 + .../event/images/nine-patch-image-impl.cpp | 405 + dali/internal/event/images/nine-patch-image-impl.h | 160 + dali/internal/event/images/resource-image-impl.cpp | 332 + dali/internal/event/images/resource-image-impl.h | 220 + .../event/object/custom-object-internal.cpp | 136 + .../internal/event/object/custom-object-internal.h | 137 + .../event/render-tasks/render-task-defaults.h | 61 + .../event/render-tasks/render-task-impl.cpp | 827 ++ .../internal/event/render-tasks/render-task-impl.h | 467 + .../event/render-tasks/render-task-list-impl.cpp | 219 + .../event/render-tasks/render-task-list-impl.h | 194 + dali/internal/event/rendering/geometry-impl.cpp | 430 + dali/internal/event/rendering/geometry-impl.h | 254 + dali/internal/event/rendering/material-impl.cpp | 596 ++ dali/internal/event/rendering/material-impl.h | 309 + dali/internal/event/rendering/renderer-impl.cpp | 283 + dali/internal/event/rendering/renderer-impl.h | 237 + dali/internal/event/rendering/sampler-impl.cpp | 378 + dali/internal/event/rendering/sampler-impl.h | 235 + dali/internal/event/rendering/shader-impl.cpp | 283 + dali/internal/event/rendering/shader-impl.h | 190 + dali/internal/event/resources/archive.cpp | 522 ++ dali/internal/event/resources/archive.h | 283 + dali/internal/event/resources/image-ticket.cpp | 45 + dali/internal/event/resources/image-ticket.h | 124 + .../event/resources/resource-client-declarations.h | 40 + dali/internal/event/resources/resource-client.cpp | 490 ++ dali/internal/event/resources/resource-client.h | 317 + .../resources/resource-ticket-lifetime-observer.h | 48 + .../event/resources/resource-ticket-observer.h | 64 + dali/internal/event/resources/resource-ticket.cpp | 171 + dali/internal/event/resources/resource-ticket.h | 167 + .../event/resources/resource-type-path.cpp | 141 + dali/internal/event/resources/resource-type-path.h | 91 + .../memory-pool-relayout-container.cpp | 107 + .../memory-pool-relayout-container.h | 123 + .../size-negotiation/relayout-controller-impl.cpp | 529 ++ .../size-negotiation/relayout-controller-impl.h | 231 + dali/internal/file.list | 175 + dali/internal/render/common/culling-algorithms.cpp | 161 + dali/internal/render/common/culling-algorithms.h | 46 + dali/internal/render/common/performance-monitor.h | 73 + .../common/post-process-resource-dispatcher.h | 56 + dali/internal/render/common/render-algorithms.cpp | 255 + dali/internal/render/common/render-algorithms.h | 62 + dali/internal/render/common/render-debug.cpp | 158 + dali/internal/render/common/render-debug.h | 127 + .../render/common/render-instruction-container.cpp | 88 + .../render/common/render-instruction-container.h | 93 + dali/internal/render/common/render-instruction.cpp | 138 + dali/internal/render/common/render-instruction.h | 156 + dali/internal/render/common/render-item.cpp | 84 + dali/internal/render/common/render-item.h | 132 + dali/internal/render/common/render-list.h | 329 + dali/internal/render/common/render-manager.cpp | 588 ++ dali/internal/render/common/render-manager.h | 268 + dali/internal/render/common/render-tracker-debug.h | 48 + dali/internal/render/common/render-tracker.cpp | 102 + dali/internal/render/common/render-tracker.h | 90 + dali/internal/render/common/rendering-types.h | 72 + .../render/common/texture-cache-dispatcher.cpp | 52 + .../render/common/texture-cache-dispatcher.h | 183 + dali/internal/render/common/uv-rect.h | 122 + dali/internal/render/common/vertex.h | 48 + .../render/data-providers/geometry-data-provider.h | 71 + .../render/data-providers/material-data-provider.h | 94 + .../render/data-providers/node-data-provider.h | 72 + .../data-providers/property-buffer-data-provider.h | 146 + .../render/data-providers/render-data-provider.cpp | 81 + .../render/data-providers/render-data-provider.h | 127 + .../render/data-providers/sampler-data-provider.h | 98 + .../data-providers/uniform-map-data-provider.h | 79 + .../render/gl-resources/bitmap-texture.cpp | 382 + dali/internal/render/gl-resources/bitmap-texture.h | 180 + .../gl-resources/compressed-bitmap-texture.cpp | 205 + .../gl-resources/compressed-bitmap-texture.h | 134 + dali/internal/render/gl-resources/context.cpp | 354 + dali/internal/render/gl-resources/context.h | 1829 ++++ .../gl-resources/frame-buffer-state-cache.cpp | 224 + .../render/gl-resources/frame-buffer-state-cache.h | 165 + .../render/gl-resources/frame-buffer-texture.cpp | 219 + .../render/gl-resources/frame-buffer-texture.h | 120 + .../internal/render/gl-resources/gl-call-debug.cpp | 82 + dali/internal/render/gl-resources/gl-call-debug.h | 64 + .../render/gl-resources/gl-resource-owner.h | 63 + dali/internal/render/gl-resources/gpu-buffer.cpp | 216 + dali/internal/render/gl-resources/gpu-buffer.h | 148 + .../gl-resources/native-frame-buffer-texture.cpp | 128 + .../gl-resources/native-frame-buffer-texture.h | 91 + .../render/gl-resources/native-texture.cpp | 130 + dali/internal/render/gl-resources/native-texture.h | 97 + .../internal/render/gl-resources/texture-cache.cpp | 607 ++ dali/internal/render/gl-resources/texture-cache.h | 332 + .../render/gl-resources/texture-declarations.h | 37 + .../render/gl-resources/texture-factory.cpp | 123 + .../internal/render/gl-resources/texture-factory.h | 97 + .../render/gl-resources/texture-observer.h | 48 + dali/internal/render/gl-resources/texture-units.h | 52 + dali/internal/render/gl-resources/texture.cpp | 305 + dali/internal/render/gl-resources/texture.h | 284 + dali/internal/render/queue/render-queue.cpp | 154 + dali/internal/render/queue/render-queue.h | 106 + dali/internal/render/renderers/render-geometry.cpp | 216 + dali/internal/render/renderers/render-geometry.h | 139 + .../renderers/render-renderer-property-buffer.cpp | 245 + .../renderers/render-renderer-property-buffer.h | 117 + dali/internal/render/renderers/render-renderer.cpp | 359 + dali/internal/render/renderers/render-renderer.h | 230 + .../renderers/scene-graph-image-renderer.cpp | 941 +++ .../render/renderers/scene-graph-image-renderer.h | 231 + .../renderers/scene-graph-renderer-debug.cpp | 118 + .../render/renderers/scene-graph-renderer-debug.h | 50 + .../renderers/scene-graph-renderer-declarations.h | 51 + .../render/renderers/scene-graph-renderer.cpp | 300 + .../render/renderers/scene-graph-renderer.h | 214 + dali/internal/render/shader-source/README | 18 + dali/internal/render/shader-source/image.txt | 44 + dali/internal/render/shaders/custom-uniform.cpp | 61 + dali/internal/render/shaders/custom-uniform.h | 79 + dali/internal/render/shaders/program-cache.h | 112 + .../internal/render/shaders/program-controller.cpp | 162 + dali/internal/render/shaders/program-controller.h | 193 + dali/internal/render/shaders/program.cpp | 712 ++ dali/internal/render/shaders/program.h | 374 + .../internal/render/shaders/scene-graph-shader.cpp | 462 + dali/internal/render/shaders/scene-graph-shader.h | 304 + dali/internal/render/shaders/uniform-meta.h | 110 + dali/internal/update/animation/property-accessor.h | 127 + .../update/animation/property-component-accessor.h | 403 + .../update/animation/scene-graph-animation.cpp | 307 + .../update/animation/scene-graph-animation.h | 451 + .../update/animation/scene-graph-animator.h | 1021 +++ .../animation/scene-graph-constraint-base.cpp | 86 + .../update/animation/scene-graph-constraint-base.h | 236 + .../scene-graph-constraint-declarations.h | 45 + .../update/animation/scene-graph-constraint.h | 175 + dali/internal/update/common/animatable-property.h | 2202 +++++ dali/internal/update/common/discard-queue.cpp | 194 + dali/internal/update/common/discard-queue.h | 171 + .../update/common/double-buffered-property.h | 376 + dali/internal/update/common/double-buffered.h | 229 + dali/internal/update/common/inherited-property.h | 703 ++ dali/internal/update/common/property-base.cpp | 42 + dali/internal/update/common/property-base.h | 91 + dali/internal/update/common/property-boolean.h | 131 + .../update/common/property-condition-functions.cpp | 394 + .../update/common/property-condition-functions.h | 383 + .../common/property-condition-step-functions.cpp | 141 + .../common/property-condition-step-functions.h | 118 + .../property-condition-variable-step-functions.cpp | 190 + .../property-condition-variable-step-functions.h | 123 + .../update/common/property-owner-messages.cpp | 44 + .../update/common/property-owner-messages.h | 364 + dali/internal/update/common/property-owner.cpp | 196 + dali/internal/update/common/property-owner.h | 253 + dali/internal/update/common/property-vector3.h | 135 + .../internal/update/common/scene-graph-buffers.cpp | 52 + dali/internal/update/common/scene-graph-buffers.h | 91 + .../scene-graph-connection-change-propagator.cpp | 85 + .../scene-graph-connection-change-propagator.h | 97 + .../update/common/scene-graph-property-buffer.cpp | 146 + .../update/common/scene-graph-property-buffer.h | 227 + .../common/scene-graph-property-notification.cpp | 191 + .../common/scene-graph-property-notification.h | 162 + dali/internal/update/common/uniform-map.cpp | 169 + dali/internal/update/common/uniform-map.h | 152 + .../controllers/render-message-dispatcher.cpp | 138 + .../update/controllers/render-message-dispatcher.h | 130 + .../update/controllers/scene-controller-impl.cpp | 53 + .../update/controllers/scene-controller-impl.h | 112 + .../internal/update/controllers/scene-controller.h | 106 + dali/internal/update/gestures/gesture-properties.h | 196 + .../update/gestures/pan-gesture-profiling.cpp | 55 + .../update/gestures/pan-gesture-profiling.h | 65 + .../update/gestures/scene-graph-pan-gesture.cpp | 1298 +++ .../update/gestures/scene-graph-pan-gesture.h | 588 ++ .../update/manager/object-owner-container.h | 146 + .../update/manager/prepare-render-algorithms.cpp | 88 + .../update/manager/prepare-render-algorithms.h | 55 + .../update/manager/prepare-render-instructions.cpp | 558 ++ .../update/manager/prepare-render-instructions.h | 96 + .../update/manager/process-render-tasks.cpp | 358 + .../internal/update/manager/process-render-tasks.h | 62 + dali/internal/update/manager/sorted-layers.h | 49 + dali/internal/update/manager/update-algorithms.cpp | 488 ++ dali/internal/update/manager/update-algorithms.h | 77 + .../update/manager/update-manager-debug.cpp | 146 + .../internal/update/manager/update-manager-debug.h | 47 + dali/internal/update/manager/update-manager.cpp | 1229 +++ dali/internal/update/manager/update-manager.h | 839 ++ .../node-attachment-declarations.h | 47 + .../update/node-attachments/node-attachment.cpp | 54 + .../update/node-attachments/node-attachment.h | 159 + .../scene-graph-camera-attachment.cpp | 575 ++ .../scene-graph-camera-attachment.h | 482 ++ .../scene-graph-image-attachment-debug.h | 49 + .../scene-graph-image-attachment.cpp | 499 ++ .../scene-graph-image-attachment.h | 403 + ...cene-graph-renderable-attachment-declarations.h | 44 + .../scene-graph-renderable-attachment.cpp | 265 + .../scene-graph-renderable-attachment.h | 311 + .../scene-graph-renderer-attachment.cpp | 512 ++ .../scene-graph-renderer-attachment.h | 283 + dali/internal/update/nodes/node-declarations.h | 49 + dali/internal/update/nodes/node-messages.cpp | 51 + dali/internal/update/nodes/node-messages.h | 250 + dali/internal/update/nodes/node.cpp | 293 + dali/internal/update/nodes/node.h | 1122 +++ dali/internal/update/nodes/scene-graph-layer.cpp | 107 + dali/internal/update/nodes/scene-graph-layer.h | 316 + .../internal/update/queue/update-message-queue.cpp | 290 + dali/internal/update/queue/update-message-queue.h | 130 + .../render-tasks/scene-graph-render-task-debug.h | 43 + .../render-tasks/scene-graph-render-task-list.cpp | 94 + .../render-tasks/scene-graph-render-task-list.h | 142 + .../render-tasks/scene-graph-render-task.cpp | 534 ++ .../update/render-tasks/scene-graph-render-task.h | 504 ++ .../update/rendering/scene-graph-geometry.cpp | 355 + .../update/rendering/scene-graph-geometry.h | 258 + .../update/rendering/scene-graph-material.cpp | 279 + .../update/rendering/scene-graph-material.h | 268 + .../update/rendering/scene-graph-sampler.cpp | 145 + .../update/rendering/scene-graph-sampler.h | 250 + dali/internal/update/resources/bitmap-metadata.cpp | 179 + dali/internal/update/resources/bitmap-metadata.h | 156 + .../resources/complete-status-manager-debug.h | 37 + .../update/resources/complete-status-manager.cpp | 156 + .../update/resources/complete-status-manager.h | 136 + .../resources/resource-manager-declarations.h | 59 + .../internal/update/resources/resource-manager.cpp | 695 ++ dali/internal/update/resources/resource-manager.h | 574 ++ .../update/resources/resource-tracker-debug.h | 47 + .../internal/update/resources/resource-tracker.cpp | 92 + dali/internal/update/resources/resource-tracker.h | 116 + .../update/resources/sync-resource-tracker.cpp | 97 + .../update/resources/sync-resource-tracker.h | 114 + dali/internal/update/touch/history.h | 296 + dali/internal/update/touch/touch-resampler.cpp | 350 + dali/internal/update/touch/touch-resampler.h | 135 + dali/public-api/actors/actor-enumerations.h | 138 + dali/public-api/actors/actor.cpp | 598 ++ dali/public-api/actors/actor.h | 1535 ++++ dali/public-api/actors/blending.cpp | 32 + dali/public-api/actors/blending.h | 106 + dali/public-api/actors/camera-actor.cpp | 166 + dali/public-api/actors/camera-actor.h | 369 + dali/public-api/actors/custom-actor-impl.cpp | 104 + dali/public-api/actors/custom-actor-impl.h | 446 + dali/public-api/actors/custom-actor.cpp | 103 + dali/public-api/actors/custom-actor.h | 133 + dali/public-api/actors/draw-mode.h | 53 + dali/public-api/actors/image-actor.cpp | 262 + dali/public-api/actors/image-actor.h | 562 ++ dali/public-api/actors/layer.cpp | 181 + dali/public-api/actors/layer.h | 438 + dali/public-api/actors/sampling.h | 53 + dali/public-api/animation/alpha-function.cpp | 76 + dali/public-api/animation/alpha-function.h | 172 + dali/public-api/animation/animation.cpp | 292 + dali/public-api/animation/animation.h | 646 ++ dali/public-api/animation/constraint-source.cpp | 59 + dali/public-api/animation/constraint-source.h | 142 + dali/public-api/animation/constraint.cpp | 239 + dali/public-api/animation/constraint.h | 543 ++ dali/public-api/animation/constraints.h | 247 + dali/public-api/animation/key-frames.cpp | 82 + dali/public-api/animation/key-frames.h | 150 + dali/public-api/animation/linear-constrainer.cpp | 74 + dali/public-api/animation/linear-constrainer.h | 153 + dali/public-api/animation/path.cpp | 98 + dali/public-api/animation/path.h | 201 + dali/public-api/animation/time-period.cpp | 40 + dali/public-api/animation/time-period.h | 69 + dali/public-api/common/compile-time-assert.h | 52 + dali/public-api/common/constants.cpp | 76 + dali/public-api/common/constants.h | 140 + dali/public-api/common/dali-common.cpp | 151 + dali/public-api/common/dali-common.h | 188 + dali/public-api/common/dali-vector.cpp | 168 + dali/public-api/common/dali-vector.h | 759 ++ dali/public-api/common/intrusive-ptr.h | 329 + dali/public-api/common/loading-state.h | 47 + dali/public-api/common/stage.cpp | 172 + dali/public-api/common/stage.h | 350 + dali/public-api/common/type-traits.h | 65 + dali/public-api/common/vector-wrapper.h | 47 + dali/public-api/common/view-mode.h | 45 + dali/public-api/dali-core-version.cpp | 49 + dali/public-api/dali-core-version.h | 32 + dali/public-api/dali-core.h | 128 + dali/public-api/events/gesture-detector.cpp | 81 + dali/public-api/events/gesture-detector.h | 166 + dali/public-api/events/gesture.cpp | 51 + dali/public-api/events/gesture.h | 132 + dali/public-api/events/hover-event.cpp | 52 + dali/public-api/events/hover-event.h | 106 + dali/public-api/events/key-event.cpp | 87 + dali/public-api/events/key-event.h | 154 + .../events/long-press-gesture-detector.cpp | 102 + .../events/long-press-gesture-detector.h | 228 + dali/public-api/events/long-press-gesture.cpp | 52 + dali/public-api/events/long-press-gesture.h | 102 + dali/public-api/events/pan-gesture-detector.cpp | 136 + dali/public-api/events/pan-gesture-detector.h | 354 + dali/public-api/events/pan-gesture.cpp | 89 + dali/public-api/events/pan-gesture.h | 189 + dali/public-api/events/pinch-gesture-detector.cpp | 67 + dali/public-api/events/pinch-gesture-detector.h | 157 + dali/public-api/events/pinch-gesture.cpp | 58 + dali/public-api/events/pinch-gesture.h | 108 + dali/public-api/events/tap-gesture-detector.cpp | 94 + dali/public-api/events/tap-gesture-detector.h | 215 + dali/public-api/events/tap-gesture.cpp | 55 + dali/public-api/events/tap-gesture.h | 101 + dali/public-api/events/touch-event.cpp | 52 + dali/public-api/events/touch-event.h | 106 + dali/public-api/events/touch-point.cpp | 44 + dali/public-api/events/touch-point.h | 135 + dali/public-api/events/wheel-event.cpp | 86 + dali/public-api/events/wheel-event.h | 152 + dali/public-api/file.list | 213 + dali/public-api/images/buffer-image.cpp | 140 + dali/public-api/images/buffer-image.h | 314 + dali/public-api/images/encoded-buffer-image.cpp | 80 + dali/public-api/images/encoded-buffer-image.h | 170 + dali/public-api/images/frame-buffer-image.cpp | 97 + dali/public-api/images/frame-buffer-image.h | 186 + dali/public-api/images/image-operations.h | 112 + dali/public-api/images/image.cpp | 76 + dali/public-api/images/image.h | 184 + dali/public-api/images/native-image-interface.h | 141 + dali/public-api/images/native-image.cpp | 67 + dali/public-api/images/native-image.h | 125 + dali/public-api/images/nine-patch-image.cpp | 82 + dali/public-api/images/nine-patch-image.h | 147 + dali/public-api/images/pixel.cpp | 200 + dali/public-api/images/pixel.h | 130 + dali/public-api/images/resource-image.cpp | 125 + dali/public-api/images/resource-image.h | 308 + dali/public-api/math/angle-axis.h | 89 + dali/public-api/math/compile-time-math.cpp | 72 + dali/public-api/math/compile-time-math.h | 176 + dali/public-api/math/degree.cpp | 32 + dali/public-api/math/degree.h | 122 + dali/public-api/math/math-utils.h | 330 + dali/public-api/math/matrix.cpp | 787 ++ dali/public-api/math/matrix.h | 411 + dali/public-api/math/matrix3.cpp | 289 + dali/public-api/math/matrix3.h | 246 + dali/public-api/math/quaternion.cpp | 552 ++ dali/public-api/math/quaternion.h | 491 ++ dali/public-api/math/radian.h | 326 + dali/public-api/math/random.h | 83 + dali/public-api/math/rect.h | 329 + dali/public-api/math/uint-16-pair.h | 203 + dali/public-api/math/vector2.cpp | 126 + dali/public-api/math/vector2.h | 520 ++ dali/public-api/math/vector3.cpp | 182 + dali/public-api/math/vector3.h | 614 ++ dali/public-api/math/vector4.cpp | 182 + dali/public-api/math/vector4.h | 617 ++ dali/public-api/math/viewport.h | 42 + dali/public-api/object/any.cpp | 88 + dali/public-api/object/any.h | 498 ++ dali/public-api/object/base-handle.cpp | 115 + dali/public-api/object/base-handle.h | 313 + dali/public-api/object/base-object.cpp | 118 + dali/public-api/object/base-object.h | 152 + dali/public-api/object/handle.cpp | 187 + dali/public-api/object/handle.h | 390 + dali/public-api/object/object-registry.cpp | 61 + dali/public-api/object/object-registry.h | 166 + dali/public-api/object/property-array.cpp | 105 + dali/public-api/object/property-array.h | 198 + dali/public-api/object/property-conditions.cpp | 130 + dali/public-api/object/property-conditions.h | 192 + dali/public-api/object/property-index-ranges.h | 67 + dali/public-api/object/property-input.cpp | 28 + dali/public-api/object/property-input.h | 160 + dali/public-api/object/property-map.cpp | 190 + dali/public-api/object/property-map.h | 225 + .../object/property-notification-declarations.h | 45 + dali/public-api/object/property-notification.cpp | 102 + dali/public-api/object/property-notification.h | 190 + dali/public-api/object/property-types.cpp | 61 + dali/public-api/object/property-types.h | 103 + dali/public-api/object/property-value.cpp | 862 ++ dali/public-api/object/property-value.h | 420 + dali/public-api/object/property.cpp | 64 + dali/public-api/object/property.h | 168 + dali/public-api/object/ref-object.cpp | 171 + dali/public-api/object/ref-object.h | 112 + dali/public-api/object/type-info.cpp | 110 + dali/public-api/object/type-info.h | 235 + dali/public-api/object/type-registry.cpp | 152 + dali/public-api/object/type-registry.h | 373 + dali/public-api/render-tasks/render-task-list.cpp | 77 + dali/public-api/render-tasks/render-task-list.h | 143 + dali/public-api/render-tasks/render-task.cpp | 248 + dali/public-api/render-tasks/render-task.h | 467 + dali/public-api/shader-effects/shader-effect.cpp | 119 + dali/public-api/shader-effects/shader-effect.h | 363 + dali/public-api/signals/base-signal.cpp | 335 + dali/public-api/signals/base-signal.h | 529 ++ dali/public-api/signals/callback.cpp | 106 + dali/public-api/signals/callback.h | 1778 ++++ .../signals/connection-tracker-interface.cpp | 32 + .../signals/connection-tracker-interface.h | 90 + dali/public-api/signals/connection-tracker.cpp | 90 + dali/public-api/signals/connection-tracker.h | 95 + dali/public-api/signals/dali-signal.h | 1491 ++++ dali/public-api/signals/functor-delegate.cpp | 63 + dali/public-api/signals/functor-delegate.h | 154 + .../public-api/signals/signal-slot-connections.cpp | 87 + dali/public-api/signals/signal-slot-connections.h | 165 + dali/public-api/signals/signal-slot-observers.cpp | 40 + dali/public-api/signals/signal-slot-observers.h | 102 + dali/public-api/signals/slot-delegate.h | 158 + .../size-negotiation/relayout-container.h | 66 + doc/dali_doc.h | 41 + docs/README | 4 + docs/api_footer.html | 2 + docs/coding-convention.html | 332 + docs/coding-style.html | 989 +++ docs/dali_internal.doxy | 1550 ++++ docs/templates/example-class-internal.cpp | 72 + docs/templates/example-class-internal.h | 155 + packaging/dali.spec | 137 + 877 files changed, 238528 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README create mode 100644 automated-tests/.gitignore create mode 100644 automated-tests/.gitignore-with-autogenerated-files create mode 100644 automated-tests/.gitignore-without-autogenerated-files create mode 100644 automated-tests/CMakeLists.txt create mode 100644 automated-tests/README.md create mode 100755 automated-tests/build.sh create mode 100755 automated-tests/coverage.sh create mode 100755 automated-tests/execute.sh create mode 100644 automated-tests/packaging/core-dali-tests.spec create mode 100755 automated-tests/scripts/add_all_smack_rule.sh create mode 100755 automated-tests/scripts/add_smack_rule.sh create mode 100755 automated-tests/scripts/add_style.pl create mode 100644 automated-tests/scripts/all_smack.rule create mode 100755 automated-tests/scripts/autocompletion.sh create mode 100755 automated-tests/scripts/init.sh create mode 100755 automated-tests/scripts/retriever.sh create mode 100755 automated-tests/scripts/summarize.pl create mode 100755 automated-tests/scripts/tcbuild.sh create mode 100755 automated-tests/scripts/tcheadgen.sh create mode 100755 automated-tests/scripts/tcpackageslistsgen.sh create mode 100755 automated-tests/scripts/tctestsgen.sh create mode 100644 automated-tests/src/CMakeLists.txt create mode 100644 automated-tests/src/common/assert.h create mode 100644 automated-tests/src/common/signal-helper.h create mode 100644 automated-tests/src/common/testcase.h create mode 100644 automated-tests/src/dali-devel/CMakeLists.txt create mode 100644 automated-tests/src/dali-devel/tct-dali-devel-core.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-Actor.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-Atlas.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-Constrainer.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-Context.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-CullFace.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-DistanceField.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-Geometry.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-Hash.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-HitTestAlgorithm.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-Material.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-Mutex.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-PropertyBuffer.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-Renderer.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-Sampler.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-Scripting.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-Shader.cpp create mode 100644 automated-tests/src/dali-devel/utc-Dali-WeakHandle.cpp create mode 100644 automated-tests/src/dali-internal/CMakeLists.txt create mode 100644 automated-tests/src/dali-internal/tct-dali-internal-core.cpp create mode 100644 automated-tests/src/dali-internal/utc-Dali-Internal-FixedSizeMemoryPool.cpp create mode 100644 automated-tests/src/dali-internal/utc-Dali-Internal-FrustumCulling.cpp create mode 100644 automated-tests/src/dali-internal/utc-Dali-Internal-Handles.cpp create mode 100644 automated-tests/src/dali-internal/utc-Dali-Internal-Image-Culling.cpp create mode 100644 automated-tests/src/dali-internal/utc-Dali-Internal-ImageFactory.cpp create mode 100644 automated-tests/src/dali-internal/utc-Dali-Internal-MemoryPoolObjectAllocator.cpp create mode 100644 automated-tests/src/dali-internal/utc-Dali-Internal-ResourceClient.cpp create mode 100644 automated-tests/src/dali/CMakeLists.txt create mode 100644 automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.cpp create mode 100644 automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.h create mode 100644 automated-tests/src/dali/dali-test-suite-utils/mesh-builder.cpp create mode 100644 automated-tests/src/dali/dali-test-suite-utils/mesh-builder.h create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-application.cpp create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-application.h create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.cpp create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.h create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.cpp create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.h create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-harness.cpp create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-harness.h create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-intrusive-ptr.h create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-native-image.cpp create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-native-image.h create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.cpp create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.h create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-render-controller.cpp create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-render-controller.h create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-touch-utils.h create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp create mode 100644 automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h create mode 100644 automated-tests/src/dali/tct-dali-core.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Actor.cpp create mode 100644 automated-tests/src/dali/utc-Dali-AlphaFunction.cpp create mode 100644 automated-tests/src/dali/utc-Dali-AngleAxis.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Animation.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Any.cpp create mode 100644 automated-tests/src/dali/utc-Dali-BaseHandle.cpp create mode 100644 automated-tests/src/dali/utc-Dali-BufferImage.cpp create mode 100644 automated-tests/src/dali/utc-Dali-CameraActor.cpp create mode 100644 automated-tests/src/dali/utc-Dali-ConnectionTracker.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Constrainer.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Constraint.cpp create mode 100644 automated-tests/src/dali/utc-Dali-ConstraintFunction.cpp create mode 100644 automated-tests/src/dali/utc-Dali-ConstraintSource.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Constraints.cpp create mode 100644 automated-tests/src/dali/utc-Dali-CustomActor.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Degree.cpp create mode 100644 automated-tests/src/dali/utc-Dali-EncodedBufferImage.cpp create mode 100644 automated-tests/src/dali/utc-Dali-FrameBufferImage.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Gesture.cpp create mode 100644 automated-tests/src/dali/utc-Dali-GestureDetector.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Handle.cpp create mode 100644 automated-tests/src/dali/utc-Dali-HoverProcessing.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Image.cpp create mode 100644 automated-tests/src/dali/utc-Dali-ImageActor.cpp create mode 100644 automated-tests/src/dali/utc-Dali-IntrusivePtr.cpp create mode 100644 automated-tests/src/dali/utc-Dali-KeyEvent.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Layer.cpp create mode 100644 automated-tests/src/dali/utc-Dali-LocklessBuffer.cpp create mode 100644 automated-tests/src/dali/utc-Dali-LongPressGesture.cpp create mode 100644 automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp create mode 100644 automated-tests/src/dali/utc-Dali-MathUtils.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Matrix.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Matrix3.cpp create mode 100644 automated-tests/src/dali/utc-Dali-MeshMaterial.cpp create mode 100644 automated-tests/src/dali/utc-Dali-NativeImage.cpp create mode 100644 automated-tests/src/dali/utc-Dali-NinePatchImages.cpp create mode 100644 automated-tests/src/dali/utc-Dali-ObjectRegistry.cpp create mode 100644 automated-tests/src/dali/utc-Dali-PanGesture.cpp create mode 100644 automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Path.cpp create mode 100644 automated-tests/src/dali/utc-Dali-PinchGesture.cpp create mode 100644 automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Pixel.cpp create mode 100644 automated-tests/src/dali/utc-Dali-PropertyArray.cpp create mode 100644 automated-tests/src/dali/utc-Dali-PropertyMap.cpp create mode 100644 automated-tests/src/dali/utc-Dali-PropertyNotification.cpp create mode 100644 automated-tests/src/dali/utc-Dali-PropertyTypes.cpp create mode 100644 automated-tests/src/dali/utc-Dali-PropertyValue.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Quaternion.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Radian.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Random.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Rect.cpp create mode 100644 automated-tests/src/dali/utc-Dali-RenderTask.cpp create mode 100644 automated-tests/src/dali/utc-Dali-RenderTaskList.cpp create mode 100644 automated-tests/src/dali/utc-Dali-ResourceImage.cpp create mode 100644 automated-tests/src/dali/utc-Dali-ShaderEffect.cpp create mode 100644 automated-tests/src/dali/utc-Dali-SignalTemplates.cpp create mode 100644 automated-tests/src/dali/utc-Dali-SignalTemplatesFunctors.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Stage.cpp create mode 100644 automated-tests/src/dali/utc-Dali-TapGesture.cpp create mode 100644 automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp create mode 100644 automated-tests/src/dali/utc-Dali-TouchEventCombiner.cpp create mode 100644 automated-tests/src/dali/utc-Dali-TouchProcessing.cpp create mode 100644 automated-tests/src/dali/utc-Dali-TypeRegistry.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Uint16Pair.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Vector.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Vector2.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Vector3.cpp create mode 100644 automated-tests/src/dali/utc-Dali-Vector4.cpp create mode 100644 automated-tests/src/dali/utc-Dali-WheelEvent.cpp create mode 100644 automated-tests/style/back_top.png create mode 100644 automated-tests/style/blue.jpg create mode 100644 automated-tests/style/gray.jpg create mode 100644 automated-tests/style/jquery.min.js create mode 100644 automated-tests/style/orange.jpg create mode 100644 automated-tests/style/popup.js create mode 100644 automated-tests/style/red.jpg create mode 100644 automated-tests/style/summary.xsl create mode 100644 automated-tests/style/testresult.xsl create mode 100644 automated-tests/style/tests.css create mode 120000 automated-tests/tcbuild create mode 100644 automated-tests/templates/tct-package/README create mode 100755 automated-tests/templates/tct-package/inst.sh create mode 100755 build/scripts/dali_env create mode 100755 build/scripts/generate-shader-strings.pl create mode 100644 build/tizen/.gitignore create mode 100644 build/tizen/Makefile.am create mode 100644 build/tizen/configure.ac create mode 100644 build/tizen/dali-core.pc.in create mode 100644 build/tizen/dali-core/Makefile.am create mode 100644 build/tizen/dali-core/linker-test.cpp create mode 100644 dali.manifest create mode 100644 dali/.gitignore create mode 100644 dali/devel-api/animation/path-constrainer.cpp create mode 100644 dali/devel-api/animation/path-constrainer.h create mode 100644 dali/devel-api/common/hash.cpp create mode 100644 dali/devel-api/common/hash.h create mode 100644 dali/devel-api/common/map-wrapper.h create mode 100644 dali/devel-api/common/mutex.cpp create mode 100644 dali/devel-api/common/mutex.h create mode 100644 dali/devel-api/common/ref-counted-dali-vector.h create mode 100644 dali/devel-api/common/set-wrapper.h create mode 100644 dali/devel-api/events/hit-test-algorithm.cpp create mode 100644 dali/devel-api/events/hit-test-algorithm.h create mode 100644 dali/devel-api/file.list create mode 100644 dali/devel-api/images/atlas.cpp create mode 100644 dali/devel-api/images/atlas.h create mode 100644 dali/devel-api/images/distance-field.cpp create mode 100644 dali/devel-api/images/distance-field.h create mode 100644 dali/devel-api/object/property-buffer.cpp create mode 100644 dali/devel-api/object/property-buffer.h create mode 100644 dali/devel-api/object/type-registry-helper.h create mode 100644 dali/devel-api/object/weak-handle.cpp create mode 100644 dali/devel-api/object/weak-handle.h create mode 100644 dali/devel-api/rendering/cull-face.cpp create mode 100644 dali/devel-api/rendering/cull-face.h create mode 100644 dali/devel-api/rendering/geometry.cpp create mode 100644 dali/devel-api/rendering/geometry.h create mode 100644 dali/devel-api/rendering/material.cpp create mode 100644 dali/devel-api/rendering/material.h create mode 100644 dali/devel-api/rendering/renderer.cpp create mode 100644 dali/devel-api/rendering/renderer.h create mode 100644 dali/devel-api/rendering/sampler.cpp create mode 100644 dali/devel-api/rendering/sampler.h create mode 100644 dali/devel-api/rendering/shader.cpp create mode 100644 dali/devel-api/rendering/shader.h create mode 100644 dali/devel-api/scripting/scripting.cpp create mode 100644 dali/devel-api/scripting/scripting.h create mode 100644 dali/integration-api/bitmap.cpp create mode 100644 dali/integration-api/bitmap.h create mode 100644 dali/integration-api/context-notifier.h create mode 100644 dali/integration-api/core.cpp create mode 100644 dali/integration-api/core.h create mode 100644 dali/integration-api/debug.cpp create mode 100644 dali/integration-api/debug.h create mode 100644 dali/integration-api/events/event.cpp create mode 100644 dali/integration-api/events/event.h create mode 100644 dali/integration-api/events/gesture-event.cpp create mode 100644 dali/integration-api/events/gesture-event.h create mode 100644 dali/integration-api/events/gesture-requests.h create mode 100644 dali/integration-api/events/hover-event-integ.cpp create mode 100644 dali/integration-api/events/hover-event-integ.h create mode 100644 dali/integration-api/events/key-event-integ.cpp create mode 100644 dali/integration-api/events/key-event-integ.h create mode 100644 dali/integration-api/events/long-press-gesture-event.cpp create mode 100644 dali/integration-api/events/long-press-gesture-event.h create mode 100644 dali/integration-api/events/multi-point-event-integ.cpp create mode 100644 dali/integration-api/events/multi-point-event-integ.h create mode 100644 dali/integration-api/events/pan-gesture-event.cpp create mode 100644 dali/integration-api/events/pan-gesture-event.h create mode 100644 dali/integration-api/events/pinch-gesture-event.cpp create mode 100644 dali/integration-api/events/pinch-gesture-event.h create mode 100644 dali/integration-api/events/tap-gesture-event.cpp create mode 100644 dali/integration-api/events/tap-gesture-event.h create mode 100644 dali/integration-api/events/touch-data.h create mode 100644 dali/integration-api/events/touch-event-combiner.cpp create mode 100644 dali/integration-api/events/touch-event-combiner.h create mode 100644 dali/integration-api/events/touch-event-integ.cpp create mode 100644 dali/integration-api/events/touch-event-integ.h create mode 100644 dali/integration-api/events/wheel-event-integ.cpp create mode 100644 dali/integration-api/events/wheel-event-integ.h create mode 100644 dali/integration-api/file.list create mode 100644 dali/integration-api/gesture-manager.h create mode 100644 dali/integration-api/gl-abstraction.h create mode 100644 dali/integration-api/gl-defines.h create mode 100644 dali/integration-api/gl-sync-abstraction.h create mode 100644 dali/integration-api/image-data.cpp create mode 100644 dali/integration-api/image-data.h create mode 100644 dali/integration-api/input-options.cpp create mode 100644 dali/integration-api/input-options.h create mode 100644 dali/integration-api/lockless-buffer.cpp create mode 100644 dali/integration-api/lockless-buffer.h create mode 100644 dali/integration-api/platform-abstraction.h create mode 100644 dali/integration-api/profiling.cpp create mode 100644 dali/integration-api/profiling.h create mode 100644 dali/integration-api/render-controller.h create mode 100644 dali/integration-api/resource-cache.h create mode 100644 dali/integration-api/resource-declarations.h create mode 100644 dali/integration-api/resource-policies.h create mode 100644 dali/integration-api/resource-request.h create mode 100644 dali/integration-api/resource-types.h create mode 100644 dali/integration-api/system-overlay.cpp create mode 100644 dali/integration-api/system-overlay.h create mode 100644 dali/internal/common/blending-options.cpp create mode 100644 dali/internal/common/blending-options.h create mode 100644 dali/internal/common/buffer-index.h create mode 100644 dali/internal/common/core-impl.cpp create mode 100644 dali/internal/common/core-impl.h create mode 100644 dali/internal/common/fixed-size-memory-pool.cpp create mode 100644 dali/internal/common/fixed-size-memory-pool.h create mode 100644 dali/internal/common/image-attributes.cpp create mode 100644 dali/internal/common/image-attributes.h create mode 100644 dali/internal/common/image-sampler.cpp create mode 100644 dali/internal/common/image-sampler.h create mode 100644 dali/internal/common/internal-constants.cpp create mode 100644 dali/internal/common/internal-constants.h create mode 100644 dali/internal/common/memory-pool-object-allocator.h create mode 100644 dali/internal/common/message-buffer.cpp create mode 100644 dali/internal/common/message-buffer.h create mode 100644 dali/internal/common/message.h create mode 100644 dali/internal/common/owner-container.h create mode 100644 dali/internal/common/owner-pointer.h create mode 100644 dali/internal/common/shader-data.h create mode 100644 dali/internal/common/shader-saver.h create mode 100644 dali/internal/common/text-vertex-2d.h create mode 100644 dali/internal/common/type-abstraction-enums.h create mode 100644 dali/internal/common/type-abstraction.h create mode 100644 dali/internal/event/actor-attachments/actor-attachment-declarations.h create mode 100644 dali/internal/event/actor-attachments/actor-attachment-impl.cpp create mode 100644 dali/internal/event/actor-attachments/actor-attachment-impl.h create mode 100644 dali/internal/event/actor-attachments/camera-attachment-impl.cpp create mode 100644 dali/internal/event/actor-attachments/camera-attachment-impl.h create mode 100644 dali/internal/event/actor-attachments/image-attachment-impl.cpp create mode 100644 dali/internal/event/actor-attachments/image-attachment-impl.h create mode 100644 dali/internal/event/actor-attachments/renderable-attachment-impl.cpp create mode 100644 dali/internal/event/actor-attachments/renderable-attachment-impl.h create mode 100644 dali/internal/event/actor-attachments/renderer-attachment-impl.cpp create mode 100644 dali/internal/event/actor-attachments/renderer-attachment-impl.h create mode 100644 dali/internal/event/actors/actor-declarations.h create mode 100644 dali/internal/event/actors/actor-impl.cpp create mode 100644 dali/internal/event/actors/actor-impl.h create mode 100644 dali/internal/event/actors/camera-actor-impl.cpp create mode 100644 dali/internal/event/actors/camera-actor-impl.h create mode 100644 dali/internal/event/actors/custom-actor-internal.cpp create mode 100644 dali/internal/event/actors/custom-actor-internal.h create mode 100644 dali/internal/event/actors/image-actor-impl.cpp create mode 100644 dali/internal/event/actors/image-actor-impl.h create mode 100644 dali/internal/event/actors/layer-impl.cpp create mode 100644 dali/internal/event/actors/layer-impl.h create mode 100644 dali/internal/event/actors/layer-list.cpp create mode 100644 dali/internal/event/actors/layer-list.h create mode 100644 dali/internal/event/animation/animation-impl.cpp create mode 100644 dali/internal/event/animation/animation-impl.h create mode 100644 dali/internal/event/animation/animation-playlist-declarations.h create mode 100644 dali/internal/event/animation/animation-playlist.cpp create mode 100644 dali/internal/event/animation/animation-playlist.h create mode 100644 dali/internal/event/animation/animator-connector-base.h create mode 100644 dali/internal/event/animation/animator-connector.h create mode 100644 dali/internal/event/animation/constrainer.cpp create mode 100644 dali/internal/event/animation/constrainer.h create mode 100644 dali/internal/event/animation/constraint-base.cpp create mode 100644 dali/internal/event/animation/constraint-base.h create mode 100644 dali/internal/event/animation/constraint-impl.h create mode 100644 dali/internal/event/animation/constraint-source-impl.h create mode 100644 dali/internal/event/animation/key-frame-channel.h create mode 100644 dali/internal/event/animation/key-frames-impl.cpp create mode 100644 dali/internal/event/animation/key-frames-impl.h create mode 100644 dali/internal/event/animation/linear-constrainer-impl.cpp create mode 100644 dali/internal/event/animation/linear-constrainer-impl.h create mode 100644 dali/internal/event/animation/path-constrainer-impl.cpp create mode 100644 dali/internal/event/animation/path-constrainer-impl.h create mode 100644 dali/internal/event/animation/path-impl.cpp create mode 100644 dali/internal/event/animation/path-impl.h create mode 100644 dali/internal/event/animation/progress-value.h create mode 100644 dali/internal/event/animation/property-constraint-ptr.h create mode 100644 dali/internal/event/animation/property-constraint.h create mode 100644 dali/internal/event/animation/property-input-accessor.h create mode 100644 dali/internal/event/animation/property-input-indexer.h create mode 100644 dali/internal/event/common/complete-notification-interface.h create mode 100644 dali/internal/event/common/connectable.h create mode 100644 dali/internal/event/common/demangler.cpp create mode 100644 dali/internal/event/common/demangler.h create mode 100644 dali/internal/event/common/event-thread-services.cpp create mode 100644 dali/internal/event/common/event-thread-services.h create mode 100644 dali/internal/event/common/notification-manager.cpp create mode 100644 dali/internal/event/common/notification-manager.h create mode 100644 dali/internal/event/common/object-connector.h create mode 100644 dali/internal/event/common/object-impl-helper.h create mode 100644 dali/internal/event/common/object-impl.cpp create mode 100644 dali/internal/event/common/object-impl.h create mode 100644 dali/internal/event/common/object-registry-impl.cpp create mode 100644 dali/internal/event/common/object-registry-impl.h create mode 100644 dali/internal/event/common/projection.cpp create mode 100644 dali/internal/event/common/projection.h create mode 100644 dali/internal/event/common/property-buffer-impl.cpp create mode 100644 dali/internal/event/common/property-buffer-impl.h create mode 100644 dali/internal/event/common/property-conditions-impl.cpp create mode 100644 dali/internal/event/common/property-conditions-impl.h create mode 100644 dali/internal/event/common/property-helper.h create mode 100644 dali/internal/event/common/property-input-impl.h create mode 100644 dali/internal/event/common/property-metadata.h create mode 100644 dali/internal/event/common/property-notification-impl.cpp create mode 100644 dali/internal/event/common/property-notification-impl.h create mode 100644 dali/internal/event/common/property-notification-manager.cpp create mode 100644 dali/internal/event/common/property-notification-manager.h create mode 100644 dali/internal/event/common/property-notifier.h create mode 100644 dali/internal/event/common/stage-def.h create mode 100644 dali/internal/event/common/stage-impl.cpp create mode 100644 dali/internal/event/common/stage-impl.h create mode 100644 dali/internal/event/common/system-overlay-impl.cpp create mode 100644 dali/internal/event/common/system-overlay-impl.h create mode 100644 dali/internal/event/common/thread-local-storage.cpp create mode 100644 dali/internal/event/common/thread-local-storage.h create mode 100644 dali/internal/event/common/type-info-impl.cpp create mode 100644 dali/internal/event/common/type-info-impl.h create mode 100644 dali/internal/event/common/type-registry-impl.cpp create mode 100644 dali/internal/event/common/type-registry-impl.h create mode 100644 dali/internal/event/effects/shader-declarations.h create mode 100644 dali/internal/event/effects/shader-effect-impl.cpp create mode 100644 dali/internal/event/effects/shader-effect-impl.h create mode 100644 dali/internal/event/effects/shader-factory.cpp create mode 100644 dali/internal/event/effects/shader-factory.h create mode 100644 dali/internal/event/events/actor-gesture-data.cpp create mode 100644 dali/internal/event/events/actor-gesture-data.h create mode 100644 dali/internal/event/events/actor-observer.cpp create mode 100644 dali/internal/event/events/actor-observer.h create mode 100644 dali/internal/event/events/event-processor.cpp create mode 100644 dali/internal/event/events/event-processor.h create mode 100644 dali/internal/event/events/gesture-detector-impl.cpp create mode 100644 dali/internal/event/events/gesture-detector-impl.h create mode 100644 dali/internal/event/events/gesture-event-processor.cpp create mode 100644 dali/internal/event/events/gesture-event-processor.h create mode 100644 dali/internal/event/events/gesture-processor.cpp create mode 100644 dali/internal/event/events/gesture-processor.h create mode 100644 dali/internal/event/events/hit-test-algorithm-impl.cpp create mode 100644 dali/internal/event/events/hit-test-algorithm-impl.h create mode 100644 dali/internal/event/events/hover-event-processor.cpp create mode 100644 dali/internal/event/events/hover-event-processor.h create mode 100644 dali/internal/event/events/key-event-processor.cpp create mode 100644 dali/internal/event/events/key-event-processor.h create mode 100644 dali/internal/event/events/long-press-gesture-detector-impl.cpp create mode 100644 dali/internal/event/events/long-press-gesture-detector-impl.h create mode 100644 dali/internal/event/events/long-press-gesture-processor.cpp create mode 100644 dali/internal/event/events/long-press-gesture-processor.h create mode 100644 dali/internal/event/events/multi-point-event-util.cpp create mode 100644 dali/internal/event/events/multi-point-event-util.h create mode 100644 dali/internal/event/events/pan-gesture-detector-impl.cpp create mode 100644 dali/internal/event/events/pan-gesture-detector-impl.h create mode 100644 dali/internal/event/events/pan-gesture-processor.cpp create mode 100644 dali/internal/event/events/pan-gesture-processor.h create mode 100644 dali/internal/event/events/pinch-gesture-detector-impl.cpp create mode 100644 dali/internal/event/events/pinch-gesture-detector-impl.h create mode 100644 dali/internal/event/events/pinch-gesture-processor.cpp create mode 100644 dali/internal/event/events/pinch-gesture-processor.h create mode 100644 dali/internal/event/events/tap-gesture-detector-impl.cpp create mode 100644 dali/internal/event/events/tap-gesture-detector-impl.h create mode 100644 dali/internal/event/events/tap-gesture-processor.cpp create mode 100644 dali/internal/event/events/tap-gesture-processor.h create mode 100644 dali/internal/event/events/touch-event-processor.cpp create mode 100644 dali/internal/event/events/touch-event-processor.h create mode 100644 dali/internal/event/events/wheel-event-processor.cpp create mode 100644 dali/internal/event/events/wheel-event-processor.h create mode 100644 dali/internal/event/images/atlas-impl.cpp create mode 100644 dali/internal/event/images/atlas-impl.h create mode 100644 dali/internal/event/images/bitmap-compressed.cpp create mode 100644 dali/internal/event/images/bitmap-compressed.h create mode 100644 dali/internal/event/images/bitmap-external.cpp create mode 100644 dali/internal/event/images/bitmap-external.h create mode 100644 dali/internal/event/images/bitmap-packed-pixel.cpp create mode 100644 dali/internal/event/images/bitmap-packed-pixel.h create mode 100644 dali/internal/event/images/buffer-image-impl.cpp create mode 100644 dali/internal/event/images/buffer-image-impl.h create mode 100644 dali/internal/event/images/context-recovery-interface.h create mode 100644 dali/internal/event/images/encoded-buffer-image-impl.cpp create mode 100644 dali/internal/event/images/encoded-buffer-image-impl.h create mode 100644 dali/internal/event/images/frame-buffer-image-impl.cpp create mode 100644 dali/internal/event/images/frame-buffer-image-impl.h create mode 100644 dali/internal/event/images/image-connector.cpp create mode 100644 dali/internal/event/images/image-connector.h create mode 100644 dali/internal/event/images/image-factory-cache.cpp create mode 100644 dali/internal/event/images/image-factory-cache.h create mode 100644 dali/internal/event/images/image-factory.cpp create mode 100644 dali/internal/event/images/image-factory.h create mode 100644 dali/internal/event/images/image-impl.cpp create mode 100644 dali/internal/event/images/image-impl.h create mode 100644 dali/internal/event/images/native-image-impl.cpp create mode 100644 dali/internal/event/images/native-image-impl.h create mode 100644 dali/internal/event/images/nine-patch-image-impl.cpp create mode 100644 dali/internal/event/images/nine-patch-image-impl.h create mode 100644 dali/internal/event/images/resource-image-impl.cpp create mode 100644 dali/internal/event/images/resource-image-impl.h create mode 100644 dali/internal/event/object/custom-object-internal.cpp create mode 100644 dali/internal/event/object/custom-object-internal.h create mode 100644 dali/internal/event/render-tasks/render-task-defaults.h create mode 100644 dali/internal/event/render-tasks/render-task-impl.cpp create mode 100644 dali/internal/event/render-tasks/render-task-impl.h create mode 100644 dali/internal/event/render-tasks/render-task-list-impl.cpp create mode 100644 dali/internal/event/render-tasks/render-task-list-impl.h create mode 100644 dali/internal/event/rendering/geometry-impl.cpp create mode 100644 dali/internal/event/rendering/geometry-impl.h create mode 100644 dali/internal/event/rendering/material-impl.cpp create mode 100644 dali/internal/event/rendering/material-impl.h create mode 100644 dali/internal/event/rendering/renderer-impl.cpp create mode 100644 dali/internal/event/rendering/renderer-impl.h create mode 100644 dali/internal/event/rendering/sampler-impl.cpp create mode 100644 dali/internal/event/rendering/sampler-impl.h create mode 100644 dali/internal/event/rendering/shader-impl.cpp create mode 100644 dali/internal/event/rendering/shader-impl.h create mode 100644 dali/internal/event/resources/archive.cpp create mode 100644 dali/internal/event/resources/archive.h create mode 100644 dali/internal/event/resources/image-ticket.cpp create mode 100644 dali/internal/event/resources/image-ticket.h create mode 100644 dali/internal/event/resources/resource-client-declarations.h create mode 100644 dali/internal/event/resources/resource-client.cpp create mode 100644 dali/internal/event/resources/resource-client.h create mode 100644 dali/internal/event/resources/resource-ticket-lifetime-observer.h create mode 100644 dali/internal/event/resources/resource-ticket-observer.h create mode 100644 dali/internal/event/resources/resource-ticket.cpp create mode 100644 dali/internal/event/resources/resource-ticket.h create mode 100644 dali/internal/event/resources/resource-type-path.cpp create mode 100644 dali/internal/event/resources/resource-type-path.h create mode 100644 dali/internal/event/size-negotiation/memory-pool-relayout-container.cpp create mode 100644 dali/internal/event/size-negotiation/memory-pool-relayout-container.h create mode 100644 dali/internal/event/size-negotiation/relayout-controller-impl.cpp create mode 100644 dali/internal/event/size-negotiation/relayout-controller-impl.h create mode 100644 dali/internal/file.list create mode 100644 dali/internal/render/common/culling-algorithms.cpp create mode 100644 dali/internal/render/common/culling-algorithms.h create mode 100644 dali/internal/render/common/performance-monitor.h create mode 100644 dali/internal/render/common/post-process-resource-dispatcher.h create mode 100644 dali/internal/render/common/render-algorithms.cpp create mode 100644 dali/internal/render/common/render-algorithms.h create mode 100644 dali/internal/render/common/render-debug.cpp create mode 100644 dali/internal/render/common/render-debug.h create mode 100644 dali/internal/render/common/render-instruction-container.cpp create mode 100644 dali/internal/render/common/render-instruction-container.h create mode 100644 dali/internal/render/common/render-instruction.cpp create mode 100644 dali/internal/render/common/render-instruction.h create mode 100644 dali/internal/render/common/render-item.cpp create mode 100644 dali/internal/render/common/render-item.h create mode 100644 dali/internal/render/common/render-list.h create mode 100644 dali/internal/render/common/render-manager.cpp create mode 100644 dali/internal/render/common/render-manager.h create mode 100644 dali/internal/render/common/render-tracker-debug.h create mode 100644 dali/internal/render/common/render-tracker.cpp create mode 100644 dali/internal/render/common/render-tracker.h create mode 100644 dali/internal/render/common/rendering-types.h create mode 100644 dali/internal/render/common/texture-cache-dispatcher.cpp create mode 100644 dali/internal/render/common/texture-cache-dispatcher.h create mode 100644 dali/internal/render/common/uv-rect.h create mode 100644 dali/internal/render/common/vertex.h create mode 100644 dali/internal/render/data-providers/geometry-data-provider.h create mode 100644 dali/internal/render/data-providers/material-data-provider.h create mode 100644 dali/internal/render/data-providers/node-data-provider.h create mode 100644 dali/internal/render/data-providers/property-buffer-data-provider.h create mode 100644 dali/internal/render/data-providers/render-data-provider.cpp create mode 100644 dali/internal/render/data-providers/render-data-provider.h create mode 100644 dali/internal/render/data-providers/sampler-data-provider.h create mode 100644 dali/internal/render/data-providers/uniform-map-data-provider.h create mode 100644 dali/internal/render/gl-resources/bitmap-texture.cpp create mode 100644 dali/internal/render/gl-resources/bitmap-texture.h create mode 100644 dali/internal/render/gl-resources/compressed-bitmap-texture.cpp create mode 100644 dali/internal/render/gl-resources/compressed-bitmap-texture.h create mode 100644 dali/internal/render/gl-resources/context.cpp create mode 100644 dali/internal/render/gl-resources/context.h create mode 100644 dali/internal/render/gl-resources/frame-buffer-state-cache.cpp create mode 100644 dali/internal/render/gl-resources/frame-buffer-state-cache.h create mode 100644 dali/internal/render/gl-resources/frame-buffer-texture.cpp create mode 100644 dali/internal/render/gl-resources/frame-buffer-texture.h create mode 100644 dali/internal/render/gl-resources/gl-call-debug.cpp create mode 100644 dali/internal/render/gl-resources/gl-call-debug.h create mode 100644 dali/internal/render/gl-resources/gl-resource-owner.h create mode 100644 dali/internal/render/gl-resources/gpu-buffer.cpp create mode 100644 dali/internal/render/gl-resources/gpu-buffer.h create mode 100644 dali/internal/render/gl-resources/native-frame-buffer-texture.cpp create mode 100644 dali/internal/render/gl-resources/native-frame-buffer-texture.h create mode 100644 dali/internal/render/gl-resources/native-texture.cpp create mode 100644 dali/internal/render/gl-resources/native-texture.h create mode 100644 dali/internal/render/gl-resources/texture-cache.cpp create mode 100644 dali/internal/render/gl-resources/texture-cache.h create mode 100644 dali/internal/render/gl-resources/texture-declarations.h create mode 100644 dali/internal/render/gl-resources/texture-factory.cpp create mode 100644 dali/internal/render/gl-resources/texture-factory.h create mode 100644 dali/internal/render/gl-resources/texture-observer.h create mode 100644 dali/internal/render/gl-resources/texture-units.h create mode 100644 dali/internal/render/gl-resources/texture.cpp create mode 100644 dali/internal/render/gl-resources/texture.h create mode 100644 dali/internal/render/queue/render-queue.cpp create mode 100644 dali/internal/render/queue/render-queue.h create mode 100644 dali/internal/render/renderers/render-geometry.cpp create mode 100644 dali/internal/render/renderers/render-geometry.h create mode 100644 dali/internal/render/renderers/render-renderer-property-buffer.cpp create mode 100644 dali/internal/render/renderers/render-renderer-property-buffer.h create mode 100644 dali/internal/render/renderers/render-renderer.cpp create mode 100644 dali/internal/render/renderers/render-renderer.h create mode 100644 dali/internal/render/renderers/scene-graph-image-renderer.cpp create mode 100644 dali/internal/render/renderers/scene-graph-image-renderer.h create mode 100644 dali/internal/render/renderers/scene-graph-renderer-debug.cpp create mode 100644 dali/internal/render/renderers/scene-graph-renderer-debug.h create mode 100644 dali/internal/render/renderers/scene-graph-renderer-declarations.h create mode 100644 dali/internal/render/renderers/scene-graph-renderer.cpp create mode 100644 dali/internal/render/renderers/scene-graph-renderer.h create mode 100644 dali/internal/render/shader-source/README create mode 100644 dali/internal/render/shader-source/image.txt create mode 100644 dali/internal/render/shaders/custom-uniform.cpp create mode 100644 dali/internal/render/shaders/custom-uniform.h create mode 100644 dali/internal/render/shaders/program-cache.h create mode 100644 dali/internal/render/shaders/program-controller.cpp create mode 100644 dali/internal/render/shaders/program-controller.h create mode 100644 dali/internal/render/shaders/program.cpp create mode 100644 dali/internal/render/shaders/program.h create mode 100644 dali/internal/render/shaders/scene-graph-shader.cpp create mode 100644 dali/internal/render/shaders/scene-graph-shader.h create mode 100644 dali/internal/render/shaders/uniform-meta.h create mode 100644 dali/internal/update/animation/property-accessor.h create mode 100644 dali/internal/update/animation/property-component-accessor.h create mode 100644 dali/internal/update/animation/scene-graph-animation.cpp create mode 100644 dali/internal/update/animation/scene-graph-animation.h create mode 100644 dali/internal/update/animation/scene-graph-animator.h create mode 100644 dali/internal/update/animation/scene-graph-constraint-base.cpp create mode 100644 dali/internal/update/animation/scene-graph-constraint-base.h create mode 100644 dali/internal/update/animation/scene-graph-constraint-declarations.h create mode 100644 dali/internal/update/animation/scene-graph-constraint.h create mode 100644 dali/internal/update/common/animatable-property.h create mode 100644 dali/internal/update/common/discard-queue.cpp create mode 100644 dali/internal/update/common/discard-queue.h create mode 100644 dali/internal/update/common/double-buffered-property.h create mode 100644 dali/internal/update/common/double-buffered.h create mode 100644 dali/internal/update/common/inherited-property.h create mode 100644 dali/internal/update/common/property-base.cpp create mode 100644 dali/internal/update/common/property-base.h create mode 100644 dali/internal/update/common/property-boolean.h create mode 100644 dali/internal/update/common/property-condition-functions.cpp create mode 100644 dali/internal/update/common/property-condition-functions.h create mode 100644 dali/internal/update/common/property-condition-step-functions.cpp create mode 100644 dali/internal/update/common/property-condition-step-functions.h create mode 100644 dali/internal/update/common/property-condition-variable-step-functions.cpp create mode 100644 dali/internal/update/common/property-condition-variable-step-functions.h create mode 100644 dali/internal/update/common/property-owner-messages.cpp create mode 100644 dali/internal/update/common/property-owner-messages.h create mode 100644 dali/internal/update/common/property-owner.cpp create mode 100644 dali/internal/update/common/property-owner.h create mode 100644 dali/internal/update/common/property-vector3.h create mode 100644 dali/internal/update/common/scene-graph-buffers.cpp create mode 100644 dali/internal/update/common/scene-graph-buffers.h create mode 100644 dali/internal/update/common/scene-graph-connection-change-propagator.cpp create mode 100644 dali/internal/update/common/scene-graph-connection-change-propagator.h create mode 100644 dali/internal/update/common/scene-graph-property-buffer.cpp create mode 100644 dali/internal/update/common/scene-graph-property-buffer.h create mode 100644 dali/internal/update/common/scene-graph-property-notification.cpp create mode 100644 dali/internal/update/common/scene-graph-property-notification.h create mode 100644 dali/internal/update/common/uniform-map.cpp create mode 100644 dali/internal/update/common/uniform-map.h create mode 100644 dali/internal/update/controllers/render-message-dispatcher.cpp create mode 100644 dali/internal/update/controllers/render-message-dispatcher.h create mode 100644 dali/internal/update/controllers/scene-controller-impl.cpp create mode 100644 dali/internal/update/controllers/scene-controller-impl.h create mode 100644 dali/internal/update/controllers/scene-controller.h create mode 100644 dali/internal/update/gestures/gesture-properties.h create mode 100644 dali/internal/update/gestures/pan-gesture-profiling.cpp create mode 100644 dali/internal/update/gestures/pan-gesture-profiling.h create mode 100644 dali/internal/update/gestures/scene-graph-pan-gesture.cpp create mode 100644 dali/internal/update/gestures/scene-graph-pan-gesture.h create mode 100644 dali/internal/update/manager/object-owner-container.h create mode 100644 dali/internal/update/manager/prepare-render-algorithms.cpp create mode 100644 dali/internal/update/manager/prepare-render-algorithms.h create mode 100644 dali/internal/update/manager/prepare-render-instructions.cpp create mode 100644 dali/internal/update/manager/prepare-render-instructions.h create mode 100644 dali/internal/update/manager/process-render-tasks.cpp create mode 100644 dali/internal/update/manager/process-render-tasks.h create mode 100644 dali/internal/update/manager/sorted-layers.h create mode 100644 dali/internal/update/manager/update-algorithms.cpp create mode 100644 dali/internal/update/manager/update-algorithms.h create mode 100644 dali/internal/update/manager/update-manager-debug.cpp create mode 100644 dali/internal/update/manager/update-manager-debug.h create mode 100644 dali/internal/update/manager/update-manager.cpp create mode 100644 dali/internal/update/manager/update-manager.h create mode 100644 dali/internal/update/node-attachments/node-attachment-declarations.h create mode 100644 dali/internal/update/node-attachments/node-attachment.cpp create mode 100644 dali/internal/update/node-attachments/node-attachment.h create mode 100644 dali/internal/update/node-attachments/scene-graph-camera-attachment.cpp create mode 100644 dali/internal/update/node-attachments/scene-graph-camera-attachment.h create mode 100644 dali/internal/update/node-attachments/scene-graph-image-attachment-debug.h create mode 100644 dali/internal/update/node-attachments/scene-graph-image-attachment.cpp create mode 100644 dali/internal/update/node-attachments/scene-graph-image-attachment.h create mode 100644 dali/internal/update/node-attachments/scene-graph-renderable-attachment-declarations.h create mode 100644 dali/internal/update/node-attachments/scene-graph-renderable-attachment.cpp create mode 100644 dali/internal/update/node-attachments/scene-graph-renderable-attachment.h create mode 100644 dali/internal/update/node-attachments/scene-graph-renderer-attachment.cpp create mode 100644 dali/internal/update/node-attachments/scene-graph-renderer-attachment.h create mode 100644 dali/internal/update/nodes/node-declarations.h create mode 100644 dali/internal/update/nodes/node-messages.cpp create mode 100644 dali/internal/update/nodes/node-messages.h create mode 100644 dali/internal/update/nodes/node.cpp create mode 100644 dali/internal/update/nodes/node.h create mode 100644 dali/internal/update/nodes/scene-graph-layer.cpp create mode 100644 dali/internal/update/nodes/scene-graph-layer.h create mode 100644 dali/internal/update/queue/update-message-queue.cpp create mode 100644 dali/internal/update/queue/update-message-queue.h create mode 100644 dali/internal/update/render-tasks/scene-graph-render-task-debug.h create mode 100644 dali/internal/update/render-tasks/scene-graph-render-task-list.cpp create mode 100644 dali/internal/update/render-tasks/scene-graph-render-task-list.h create mode 100644 dali/internal/update/render-tasks/scene-graph-render-task.cpp create mode 100644 dali/internal/update/render-tasks/scene-graph-render-task.h create mode 100644 dali/internal/update/rendering/scene-graph-geometry.cpp create mode 100644 dali/internal/update/rendering/scene-graph-geometry.h create mode 100644 dali/internal/update/rendering/scene-graph-material.cpp create mode 100644 dali/internal/update/rendering/scene-graph-material.h create mode 100644 dali/internal/update/rendering/scene-graph-sampler.cpp create mode 100644 dali/internal/update/rendering/scene-graph-sampler.h create mode 100644 dali/internal/update/resources/bitmap-metadata.cpp create mode 100644 dali/internal/update/resources/bitmap-metadata.h create mode 100644 dali/internal/update/resources/complete-status-manager-debug.h create mode 100644 dali/internal/update/resources/complete-status-manager.cpp create mode 100644 dali/internal/update/resources/complete-status-manager.h create mode 100644 dali/internal/update/resources/resource-manager-declarations.h create mode 100644 dali/internal/update/resources/resource-manager.cpp create mode 100644 dali/internal/update/resources/resource-manager.h create mode 100644 dali/internal/update/resources/resource-tracker-debug.h create mode 100644 dali/internal/update/resources/resource-tracker.cpp create mode 100644 dali/internal/update/resources/resource-tracker.h create mode 100644 dali/internal/update/resources/sync-resource-tracker.cpp create mode 100644 dali/internal/update/resources/sync-resource-tracker.h create mode 100644 dali/internal/update/touch/history.h create mode 100644 dali/internal/update/touch/touch-resampler.cpp create mode 100644 dali/internal/update/touch/touch-resampler.h create mode 100644 dali/public-api/actors/actor-enumerations.h create mode 100644 dali/public-api/actors/actor.cpp create mode 100644 dali/public-api/actors/actor.h create mode 100644 dali/public-api/actors/blending.cpp create mode 100644 dali/public-api/actors/blending.h create mode 100644 dali/public-api/actors/camera-actor.cpp create mode 100644 dali/public-api/actors/camera-actor.h create mode 100644 dali/public-api/actors/custom-actor-impl.cpp create mode 100644 dali/public-api/actors/custom-actor-impl.h create mode 100644 dali/public-api/actors/custom-actor.cpp create mode 100644 dali/public-api/actors/custom-actor.h create mode 100644 dali/public-api/actors/draw-mode.h create mode 100644 dali/public-api/actors/image-actor.cpp create mode 100644 dali/public-api/actors/image-actor.h create mode 100644 dali/public-api/actors/layer.cpp create mode 100644 dali/public-api/actors/layer.h create mode 100644 dali/public-api/actors/sampling.h create mode 100644 dali/public-api/animation/alpha-function.cpp create mode 100644 dali/public-api/animation/alpha-function.h create mode 100644 dali/public-api/animation/animation.cpp create mode 100644 dali/public-api/animation/animation.h create mode 100644 dali/public-api/animation/constraint-source.cpp create mode 100644 dali/public-api/animation/constraint-source.h create mode 100644 dali/public-api/animation/constraint.cpp create mode 100644 dali/public-api/animation/constraint.h create mode 100644 dali/public-api/animation/constraints.h create mode 100644 dali/public-api/animation/key-frames.cpp create mode 100644 dali/public-api/animation/key-frames.h create mode 100644 dali/public-api/animation/linear-constrainer.cpp create mode 100644 dali/public-api/animation/linear-constrainer.h create mode 100644 dali/public-api/animation/path.cpp create mode 100644 dali/public-api/animation/path.h create mode 100644 dali/public-api/animation/time-period.cpp create mode 100644 dali/public-api/animation/time-period.h create mode 100644 dali/public-api/common/compile-time-assert.h create mode 100644 dali/public-api/common/constants.cpp create mode 100644 dali/public-api/common/constants.h create mode 100644 dali/public-api/common/dali-common.cpp create mode 100644 dali/public-api/common/dali-common.h create mode 100644 dali/public-api/common/dali-vector.cpp create mode 100644 dali/public-api/common/dali-vector.h create mode 100644 dali/public-api/common/intrusive-ptr.h create mode 100644 dali/public-api/common/loading-state.h create mode 100644 dali/public-api/common/stage.cpp create mode 100644 dali/public-api/common/stage.h create mode 100644 dali/public-api/common/type-traits.h create mode 100644 dali/public-api/common/vector-wrapper.h create mode 100644 dali/public-api/common/view-mode.h create mode 100644 dali/public-api/dali-core-version.cpp create mode 100644 dali/public-api/dali-core-version.h create mode 100644 dali/public-api/dali-core.h create mode 100644 dali/public-api/events/gesture-detector.cpp create mode 100644 dali/public-api/events/gesture-detector.h create mode 100644 dali/public-api/events/gesture.cpp create mode 100644 dali/public-api/events/gesture.h create mode 100644 dali/public-api/events/hover-event.cpp create mode 100644 dali/public-api/events/hover-event.h create mode 100644 dali/public-api/events/key-event.cpp create mode 100644 dali/public-api/events/key-event.h create mode 100644 dali/public-api/events/long-press-gesture-detector.cpp create mode 100644 dali/public-api/events/long-press-gesture-detector.h create mode 100644 dali/public-api/events/long-press-gesture.cpp create mode 100644 dali/public-api/events/long-press-gesture.h create mode 100644 dali/public-api/events/pan-gesture-detector.cpp create mode 100644 dali/public-api/events/pan-gesture-detector.h create mode 100644 dali/public-api/events/pan-gesture.cpp create mode 100644 dali/public-api/events/pan-gesture.h create mode 100644 dali/public-api/events/pinch-gesture-detector.cpp create mode 100644 dali/public-api/events/pinch-gesture-detector.h create mode 100644 dali/public-api/events/pinch-gesture.cpp create mode 100644 dali/public-api/events/pinch-gesture.h create mode 100644 dali/public-api/events/tap-gesture-detector.cpp create mode 100644 dali/public-api/events/tap-gesture-detector.h create mode 100644 dali/public-api/events/tap-gesture.cpp create mode 100644 dali/public-api/events/tap-gesture.h create mode 100644 dali/public-api/events/touch-event.cpp create mode 100644 dali/public-api/events/touch-event.h create mode 100644 dali/public-api/events/touch-point.cpp create mode 100644 dali/public-api/events/touch-point.h create mode 100644 dali/public-api/events/wheel-event.cpp create mode 100644 dali/public-api/events/wheel-event.h create mode 100644 dali/public-api/file.list create mode 100644 dali/public-api/images/buffer-image.cpp create mode 100644 dali/public-api/images/buffer-image.h create mode 100644 dali/public-api/images/encoded-buffer-image.cpp create mode 100644 dali/public-api/images/encoded-buffer-image.h create mode 100644 dali/public-api/images/frame-buffer-image.cpp create mode 100644 dali/public-api/images/frame-buffer-image.h create mode 100644 dali/public-api/images/image-operations.h create mode 100644 dali/public-api/images/image.cpp create mode 100644 dali/public-api/images/image.h create mode 100644 dali/public-api/images/native-image-interface.h create mode 100644 dali/public-api/images/native-image.cpp create mode 100644 dali/public-api/images/native-image.h create mode 100644 dali/public-api/images/nine-patch-image.cpp create mode 100644 dali/public-api/images/nine-patch-image.h create mode 100644 dali/public-api/images/pixel.cpp create mode 100644 dali/public-api/images/pixel.h create mode 100644 dali/public-api/images/resource-image.cpp create mode 100644 dali/public-api/images/resource-image.h create mode 100644 dali/public-api/math/angle-axis.h create mode 100644 dali/public-api/math/compile-time-math.cpp create mode 100644 dali/public-api/math/compile-time-math.h create mode 100644 dali/public-api/math/degree.cpp create mode 100644 dali/public-api/math/degree.h create mode 100644 dali/public-api/math/math-utils.h create mode 100644 dali/public-api/math/matrix.cpp create mode 100644 dali/public-api/math/matrix.h create mode 100644 dali/public-api/math/matrix3.cpp create mode 100644 dali/public-api/math/matrix3.h create mode 100644 dali/public-api/math/quaternion.cpp create mode 100644 dali/public-api/math/quaternion.h create mode 100644 dali/public-api/math/radian.h create mode 100644 dali/public-api/math/random.h create mode 100644 dali/public-api/math/rect.h create mode 100644 dali/public-api/math/uint-16-pair.h create mode 100644 dali/public-api/math/vector2.cpp create mode 100644 dali/public-api/math/vector2.h create mode 100644 dali/public-api/math/vector3.cpp create mode 100644 dali/public-api/math/vector3.h create mode 100644 dali/public-api/math/vector4.cpp create mode 100644 dali/public-api/math/vector4.h create mode 100644 dali/public-api/math/viewport.h create mode 100644 dali/public-api/object/any.cpp create mode 100644 dali/public-api/object/any.h create mode 100644 dali/public-api/object/base-handle.cpp create mode 100644 dali/public-api/object/base-handle.h create mode 100644 dali/public-api/object/base-object.cpp create mode 100644 dali/public-api/object/base-object.h create mode 100644 dali/public-api/object/handle.cpp create mode 100644 dali/public-api/object/handle.h create mode 100644 dali/public-api/object/object-registry.cpp create mode 100644 dali/public-api/object/object-registry.h create mode 100644 dali/public-api/object/property-array.cpp create mode 100644 dali/public-api/object/property-array.h create mode 100644 dali/public-api/object/property-conditions.cpp create mode 100644 dali/public-api/object/property-conditions.h create mode 100644 dali/public-api/object/property-index-ranges.h create mode 100644 dali/public-api/object/property-input.cpp create mode 100644 dali/public-api/object/property-input.h create mode 100644 dali/public-api/object/property-map.cpp create mode 100644 dali/public-api/object/property-map.h create mode 100644 dali/public-api/object/property-notification-declarations.h create mode 100644 dali/public-api/object/property-notification.cpp create mode 100644 dali/public-api/object/property-notification.h create mode 100644 dali/public-api/object/property-types.cpp create mode 100644 dali/public-api/object/property-types.h create mode 100644 dali/public-api/object/property-value.cpp create mode 100644 dali/public-api/object/property-value.h create mode 100644 dali/public-api/object/property.cpp create mode 100644 dali/public-api/object/property.h create mode 100644 dali/public-api/object/ref-object.cpp create mode 100644 dali/public-api/object/ref-object.h create mode 100644 dali/public-api/object/type-info.cpp create mode 100644 dali/public-api/object/type-info.h create mode 100644 dali/public-api/object/type-registry.cpp create mode 100644 dali/public-api/object/type-registry.h create mode 100644 dali/public-api/render-tasks/render-task-list.cpp create mode 100644 dali/public-api/render-tasks/render-task-list.h create mode 100644 dali/public-api/render-tasks/render-task.cpp create mode 100644 dali/public-api/render-tasks/render-task.h create mode 100644 dali/public-api/shader-effects/shader-effect.cpp create mode 100644 dali/public-api/shader-effects/shader-effect.h create mode 100644 dali/public-api/signals/base-signal.cpp create mode 100644 dali/public-api/signals/base-signal.h create mode 100644 dali/public-api/signals/callback.cpp create mode 100644 dali/public-api/signals/callback.h create mode 100644 dali/public-api/signals/connection-tracker-interface.cpp create mode 100644 dali/public-api/signals/connection-tracker-interface.h create mode 100644 dali/public-api/signals/connection-tracker.cpp create mode 100644 dali/public-api/signals/connection-tracker.h create mode 100644 dali/public-api/signals/dali-signal.h create mode 100644 dali/public-api/signals/functor-delegate.cpp create mode 100644 dali/public-api/signals/functor-delegate.h create mode 100644 dali/public-api/signals/signal-slot-connections.cpp create mode 100644 dali/public-api/signals/signal-slot-connections.h create mode 100644 dali/public-api/signals/signal-slot-observers.cpp create mode 100644 dali/public-api/signals/signal-slot-observers.h create mode 100644 dali/public-api/signals/slot-delegate.h create mode 100644 dali/public-api/size-negotiation/relayout-container.h create mode 100644 doc/dali_doc.h create mode 100644 docs/README create mode 100644 docs/api_footer.html create mode 100644 docs/coding-convention.html create mode 100644 docs/coding-style.html create mode 100644 docs/dali_internal.doxy create mode 100644 docs/templates/example-class-internal.cpp create mode 100644 docs/templates/example-class-internal.h create mode 100644 packaging/dali.spec diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..caf34e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +.cproject +.project +.settings +.directory +Makefile.in +Makefile +BROWSE +*~ +*.pc +*.o +*.o.d +*.lo +*.loT +*.la +*.so +*.orig +*.odt +*.fodt +*.test +*.example +*.a +*.apk +*.ap_ +*.class +*.classpath +*.dex +*.gcno +*.gcda +*.gcov +.deps +.libs +*.swp +*.creator +*.creator.user +/docs/generated/* +/build/tizen/doc +/build/tizen/.cov +/build/desktop +/packaging/home* diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..dc0510e --- /dev/null +++ b/LICENSE @@ -0,0 +1,70 @@ +Apache License + +Version 2.0, January 2004 + +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and +You must cause any modified files to carry prominent notices stating that You changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + +You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..d6d395a --- /dev/null +++ b/README @@ -0,0 +1,75 @@ +T.O.C. +====== + + 1. GBS Builds + 1.1. NON-SMACK Targets + 1.2. SMACK enabled Targets + 2. Building for Ubuntu desktop + 2.1. Minimum Requirements + 2.2. Creating a DALi Environment + 2.3. Building the Repository + + + +1. GBS Builds +============= + +1.1. NON-SMACK Targets +---------------------- + + gbs build -A [TARGET_ARCH] + +1.2. SMACK enabled Targets +-------------------------- + + gbs build -A [TARGET_ARCH] --define "%enable_dali_smack_rules 1" + + + +2. Building for Ubuntu desktop +============================== + +2.1. Minimum Requirements +------------------------ + + - Ubuntu 14.04 + +2.2. Creating a DALi Environment +------------------------------- + +To build for desktop first ensure ALL sources are selected: + - Go to Ubuntu Settings and then to "Software & Updates" + - In the "Ubuntu Software" tab, ensure ALL software sources are ticked + (This is required because we install some community-maintained free & open-source software) + +Then you can create a dali-env folder in your home folder with: + + dali-core/build/scripts/dali_env -c + +This will also download any dependencies that the dali repositories require. + +You can save the environment variables to a file: + + dali-env/opt/bin/dali_env -s > setenv + +This process only needs to be done once. + +Next source these variables: + + . setenv + +You will have to source these variables every time you open up a new terminal (or you can add to .bashrc if you prefer). + +2.3. Building the Repository +---------------------------- + +To build the repository enter the 'build/tizen' folder: + + cd dali-core/build/tizen + +Then run the following commands: + + autoreconf --install + ./configure --prefix=$DESKTOP_PREFIX + make install -j8 + diff --git a/automated-tests/.gitignore b/automated-tests/.gitignore new file mode 100644 index 0000000..39d9377 --- /dev/null +++ b/automated-tests/.gitignore @@ -0,0 +1,5 @@ +*.xml +build +build.log +tct*core.h +results_xml.* diff --git a/automated-tests/.gitignore-with-autogenerated-files b/automated-tests/.gitignore-with-autogenerated-files new file mode 100644 index 0000000..f039d8a --- /dev/null +++ b/automated-tests/.gitignore-with-autogenerated-files @@ -0,0 +1,4 @@ +*.xml +build +build.log +tct*core.h diff --git a/automated-tests/.gitignore-without-autogenerated-files b/automated-tests/.gitignore-without-autogenerated-files new file mode 100644 index 0000000..8f3f9e2 --- /dev/null +++ b/automated-tests/.gitignore-without-autogenerated-files @@ -0,0 +1,3 @@ +*.xml +build +build.log diff --git a/automated-tests/CMakeLists.txt b/automated-tests/CMakeLists.txt new file mode 100644 index 0000000..c27852a --- /dev/null +++ b/automated-tests/CMakeLists.txt @@ -0,0 +1,13 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(tct_coreapi_utc) + +INCLUDE(FindPkgConfig) +SET(BIN_DIR "/opt/usr/bin") + +INCLUDE_DIRECTORIES( + src/common +) + +ADD_SUBDIRECTORY(src) + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ") diff --git a/automated-tests/README.md b/automated-tests/README.md new file mode 100644 index 0000000..8db6f2c --- /dev/null +++ b/automated-tests/README.md @@ -0,0 +1,221 @@ +Testing environment {#auto_testing} +=================== + +The new test environment from Tizen is the Web-TCT test suite. This was written for testing web components, but can easily be used for testing Dali. + +Each of the DALi repositories, **dali-core**, **dali-adaptor** and **dali-toolkit**, have their own test suites under the `automated-tests` folder. Within the src folder are a number of secondary folders - these correspond to 'API' tests and internal (for desktop testing only) + +Installation +------------ + +There are usage instructions and installation instructions on the Tizen.org website [here](http://download.tizen.org/tct/2.2.1/Manual/Web_TCT_2.2.1_User_Guide_v1.0.pdf) + +These are device specific instructions, however, installing the test suite will also provide the relevant packages for running tests on Ubuntu ( follow the first block of quickstart instructions below ). + +If you are planning on running tests on device, then flash your handset with latest image, or turn off ssh: `set_usb_debug.sh --mtp-sdb` and plug it in, then follow the quickstart instructions repeated below. + +Quickstart +---------- + +For target or desktop testing: + + cd ~/Packages + wget http://download.tizen.org/tct/2.2.1/2.2.1_r1/web-tct_2.2.1_r1.tar.gz + sudo tar xzf web-tct_2.2.1_r1.tar.gz + cd web-tct_2.2.1_r1/tools + sudo -E ./tct-config-host.sh + + +If you are planning on running tests on device, then plug in your freshly flashed device and run the following commands: + + sudo apt-get install sdb + ./tct-config-device.sh + +**NOTE:** After flashing a handset, you will need to run this step of the installation again. + +Testing on desktop +================== + +Building libraries with coverage options +---------------------------------------- + +Building dali core: + + cd dali-core # the location of your dali-core repository + cd build/tizen + export CC=gcc + export CXX=g++ + git clean -fxd . # Only do this in the build folder + autoreconf --install + CXXFLAGS='-g -O0 --coverage' LDFLAGS='--coverage' ./configure --prefix=$DESKTOP_PREFIX --enable-debug + make -j8 install + +Repeat for dali-adaptor and toolkit. + +Note, you __must__ use a local build and not a distributed build, and you __must__ also build with debug enabled to allow *DALI_ASSERT_DEBUG* to trigger on wrong behaviour ( Which should always be a test case failure! ) + +Building the tests +------------------ + +Run the following commands: + + cd automated-tests + ./build.sh + +This will build dali and dali-internal test sets. + +Test sets can be built individually: + + ./build.sh dali + +They can also be built without regenerating test case scripts (Useful for quicker rebuilds) + + ./build.sh -n dali-internal + +Or without cleaning down the build area (Useful for fast build/run/debug cycles) + + ./build.sh -n -r dali-internal + + +Executing the tests +------------------- + +To execute tests, cd into automated-tests and run + + ./execute.sh + +This will execute dali and dali-internal test sets. Note that the output summary for the first will be printed before running the second. + +By default the tests execute in parallel, which is faster but does not produce a single output file (summary.xml). Use this to execute the tests in series: + + ./execute.sh -s + +To see the summary.xml results, execute the tests in series and open as follows: + + firefox --new-window summary.xml + +To see a list of all of the options: + + ./execute.sh -h + +To execute a subset of tests, you can run individual test sets, e.g. + + ./execute.sh dali + +To get coverage output, run + + ./coverage.sh + + +Testing on target +================= + +To build for target, first build and install dali-core, dali-adaptor and dali-toolkit, then build dali-capi without --keep-packs option. + +You will need to install libconfig-tiny-perl: + +sudo apt-get install libconfig-tiny-perl + +If you use a non-standard `GBS_ROOT` then you will need to edit the tcbuild script to match your configuration - change line 96 and add a -B option with your GBS-ROOT path (line 96 = `gbs build -A armv7l --spec core-$1-tests.spec --include-all --keep-packs` ). +To install on device from a non-standard GBS_ROOT, also modify line 28 (`RPM_DIR="$HOME/GBS-ROOT/local/repos/$PROFILE/armv7l/RPMS"`). + +For core Dali cd into automated-tests, and use: + +sudo ./tcbuild build dali + + sudo ./tcbuild build dali + ./tcbuild install dali + +For Dali Adaptor, cd into automated-tests, and use: + + sudo ./tcbuild build dali-adaptor + sudo ./tcbuild build dali-platform-abstraction + ./tcbuild install dali-adaptor + ./tcbuild install dali-platform-abstraction + +Ensure your handset's filesystem is writable: + + sdb shell su -c "change-booting-mode.sh --update" + +To execute tests, cd into automated-tests and run + + tct-mgr + +This will bring up the java test suite program. You should see the Plan pane with a list of all tests in. Select the tct-dali-core-tests. and you will be offered a dialog to choose a test plan: either create a new one or use temp. +Select dali test suite, and click Run, then "Create a new plan", and call it "Dali-Core" or some such. It will now run the dali-test suite. + +You can find the output files under /opt/tct/manager/result/ + + +Adding tests +============ + +To Managed API +-------------- + +If you are adding test cases for new or existing managed API (CAPI), you need to add your changes to the src/dali mirror, and copy your change to the managed test suite in core-api. You need to inform HQ of your update. + +For internal API +---------------- + +If you are adding tests for internal API, then this will only work on desktop, and you should add your tests to the src/dali-internal test suite. + +General +------- + +If you are adding test cases to existing files, then all you need to do is create functions with the method signature + + int UtcTestcase(void) + { + TestApplication application; + ... + END_TEST; + } + + +Note that **there must be no extra whitespace in the method signature** (i.e., it must violate our coding convention and follow __exactly__ this pattern: `int UtcDaliMyTestcaseName(void)`), as it's parsed by an awk script to auto-generate the testcase arrays in the main header file. + +You can contine to use the TET api, e.g. `tet_infoline`, `tet_result` and our test check methods `DALI_TEST_CHECK`, `DALI_TEST_EQUALS`, etc. + +If you need any non-test methods or variables, ensure they are wrapped in an anonymous namespace. + +If you are adding new test files, then you need to add the filename to the SET(TC_SOURCES... +section of CMakeLists.txt (this is also parsed by an awk script prior to building) + +Debugging +========= + +On desktop, you can debug the tests by running gdb on the test program: + + $ cd automated-tests + $ gdb build/src/dali/tct-dali-core + gdb> r + +replace `` with the name of the failing testcase. + +For example, using testcase UtcDaliNinePatch01 from the dali-core test suite: + + $ gdb build/src/dali/tct-dali-core + gdb> r UtcDaliNinePatch01 + + +On target, you can re-install the test RPM and associated debug RPMs manually using + + sdb push .rpm /tmp + +After installing the rpm and it's debug RPMs, you can find the executable in /opt/usr/bin/tct-dali-core. First ensure you have smack permissions set: + + chsmack -e "^" /usr/bin/gdb + chsmack -e "^" /opt/usr/bin/tct-dali-core/tct-dali-core + +then run it under gdb as above. + + +Troubleshooting +=============== + +If when running tct-mgr tests, if "Health-Check get" fails and leaves a white screen on the device, you will need to run `tct-config-device.sh` from your `web-tct/tools` directory (wherever you untarred it) and power cycle your handset. If that still fails, you can work-around the issue by running "`mkdir –p /opt/usr/media/Documents/tct/`" on target – you may also need to kill the getCapabilities app from App Manager on the handset) + +If the test results show that the test cases fail with "Undefined reference to XXX", it means you have probably failed to update the dali packages on target. + +If all the tests are failing then make sure that you have enabled the engineering mode on the target with the 'change-booting-mode.sh --update' command in sdb shell, as the tests may not have installed correctly diff --git a/automated-tests/build.sh b/automated-tests/build.sh new file mode 100755 index 0000000..7c7584b --- /dev/null +++ b/automated-tests/build.sh @@ -0,0 +1,50 @@ +#!/bin/bash + + +TEMP=`getopt -o rn --long rebuild,no-gen \ + -n 'genmake' -- "$@"` + +if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi + +# Note the quotes around `$TEMP': they are essential! +eval set -- "$TEMP" + +opt_rebuild=false +opt_generate=true + +while true ; do + case "$1" in + -r|--rebuild) opt_rebuild=true ; shift ;; + -n|--no-gen) opt_generate=false ; shift ;; + --) shift ; break ;; + *) shift ;; # Ignore + esac +done + +if [ false == $opt_rebuild -o ! -d "build" ] ; then + rm -rf build + mkdir build +fi + +function build +{ + if [ $opt_generate == true -o $opt_rebuild == false ] ; then + (cd src/$1; ../../scripts/tcheadgen.sh tct-$1-core.h) + if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi + fi + (cd build ; cmake .. -DMODULE=$1 ; make -j7 ) +} + +if [ -n "$1" ] ; then + echo BUILDING ONLY $1 + build $1 +else + for mod in `ls -1 src/ | grep -v CMakeList ` + do + if [ $mod != 'common' ] && [ $mod != 'manual' ]; then + echo BUILDING $mod + build $mod + if [ $? -ne 0 ]; then echo "Build failed" ; exit 1; fi + fi + done +fi diff --git a/automated-tests/coverage.sh b/automated-tests/coverage.sh new file mode 100755 index 0000000..c5fbed7 --- /dev/null +++ b/automated-tests/coverage.sh @@ -0,0 +1,30 @@ +#!/bin/bash + +( cd ../build/tizen ; make cov_data ) + +# From lcov version 1.10 onwards, branch coverage is off by default and earlier versions do not support the rc option +LCOV_OPTS=`if [ \`printf "\\\`lcov --version | cut -d' ' -f4\\\`\n1.10\n" | sort -V | head -n 1\` = 1.10 ] ; then echo "--rc lcov_branch_coverage=1" ; fi` + +for i in `find . -name "*.dir"` ; do + ( + cd $i + echo `pwd` + covs=( `ls *.gcda 2>/dev/null` ) + if [[ $? -eq 0 ]] + then + lcov $LCOV_OPTS --directory . -c -o dali.info + lcov $LCOV_OPTS --remove dali.info "/usr/include/*" "*/automated-tests/*" "*/dali-env/*" -o dali.info + if [ ! -s dali.info ] + then + rm -f dali.info + fi + fi + ) +done + +( + cd .. ; + genhtml $LCOV_OPTS -o build/tizen/doc/coverage `find . -name dali.info` +) + +echo "Coverage output: ../build/tizen/doc/coverage/index.html" diff --git a/automated-tests/execute.sh b/automated-tests/execute.sh new file mode 100755 index 0000000..04dbd1f --- /dev/null +++ b/automated-tests/execute.sh @@ -0,0 +1,106 @@ +#!/bin/bash + +TEMP=`getopt -o hsr --long help,serial,rerun -n 'execute.sh' -- "$@"` + +if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi + +# Note the quotes around `$TEMP': they are essential! +eval set -- "$TEMP" + +function usage +{ + echo -e "Usage: execute.sh\t\tExecute test cases from all modules in parallel" + echo -e " execute.sh \tExecute test cases from the given module in parallel" + echo -e " execute.sh -s\t\tExecute test cases in serial using Testkit-Lite" + echo -e " execute.sh -r\t\tExecute test cases in parallel, re-running failed test cases in serial afterwards" + echo -e " execute.sh \tFind and execute the given test case" + exit 2 +} + +opt_serial=0 +opt_rerun="" +while true ; do + case "$1" in + -h|--help) usage ;; + -s|--serial) opt_serial=1 ; shift ;; + -r|--rerun) opt_rerun="-r" ; shift ;; + --) shift; break;; + *) echo "Internal error $1!" ; exit 1 ;; + esac +done + +function execute +{ + scripts/tctestsgen.sh $1 `pwd` desktop $2 + testkit-lite -f `pwd`/tests.xml -o tct-${1}-core-tests.xml -A --comm localhost + scripts/add_style.pl $1 +} + + + +# Clean up old test results +rm -f tct*core-tests.xml + +# Clean up old coverage data +if [ -d ../build/tizen ] ; then + rm -f ../build/tizen/dali-core/.libs/*.gcda +fi + +find build \( -name "*.gcda" \) -exec rm '{}' \; + +ASCII_BOLD="\e[1m" +ASCII_RESET="\e[0m" + +if [ $opt_serial = 1 ] ; then + # Run all test case executables serially, create XML output + if [ -n "$1" ] ; then + execute $1 $* + else + for mod in `ls -1 src/ | grep -v CMakeList ` + do + if [ $mod != 'common' ] && [ $mod != 'manual' ]; then + + echo -ne "$ASCII_BOLD" + echo -e "Executing $mod$ASCII_RESET" + execute $mod $* + fi + done + fi + + scripts/summarize.pl +else + # if $1 is an executable filename, execute it· + + if [ -z "$1" ] ; then + # No arguments: + # Execute each test executable in turn, using parallel execution + for mod in `ls -1 src/ | grep -v CMakeList | grep -v common | grep -v manual` + do + echo -e "$ASCII_BOLD" + echo -e "Executing $mod$ASCII_RESET" + build/src/$mod/tct-$mod-core $opt_rerun + done + + elif [ -f "build/src/$1/tct-$1-core" ] ; then + # First argument is an executable filename - execute only that with any + # remaining arguments + module=$1 + shift; + build/src/$module/tct-$module-core $opt_rerun $* + + else + # First argument is not an executable. Is it a test case name? + # Try executing each executable with the test case name until success/known failure + for mod in `ls -1 src/ | grep -v CMakeList | grep -v common | grep -v manual` + do + output=`build/src/$mod/tct-$mod-core $1` + ret=$? + if [ $ret -ne 6 ] ; then + echo $output + if [ $ret -eq 0 ] ; then echo -e "\nPassed" ; fi + exit $ret + fi + done + echo $1 not found + fi +fi diff --git a/automated-tests/packaging/core-dali-tests.spec b/automated-tests/packaging/core-dali-tests.spec new file mode 100644 index 0000000..e5127bb --- /dev/null +++ b/automated-tests/packaging/core-dali-tests.spec @@ -0,0 +1,51 @@ +%define MODULE_NAME dali +%define MODULE_LIBNAME dali +Name: core-%{MODULE_NAME}-tests +Summary: Core API unit TC (%{name}) +Version: 0.1 +Release: 0 +Group: Development/Tools +License: Apache License, Version 2.0, Samsung Properietary +Source0: %{name}-%{version}.tar.gz +Requires: dali +BuildRequires: dali-integration-devel +BuildRequires: pkgconfig(dali-core) +BuildRequires: pkgconfig(dali) +BuildRequires: cmake + +%description +Core API unit TC (%{name}) + +%prep +%setup -q + +%build + +%define PREFIX "%{_libdir}/%{name}" + +export LDFLAGS+="-Wl,--rpath=%{PREFIX} -Wl,--as-needed" +cd automated-tests +cmake . -DMODULE="%{MODULE_NAME}" -DCMAKE_INSTALL_PREFIX=%{_prefix} + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +cd automated-tests +%make_install +mkdir -p %{buildroot}/opt/usr/share/license +cp %{_builddir}/%{name}-%{version}/LICENSE %{buildroot}/opt/usr/share/license/%{name} +mkdir -p %{buildroot}/tmp/ +cp %{_builddir}/%{name}-%{version}/automated-tests/scripts/add_all_smack_rule.sh %{buildroot}/tmp/ +cp %{_builddir}/%{name}-%{version}/automated-tests/scripts/all_smack.rule %{buildroot}/tmp/ + +%post + +%postun + + +%files +/opt/usr/bin/* +/opt/usr/share/license/%{name} +/tmp/add_all_smack_rule.sh +/tmp/all_smack.rule diff --git a/automated-tests/scripts/add_all_smack_rule.sh b/automated-tests/scripts/add_all_smack_rule.sh new file mode 100755 index 0000000..8efb158 --- /dev/null +++ b/automated-tests/scripts/add_all_smack_rule.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +SCRIPTDIR=`dirname $(readlink -f $0)` +SMACK_FILE=$SCRIPTDIR/all_smack.rule + +echo "" +echo "Add smack rule in $SMACK_FILE" +echo "===================================================" +echo "" + +while read rule; do + NO_BLANK=$(echo $rule | sed 's/ //g' | sed 's/ //g') + if [ ${#NO_BLANK} -lt 1 ]; then + echo "Blank" + continue + elif [ `echo $NO_BLANK|cut -c1-1` = '#' ]; then + echo "Comment" + continue + fi + + echo "echo \"$rule\" > /smack/load2" + echo "$rule" > /smack/load2 +done < $SMACK_FILE + +echo "===================================================" +echo "" diff --git a/automated-tests/scripts/add_smack_rule.sh b/automated-tests/scripts/add_smack_rule.sh new file mode 100755 index 0000000..22fe5ee --- /dev/null +++ b/automated-tests/scripts/add_smack_rule.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +SCRIPTDIR=`dirname $(readlink -f $0)` +SMACK_FILE=$SCRIPTDIR/all_smack.rule + +echo "" +echo "Add smack rule in $SMACK_FILE" +echo "===================================================" + +echo "sdb root on" +sdb root on + +while read rule; do + NO_BLANK=$(echo $rule | sed 's/ //g' | sed 's/ //g') + if [ ${#NO_BLANK} -lt 1 ]; then + #echo "Blank" + continue + elif [ `echo $NO_BLANK|cut -c1-1` = '#' ]; then + #echo "Comment" + continue + fi + + echo "sdb shell \"echo $rule > /smack/load2\"" + sdb shell "echo $rule > /smack/load2" +done < $SMACK_FILE + +echo "===================================================" +echo "" diff --git a/automated-tests/scripts/add_style.pl b/automated-tests/scripts/add_style.pl new file mode 100755 index 0000000..e958842 --- /dev/null +++ b/automated-tests/scripts/add_style.pl @@ -0,0 +1,30 @@ +#!/usr/bin/perl + +use strict; +use Encode; +use Getopt::Long; +use Cwd; + +my $pwd = getcwd; +my $MOD_NAME = $ARGV[0]; +my $results_xml = "tct-$MOD_NAME-core-tests.xml"; +my $results_out = "results_xml.$$"; + +# Copy $results_xml, writing new stylesheet line: +# Write as second line +open RESULTS, "<$results_xml" || die "Can't open $results_xml for reading:$!\n"; +open RESULTS_OUT, ">$results_out" || die "Can't open $results_out for writing:$!\n"; +my $fline = readline RESULTS; +print RESULTS_OUT $fline; +print RESULTS_OUT "\n"; +while() +{ + if( ! /xml-stylesheet/ ) + { + print RESULTS_OUT $_; + } +} +close RESULTS_OUT; +close RESULTS; +unlink $results_xml; +print `mv $results_out $results_xml`; diff --git a/automated-tests/scripts/all_smack.rule b/automated-tests/scripts/all_smack.rule new file mode 100644 index 0000000..93f2b67 --- /dev/null +++ b/automated-tests/scripts/all_smack.rule @@ -0,0 +1,28 @@ +# calendar-service +_ calendar-service::svc rwx + +# capi-appfw-application +_ alarm-server::alarm rw +_ aul::launch x +_ aul::terminate x + +# capi-network-bluetooth +_ bt-service::admin w +_ bt-service::manager w +_ bt-service::gap w +_ bt-service::spp w +_ bt:service::opp w + +# capi-network-nfc +_ nfc-manager rwx +_ nfc-manager::tag rwx +_ nfc-manager::p2p rwx +_ nfc-manager::admin rwx +_ nfc-manager::common rwx + +# capi-location-* +_ location::maps rw +_ location::client rw + +# libmdm +_ mdm-server::eas rw diff --git a/automated-tests/scripts/autocompletion.sh b/automated-tests/scripts/autocompletion.sh new file mode 100755 index 0000000..d952c73 --- /dev/null +++ b/automated-tests/scripts/autocompletion.sh @@ -0,0 +1,18 @@ +#!/bin/bash +if [ -z "$TC_PROJECT_DIR" ]; then + echo "CoreAPI project directory can't be found. `basename $0` exitting..." + exit 1 +fi + +_tcbuild () { + local cur + cur=${COMP_WORDS[$COMP_CWORD]} + if [ $COMP_CWORD -eq 1 ]; then + COMPREPLY=( $( compgen -W "addmod build install rmmod" -- $cur ) ) + else #if [ $COMP_CWORD -eq 2 ]; then + COMPREPLY=( $( cd $TC_PROJECT_DIR/src; compgen -d -X "common" -- $cur ) ) + fi + return 0 +} + +complete -F _tcbuild tcbuild diff --git a/automated-tests/scripts/init.sh b/automated-tests/scripts/init.sh new file mode 100755 index 0000000..1ccd9ea --- /dev/null +++ b/automated-tests/scripts/init.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +PROJECT_DIR="$(cd "$(dirname $0)" && cd .. && pwd)" + +ln -s $PROJECT_DIR/scripts/tcbuild.sh $PROJECT_DIR/tcbuild + +echo "" >> $HOME/.bashrc +echo "# CoreAPI-tests convenience helpers" >> $HOME/.bashrc +echo "export TC_PROJECT_DIR=\"$PROJECT_DIR\"" >> $HOME/.bashrc +echo "source $PROJECT_DIR/scripts/autocompletion.sh" >> $HOME/.bashrc diff --git a/automated-tests/scripts/retriever.sh b/automated-tests/scripts/retriever.sh new file mode 100755 index 0000000..c1d466d --- /dev/null +++ b/automated-tests/scripts/retriever.sh @@ -0,0 +1,212 @@ +#!/bin/bash + +USAGE=$(cat < 3, +# - argument doesn't begin with '-' and number of arguments is > 2 +if [[ ( "$1" == -* && ( ! "$1" =~ ^-(anum|mnum|f)$ || $# > 3 ) ) || ( "$1" != -* && $# > 2 ) ]]; then + echo -e "$USAGE" + exit 1 +fi + +# get directory from last argument (or assume current one) +if [[ ! "$1" =~ ^-(anum|mnum|f)$ ]]; then + DIR=${1:-.} +else + DIR=${2:-.} +fi + +# get filename from last argument +if [[ $# == 3 && -f $DIR/$3 ]] ; then + FILE=$3 +elif [[ $# == 2 && -f $DIR/$2 ]] ; then + FILE=$2 +fi + +#echo "Dir: $DIR File: $FILE" >& 2 + + +# populate $TC_FILES with files declared in CMakeLists.txt +if [[ -z $FILE ]]; then + get_tc_files $DIR + if [ $? != 0 ]; then + exit 1 + fi + echo "Got all files" >& 2 +else + TC_FILES="$DIR/$FILE" + echo "TC_FILES: $TC_FILES" >& 2 +fi + + + +# run appropriate subcommand +case "$1" in + -anum) + tc_anum $TC_FILES ;; + -mnum) + tc_mnum $TC_FILES ;; + -f) + tc_fullinfo $TC_FILES ;; + *) + tc_names $TC_FILES ;; +esac diff --git a/automated-tests/scripts/summarize.pl b/automated-tests/scripts/summarize.pl new file mode 100755 index 0000000..c90eb89 --- /dev/null +++ b/automated-tests/scripts/summarize.pl @@ -0,0 +1,109 @@ +#!/usr/bin/perl + +use strict; +use XML::Parser; +use Encode; +use Getopt::Long; +use Cwd; + +my $pwd = getcwd; +my $num_tests=0; +my $num_passes=0; +my $num_actual_passes=0; +my $text = ""; + +sub handle_start +{ + my ($p, $elt, %attrs) = @_; + + if($elt =~ /testcase/) + { + $num_tests++; + if($attrs{"result"} eq "PASS") + { + $num_passes++; + } + } + if($elt =~ /actual_result/) + { + $text = ""; + } +} + +sub handle_end +{ + my ($p, $elt) = @_; + if($elt =~ /actual_result/) + { + if($text eq "PASS") + { + $num_actual_passes++; + } + $text = ""; + } +} + +sub handle_char +{ + my ($p, $str) = @_; + $text .= $str; +} + +my($parser) = new XML::Parser(Handlers => {Start => \&handle_start, + End => \&handle_end, + Char => \&handle_char}); + + +# Write summary.xml: +open SUMMARY, ">summary.xml" || die "Can't open summary.xml for writing:$!\n"; +print SUMMARY << "EOS"; + + + + + + 2014-03-21_18_52_41 + 2014-03-21_18_57_54 + +EOS + +print "\n\nSummary of all tests:\n"; +my $output_files = `ls tct*core-tests.xml`; +my $file; +foreach $file (split /\s+/, $output_files ) +{ + $num_tests=0; + $num_passes=0; + $num_actual_passes=0; + $text = ""; + + $parser->parsefile($file); + + my $pass_rate = sprintf("%5.2f", $num_passes * 100.0 / $num_tests); + my $num_fails = $num_tests - $num_passes; + my $fail_rate = sprintf("%5.2f", $num_fails * 100.0 / $num_tests); + + my $suite_name = $file; + $suite_name =~ s/\.xml$//; + + print "$suite_name: $num_passes tests passed out of $num_tests ( $pass_rate% )\n"; + +print SUMMARY << "EOS2"; + + $num_tests + $num_passes + $pass_rate + $num_fails + $fail_rate + 0 + 0.00 + 0 + 0.00 + +EOS2 +} + +print SUMMARY "\n"; +close SUMMARY; + +print "Summary of results written to summary.xml\n"; diff --git a/automated-tests/scripts/tcbuild.sh b/automated-tests/scripts/tcbuild.sh new file mode 100755 index 0000000..b604675 --- /dev/null +++ b/automated-tests/scripts/tcbuild.sh @@ -0,0 +1,215 @@ +#!/bin/bash + +#---------- DEBUG_BEGIN ---------- +#ARG="-d" # debug-on flag, might be set as $1 +# keyprompt "introductory message" -- wait until any key pressed +function keyprompt { echo -ne "\n\e[1;31m$1 -- " && read -n 1 && echo -e "\n\e[0m"; } +# d_bp -- breakpoint at which user need to press any key to proceed +function d_bp { if [[ "$ARG" == "-d" ]]; then keyprompt "d >> Press any key"; fi } +# d_showVar VARNAME -- print bash variable name +function d_showVar { if [ "$ARG" == "-d" -a -n "$1" ]; then echo "d >> ${1} = ${!1}"; fi } +# d_print "message" -- print a debug message +function d_print { if [ "$ARG" == "-d" -a -n "$1" ]; then echo -e "d >> $1"; fi } +#---------- DEBUG_END ---------- + +PROJECT_DIR="$(cd "$(dirname $0)" && pwd)" +d_showVar PROJECT_DIR + +function gbs_profile { +perl -e " +use Config::Tiny; +my \$Config = Config::Tiny->read( \"\$ENV{HOME}/.gbs.conf\" ); +my \$profile = \$Config->{general}->{profile}; +\$profile =~ s/profile.//; +print \$profile;" +} + +PROFILE=`gbs_profile` +RPM_DIR="$HOME/GBS-ROOT/local/repos/$PROFILE/armv7l/RPMS" +d_showVar RPM_DIR + +function add_module { + # argument check + if [ -z "$1" ]; then echo "Usage: `basename $0` addmod [module_lib_name]"; exit 1; fi + + MODULE_NAME=$1 + d_showVar MODULE_NAME + MODULE_NAME_C=$(echo $MODULE_NAME | sed -e 's/-\([a-z]\)/\U\1/' -e 's/^\([a-z]\)/\U\1/') + d_showVar MODULE_NAME_C + MODULE_NAME_U=$(echo $MODULE_NAME | sed -e 's/-/_/') + d_showVar MODULE_NAME_U +# MODULE_LIBNAME=${2:-capi-$MODULE_NAME} + MODULE_LIBNAME=$1 + d_showVar MODULE_LIBNAME + + echo "Adding $MODULE_NAME module to project..." + d_bp + cd $PROJECT_DIR + # prepare .spec file + echo "-- Generating packaging/core-$MODULE_NAME-tests.spec file" + if [ ! -d packaging ]; then mkdir packaging; fi + sed -e "s:\[MODULE_NAME\]:$MODULE_NAME:g" -e "s:\[MODULE_LIBNAME\]:$MODULE_LIBNAME:g" \ + templates/core-\[module_name\]-tests.spec > packaging/core-$MODULE_NAME-tests.spec + # prepare src directory + mkdir src/$MODULE_NAME + echo "-- Generating src/$MODULE_NAME/CMakeLists.txt file" + sed -e "s:%{MODULE_NAME}:$MODULE_NAME:g" -e "s:%{MODULE_LIBNAME}:$MODULE_LIBNAME:g" \ + templates/src-directory/CMakeLists.txt > src/$MODULE_NAME/CMakeLists.txt + echo "-- Generating src/$MODULE_NAME/tct-$MODULE_NAME-core.c file" + sed -e "s:%{MODULE_NAME}:$MODULE_NAME:g" \ + templates/src-directory/tct-\[module_name\]-core.c > src/$MODULE_NAME/tct-$MODULE_NAME-core.c + echo "-- Generating src/$MODULE_NAME/utc-$MODULE_NAME.c file" + sed -e "s:%{MODULE_NAME_U}:$MODULE_NAME_U:g" -e "s:%{MODULE_NAME_C}:$MODULE_NAME_C:g" \ + templates/src-directory/utc-\[module_name\].c > src/$MODULE_NAME/utc-$MODULE_NAME.c + echo "Task finished successfully" +} + +function rm_module { + # argument check + if [ -z "$1" ]; then echo "Usage: `basename $0` rmmod "; exit 1; fi + + MODULE_NAME=$1 + d_showVar MODULE_NAME + + echo "Removing $MODULE_NAME module from project..." + d_bp + echo "---- Updating /opt/tct/packages/package_list.xml" + scripts/tcpackageslistsgen.sh $MODULE_NAME /opt/tct/packages/package_list.xml 1 + if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi + # echo "---- Updating test plans" + # scripts/tcpackageslistsgen.sh $MODULE_NAME /opt/tct/manager/plan/*.xml 1 + # if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi + + cd $PROJECT_DIR + echo "-- Removing packaging/core-$MODULE_NAME-tests.spec file" + rm packaging/core-$MODULE_NAME-tests.spec + echo "-- Removing src/$MODULE_NAME directory" + rm -r src/$MODULE_NAME + echo "Task finished successfully" +} + +function build { + if [ -n "$1" ]; then + (cd src/$1; ../../scripts/tcheadgen.sh tct-$1-core.h) + if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi + cp packaging/core-$1-tests.spec ../packaging + cp .gitignore-without-autogenerated-files .gitignore + gbs build -A armv7l --spec core-$1-tests.spec --include-all --keep-packs | \ + tee build.log | stdbuf -o0 sed -e 's/error:/\x1b[1;91m&\x1b[0m/' \ + -e 's/warning:/\x1b[93m&\x1b[0m/' + rm ../packaging/core-$1-tests.spec + cp .gitignore-with-autogenerated-files .gitignore + else + echo "Build requires a module name" + exit 1 + fi +} + +function inst { + if [ -z "$1" ] + then + for mod in `ls -1 src/ | grep -v CMakeLists` + do + + if [ $mod != 'common' ] && [ $mod != 'manual' ]; then + + PKG_NAME="core-$mod-tests" + d_showVar PKG_NAME + VER=$(cat packaging/$PKG_NAME.spec | awk '/^Version:/ { print $2; exit; }') + d_showVar VER + PKG_VNAME="$PKG_NAME-$VER" + d_showVar PKG_VNAME + PKG_FNAME="$PKG_VNAME-0.armv7l.rpm" + d_showVar PKG_FNAME + + if [ -f "$RPM_DIR/$PKG_FNAME" ] + then + inst $mod + echo "" + fi + fi + done + else + cd $PROJECT_DIR + # setting variables + MOD_NAME="$1" + d_showVar MOD_NAME + PKG_NAME="core-$MOD_NAME-tests" + d_showVar PKG_NAME + VER=$(cat packaging/$PKG_NAME.spec | awk '/^Version:/ { print $2; exit; }') + d_showVar VER + PKG_VNAME="$PKG_NAME-$VER" + d_showVar PKG_VNAME + PKG_FNAME="$PKG_VNAME-0.armv7l.rpm" + d_showVar PKG_FNAME + TCT_DIR="opt/tct-$MOD_NAME-core-tests" + d_showVar TCT_DIR + + echo "Deploying $MOD_NAME suite to tct-mgr..." + d_bp + # prepare tct directory and files + echo "-- Preparing suite .zip file..." + echo "---- Creating /tmp/$TCT_DIR directory" + rm -r /tmp/opt > /dev/null 2>&1 + mkdir -p /tmp/$TCT_DIR + # README + echo "---- Copying /tmp/$TCT_DIR" + cp templates/tct-package/README /tmp/$TCT_DIR + # rpm + echo "---- Copying /tmp/$TCT_DIR package" + cp $RPM_DIR/$PKG_FNAME /tmp/$TCT_DIR + if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi + # inst.sh + echo "---- Generating /tmp/$TCT_DIR/inst.sh file" + sed -e "s:%{PKG_NAME}:\"$PKG_NAME\":g" -e "s:%{PKG_FULLNAME}:\"$PKG_FNAME\":g" \ + -e "s:%{PKG_DIR}:\"/opt/usr/media/tct/$TCT_DIR\":g" \ + templates/tct-package/inst.sh > /tmp/$TCT_DIR/inst.sh + chmod a+x /tmp/$TCT_DIR/inst.sh + # tests.xml + echo "---- Generating /tmp/$TCT_DIR" + scripts/tctestsgen.sh $MOD_NAME /tmp/$TCT_DIR target + if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi + # zip + echo "---- Preparing /tmp/tct/packages/tct-$MOD_NAME-core-tests-2.2.1-1.zip file" + # clear old zips + rm -r /tmp/tct/packages > /dev/null 2>&1 + mkdir -p /tmp/tct/packages + # create new zip + ( cd /tmp; zip -r /tmp/tct/packages/tct-$MOD_NAME-core-tests-2.2.1-1.zip opt > /dev/null 2>&1; ) + # deployment + echo "-- Suite deployment..." + echo "---- Copying /opt/tct/packages/tct-$MOD_NAME-core-tests-2.2.1-1.zip" + cp /tmp/tct/packages/tct-$MOD_NAME-core-tests-2.2.1-1.zip /opt/tct/packages/ + echo "---- Updating /opt/tct/packages/package_list.xml" + scripts/tcpackageslistsgen.sh $MOD_NAME /opt/tct/packages/package_list.xml 0 + if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi + # echo "---- Updating test plans" + # for file in `grep -r tct-$MOD_NAME-core-tests /opt/tct/manager/plan/ | cut -d: -f1 | uniq` + # do + # scripts/tcpackageslistsgen.sh $MOD_NAME $file + # done + # scripts/tcpackageslistsgen.sh $MOD_NAME /opt/tct/manager/plan/Full_test.xml + # if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi + echo "Task finished successfully" + fi +} + +if [ -z "$1" ]; then + # usage note + echo "Usage: `basename $0` [module_lib_name]" + exit 1 +elif [ "addmod" == "$1" ]; then + # add new module + add_module $2 $3 +elif [ "rmmod" == "$1" ]; then + # remove module + rm_module $2 +elif [ "build" == "$1" ]; then + # build the binary + build $2 +elif [ "install" == "$1" ]; then + # install + inst $2 +else + echo "Invalid subcommand: $1" +fi diff --git a/automated-tests/scripts/tcheadgen.sh b/automated-tests/scripts/tcheadgen.sh new file mode 100755 index 0000000..c7b7700 --- /dev/null +++ b/automated-tests/scripts/tcheadgen.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +if [[ -z $1 ]]; then + echo "Usage note: tcheadgen.sh " + exit 1 +fi + +FILE="$PWD/$1" +TFILE="/tmp/retr.csv" +HEADER_NAME=$(echo $1 | tr '[:lower:]' '[:upper:]' | sed -e 's/-/_/g' -e 's/\./_/') +SCRIPT_DIR="$(cd "$(dirname $0)" && pwd)" + +$SCRIPT_DIR/retriever.sh > $TFILE +if [ $? -ne 0 ]; then cat $TFILE; exit 1; fi +awk -F',' -v HEADER_NAME="$HEADER_NAME" ' + BEGIN { + OFS = ", "; + + startup_counter = 0; + startup_list[0] = ""; + + cleanup_counter = 0; + cleanup_list[0] = ""; + + testcase_counter = 0; + testcase_list[0] = ""; + + tc_array_counter = 0; + tc_array_list[0] = ""; + +print "#ifndef __" HEADER_NAME "__" +print "#define __" HEADER_NAME "__" +print "" +print "#include \"testcase.h\"" +print "" + } + { + testcase_list[testcase_counter++] = $1; + + if (startup_counter == 0 || startup_list[startup_counter-1] != $2) + startup_list[startup_counter++] = $2; + + if (startup_counter == 0 || cleanup_list[cleanup_counter-1] != $3) + cleanup_list[cleanup_counter++] = $3; + + tc_array_list[tc_array_counter++] = "\"" $1 "\", " $1 ", " $2 ", " $3; + } + END { + sc_count = (startup_counter > cleanup_counter) ? startup_counter : cleanup_counter; + for (i = 0; i < sc_count; i++) { + if (i < startup_counter && startup_list[i] != "NULL") +print "extern void " startup_list[i] "(void);" + if (i < cleanup_counter && cleanup_list[i] != "NULL") +print "extern void " cleanup_list[i] "(void);" + } + +print "" + for (i = 0; i < testcase_counter; i++) +print "extern int " testcase_list[i] "(void);" + +print "" +print "testcase tc_array[] = {" + + for (i = 0; i < tc_array_counter; i++) +print " {" tc_array_list[i] "}," + +print " {NULL, NULL}" +print "};" +print "" +print "#endif // __" HEADER_NAME "__" +}' $TFILE > $FILE diff --git a/automated-tests/scripts/tcpackageslistsgen.sh b/automated-tests/scripts/tcpackageslistsgen.sh new file mode 100755 index 0000000..15ea51f --- /dev/null +++ b/automated-tests/scripts/tcpackageslistsgen.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +if [ -z $1 -o -z $2 ]; then + echo "Usage note: tcpackageslistsgen.sh " + exit 1 +fi + +MODULE_NAME=$1 +FILE=$2 +if [ ! -f $FILE ]; then + echo "No such file: $2" + exit +fi +SCRIPT_DIR="$(cd "$(dirname $0)" && pwd)" +AUTO_NUM=$(cd $SCRIPT_DIR/..; scripts/retriever.sh -anum src/$MODULE_NAME) +if [ $? -ne 0 ]; then echo $AUTO_NUM; exit 1; fi +MAN_NUM=$(cd $SCRIPT_DIR/..; scripts/retriever.sh -mnum src/$MODULE_NAME) +if [ $? -ne 0 ]; then echo $MAN_NUM; exit 1; fi + +TFILE="/tmp/tempfile.xml" +if [ -f $TFILE ]; then + rm $TFILE +fi + +function regen { + awk -v RS='\r\n' -v ORS='\r\n' -v MODULE_NAME=$MODULE_NAME -v AUTO_NUM=$AUTO_NUM -v MAN_NUM=$MAN_NUM ' + BEGIN { + found = 0; + replaced = 0; + } + $0 ~ "" { + found = 1; + next + } + /<\/suite>/ { + if (found == 1) { +print " "; +print " " AUTO_NUM ""; +print " " MAN_NUM ""; +print " " AUTO_NUM+MAN_NUM ""; +print " tct-" MODULE_NAME "-core-tests-2.2.1-1.zip"; +print " "; + found = 0; + replaced = 1; + } else { + print $0; + } + next + } + /<\/ns3:testplan>/ { + if (replaced == 0) { +print " "; +print " " AUTO_NUM ""; +print " " MAN_NUM ""; +print " " AUTO_NUM+MAN_NUM ""; +print " tct-" MODULE_NAME "-core-tests-2.2.1-1.zip"; +print " "; +print $0 + } else { + print $0 + } + next + } + { + if (found == 0) { + print $0; + } + }' $FILE > $TFILE + cat $TFILE > $FILE +} + +regen diff --git a/automated-tests/scripts/tctestsgen.sh b/automated-tests/scripts/tctestsgen.sh new file mode 100755 index 0000000..1881668 --- /dev/null +++ b/automated-tests/scripts/tctestsgen.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +if [[ -z $1 ]]; then + echo "Usage note: tctestsgen.sh " + exit 1 +fi + +MODULE_NAME=$1 +MODULE_NAME_C=$(echo $MODULE_NAME | sed -e 's/-\([a-z]\)/\U\1/' -e 's/^\([a-z]\)/\U\1/') +SCRIPT_DIR="$(cd "$(dirname $0)" && pwd)" +TC_DIR="/opt/usr/bin/tct-$1-core" +if [[ $3 == "desktop" ]] ; then + TC_DIR="build/src/$1" +fi + +FILE="$2/tests.xml" +if [ -a $FILE ]; then + rm $FILE +fi +TFILE="/tmp/tcs.csv" +if [ -a $TFILE ]; then + rm $TFILE +fi + +function gen { + awk -F',' -v MODULE_NAME=$MODULE_NAME -v MODULE_NAME_C=$MODULE_NAME_C -v TC_DIR=$TC_DIR ' + BEGIN { + set = "" +print ""; +print " "; +print ""; +print " "; + } + { + if (set != "" && set != $2) { +print " " + } + + if (set != $2) { + set = $2; +print " "; + } + + tcname = $1; + tcpurpose = $3 + +print " "; +print " "; + +print " " TC_DIR "/tct-" MODULE_NAME "-core " tcname ""; +print " "; +print " "; + } + END { + if (set != "") { +print " " + } +print " " +print "" + }' $TFILE > $FILE +} + +(cd $SCRIPT_DIR/..; scripts/retriever.sh -f src/$MODULE_NAME $4 > ${TFILE}_pre) +if [ $? -ne 0 ]; then cat ${TFILE}_pre; exit 1; fi +cat ${TFILE}_pre | sort -t',' -k2,2 -s > $TFILE +gen diff --git a/automated-tests/src/CMakeLists.txt b/automated-tests/src/CMakeLists.txt new file mode 100644 index 0000000..e4f0a2b --- /dev/null +++ b/automated-tests/src/CMakeLists.txt @@ -0,0 +1,6 @@ +IF( DEFINED MODULE ) + MESSAGE(STATUS "Building: ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}") + ADD_SUBDIRECTORY(${MODULE}) +ELSE( DEFINED MODULE ) + MESSAGE(FATAL_ERROR "No module selected to build. Aborting...") +ENDIF( DEFINED MODULE ) diff --git a/automated-tests/src/common/assert.h b/automated-tests/src/common/assert.h new file mode 100644 index 0000000..a5d6cff --- /dev/null +++ b/automated-tests/src/common/assert.h @@ -0,0 +1,82 @@ +#ifndef _ASSERT_H_ +#define _ASSERT_H_ +#include +#include + +#define assert(exp) \ + if (!(exp)) { \ + fprintf(stderr, \ + "Assert fail in %s:%d\n", __FILE__, __LINE__); \ + fprintf(stderr, \ + "Following expression is not true:\n" \ + "%s\n", #exp); \ + return 1; \ + } + +#define assert_eq(var, ref) \ + if (var != ref) { \ + fprintf(stderr, \ + "Assert fail in %s:%d\n", __FILE__, __LINE__); \ + fprintf(stderr, \ + "Values \"%s\" and \"%s\" are not equal:\n" \ + "%s == %d, %s == %d\n", \ + #var, #ref, #var, (int)var, #ref, (int)ref); \ + return 1; \ + } + +#define assert_neq(var, ref) \ + if (var == ref) { \ + fprintf(stderr, \ + "Assert fail in %s:%d\n", __FILE__, __LINE__); \ + fprintf(stderr, \ + "Values \"%s\" and \"%s\" are equal:\n" \ + "%s == %s == %d\n", \ + #var, #ref, #var, #ref, (int)ref); \ + return 1; \ + } + +#define assert_gt(var, ref) \ + if (var <= ref) { \ + fprintf(stderr, \ + "Assert fail in %s:%d\n", __FILE__, __LINE__); \ + fprintf(stderr, \ + "Value \"%s\" is not greater than \"%s\":\n" \ + "%s == %d, %s == %d\n", \ + #var, #ref, #var, var, #ref, ref); \ + return 1; \ + } + +#define assert_geq(var, ref) \ + if (var < ref) { \ + fprintf(stderr, \ + "Assert fail in %s:%d\n", __FILE__, __LINE__); \ + fprintf(stderr, \ + "Value \"%s\" is not greater or equal to \"%s\":\n" \ + "%s == %d, %s == %d\n", \ + #var, #ref, #var, var, #ref, ref); \ + return 1; \ + } + +#define assert_lt(var, ref) \ + if (var >= ref) { \ + fprintf(stderr, \ + "Assert fail in %s:%d\n", __FILE__, __LINE__); \ + fprintf(stderr, \ + "Value \"%s\" is not lower than \"%s\":\n" \ + "%s == %d, %s == %d\n", \ + #var, #ref, #var, var, #ref, ref); \ + return 1; \ + } + +#define assert_leq(var, ref) \ + if (var > ref) { \ + fprintf(stderr, \ + "Assert fail in %s:%d\n", __FILE__, __LINE__); \ + fprintf(stderr, \ + "Value \"%s\" is not lower or equal to \"%s\":\n" \ + "%s == %d, %s == %d\n", \ + #var, #ref, #var, var, #ref, ref); \ + return 1; \ + } + +#endif // _ASSERT_H_ diff --git a/automated-tests/src/common/signal-helper.h b/automated-tests/src/common/signal-helper.h new file mode 100644 index 0000000..b1f555f --- /dev/null +++ b/automated-tests/src/common/signal-helper.h @@ -0,0 +1,1082 @@ +#ifndef SIGNAL_HELPER +#define SIGNAL_HELPER + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// Helper classes for testing DALi signal and slots + +class TestButton +{ +public: + + TestButton( unsigned int id ) + : mId(id) + { + } + + void Press() + { + mPanelDown.Emit( *this ); + } + + void Release() + { + mPanelUp.Emit( *this ); + } + + typedef Signal< void (TestButton&) > PanelDownSignal; + typedef Signal< void (TestButton&) > PanelUpSignal; + + PanelDownSignal& DownSignal() + { + return mPanelDown; + } + + PanelUpSignal& SignalUp() + { + return mPanelUp; + } + + int GetId() + { + return mId; + } + +private: + + int mId; + PanelDownSignal mPanelDown; + PanelUpSignal mPanelUp; +}; + +class TestApp : public ConnectionTracker +{ +public: + + TestApp() + : mButtonPressed( false ), + mVoidFunctionCalled( false ) + { + } + + void OnButtonPress( TestButton& button ) + { + mButtonPressed = true; + mButtonId = button.GetId(); + } + + void OnButtonRelease( TestButton& button ) + { + mButtonPressed = false; + mButtonId = button.GetId(); + } + + int GetButtonPressedId() + { + return mButtonId; + } + + bool BoolReturnTestFalse() + { + return false; + } + + bool BoolReturnTestTrue() + { + return true; + } + + void VoidFunction() + { + mVoidFunctionCalled = true; + } + + bool mButtonPressed; + bool mVoidFunctionCalled; + int mButtonId; +}; + +class TestSignals +{ +public: + + // Void return, no parameters + typedef Signal VoidRetNoParamSignal; + + // Void return, 1 value parameter + typedef Signal VoidRet1ValueParamSignal; + + // Void return, 1 reference parameter + typedef Signal< void (int&)> VoidRet1RefParamSignal; + + // Void return, 2 value parameters + typedef Signal VoidRet2ValueParamSignal; + + // Void return, 3 value parameters + typedef Signal VoidRet3ValueParamSignal; + + // bool return, 1 value parameter + typedef Signal< bool (float)> BoolRet1ValueParamSignal; + + // bool return, 2 value parameter + typedef Signal BoolRet2ValueParamSignal; + + // int return, 2 value parameter + typedef Signal IntRet2ValueParamSignal; + + // float return, 0 parameters + typedef Signal< float () > FloatRet0ParamSignal; + + // float return, 1 value parameters + typedef Signal< float (float ) > FloatRet1ParamSignal; + + // float return, 2 value parameters + typedef Signal FloatRet2ValueParamSignal; + + // float return, 3 value parameters + typedef Signal FloatRet3ValueParamSignal; + + // void return, 3 value parameters + typedef Signal VoidSignalTypeFloatValue3; + + + VoidRetNoParamSignal& SignalVoidNone() { return mSignalVoid0; } + VoidRet1RefParamSignal& SignalVoid1Ref() { return mSignalVoid1R; } + VoidRet1ValueParamSignal& SignalVoid1Value() { return mSignalVoid1V; } + VoidRet2ValueParamSignal& SignalVoid2Value() { return mSignalVoid2V; } + VoidRet3ValueParamSignal& SignalVoid3Value() { return mSignalVoid3V; } + + BoolRet1ValueParamSignal& SignalBool1Value() { return mSignalBool1V; } + BoolRet2ValueParamSignal& SignalBool2Value() { return mSignalBool2V; } + IntRet2ValueParamSignal& SignalInt2Value() { return mSignalInt2V; } + FloatRet0ParamSignal& SignalFloat0() { return mSignalFloat0; } + FloatRet1ParamSignal& SignalFloat1Value() {return mSignalFloat1V; } + FloatRet2ValueParamSignal& SignalFloat2Value() { return mSignalFloat2V; } + + VoidSignalTypeFloatValue3& VoidSignalFloatValue3() { return mVoidSignalFloatValue3; } + FloatRet3ValueParamSignal& SignalFloat3Value() { return mFloatSignalFloatValue3; } + + TestSignals() + { + } + + void CheckNoConnections() + { + DALI_TEST_EQUALS( mSignalVoid0.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mSignalVoid1R.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mSignalVoid1V.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mSignalVoid2V.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mSignalVoid3V.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mSignalBool1V.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mSignalBool2V.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mSignalInt2V.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mSignalFloat0.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mSignalFloat1V.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mSignalFloat2V.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mVoidSignalFloatValue3.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mFloatSignalFloatValue3.GetConnectionCount(), 0u, TEST_LOCATION ); + } + + void EmitVoidSignalVoid() + { + mSignalVoid0.Emit(); + } + + void EmitVoidSignalIntRef(int& ref) + { + mSignalVoid1R.Emit(ref); + } + + void EmitVoidSignal1IntValue(int p1) + { + mSignalVoid1V.Emit(p1); + } + + void EmitVoidSignal2IntValue(int p1, int p2) + { + mSignalVoid2V.Emit(p1,p2); + } + + void EmitVoidSignal3IntValue(int p1, int p2, int p3) + { + mSignalVoid3V.Emit(p1,p2,p3); + } + + + bool EmitBoolSignalFloatValue(float p1) + { + return mSignalBool1V.Emit(p1); + } + + bool EmitBoolSignalFloatValueIntValue(float p1, int p2) + { + return mSignalBool2V.Emit(p1, p2); + } + + int EmitIntSignalFloatValueIntValue(float p1, int p2) + { + return mSignalInt2V.Emit(p1, p2); + } + + float EmitFloat1VSignal(float p1 ) + { + return mSignalFloat1V.Emit(p1 ); + } + + float EmitFloat2VSignal(float p1, float p2) + { + return mSignalFloat2V.Emit(p1, p2); + } + + float EmitFloat0Signal() + { + return mSignalFloat0.Emit(); + } + + void EmitVoidSignalFloatValue3(float p1, float p2, float p3) + { + mVoidSignalFloatValue3.Emit(p1, p2, p3); + } + + float EmitFloat3VSignal(float p1, float p2, float p3) + { + return mFloatSignalFloatValue3.Emit(p1, p2, p3); + } + +private: + + VoidRetNoParamSignal mSignalVoid0; + VoidRet1RefParamSignal mSignalVoid1R; + VoidRet1ValueParamSignal mSignalVoid1V; + VoidRet2ValueParamSignal mSignalVoid2V; + VoidRet3ValueParamSignal mSignalVoid3V; + + BoolRet1ValueParamSignal mSignalBool1V; + BoolRet2ValueParamSignal mSignalBool2V; + IntRet2ValueParamSignal mSignalInt2V; + FloatRet0ParamSignal mSignalFloat0; + FloatRet1ParamSignal mSignalFloat1V; + FloatRet2ValueParamSignal mSignalFloat2V; + VoidSignalTypeFloatValue3 mVoidSignalFloatValue3; + FloatRet3ValueParamSignal mFloatSignalFloatValue3; +}; + +/** + * A helper class with various slots + */ +class TestSlotHandler : public ConnectionTracker +{ +public: + + TestSlotHandler() + : mIntParam1( 0 ), + mIntParam2( 0 ), + mIntParam3( 0 ), + mFloatParam1( 0.0f ), + mFloatParam2( 0.0f ), + mFloatParam3( 0.0f ), + mBoolReturn( false ), + mIntReturn( 0 ), + mFloatReturn( 0.0f ), + mHandled( false ), + mHandledCount( 0 ) + { + } + + void Reset() + { + mIntParam1 = 0; + mIntParam2 = 0; + mIntParam3 = 0; + mFloatParam1 = 0.0f; + mFloatParam2 = 0.0f; + mFloatParam3 = 0.0f; + mBoolReturn = false; + mIntReturn = 0; + mFloatReturn = 0.0f; + mHandled = false; + } + + void VoidSlotVoid() + { + mHandled = true; + ++mHandledCount; + } + + void VoidSlotVoidAlternative() + { + mHandled = true; + ++mHandledCount; + } + + void VoidSlotIntRef( int& p1 ) + { + mIntParam1 = p1; + mHandled = true; + ++mHandledCount; + } + + void VoidSlotIntValue( int p1 ) + { + mIntParam1 = p1; + mHandled = true; + ++mHandledCount; + } + + void VoidDuplicateSlotIntValue( int p1 ) + { + mIntParam2 = p1; + mHandled = true; + ++mHandledCount; + } + + void VoidSlotIntValueIntValue( int p1, int p2 ) + { + mIntParam1 = p1; + mIntParam2 = p2; + mHandled = true; + ++mHandledCount; + } + + bool BoolSlotFloatValue( float p1 ) + { + mFloatParam1 = p1; + mHandled = true; + ++mHandledCount; + return mBoolReturn; + } + + bool BoolSlotFloatValueIntValue( float p1, int p2 ) + { + mFloatParam1 = p1; + mIntParam2 = p2; + mHandled = true; + ++mHandledCount; + return mBoolReturn; + } + + int IntSlotFloatValueIntValue( float p1, int p2 ) + { + mFloatParam1 = p1; + mIntParam2 = p2; + mHandled = true; + ++mHandledCount; + return mIntReturn; + } + + float FloatSlotVoid() + { + mHandled = true; + ++mHandledCount; + return mFloatReturn; + } + + float FloatSlotFloatValueFloatValue( float p1, float p2 ) + { + mFloatParam1 = p1; + mFloatParam2 = p2; + mHandled = true; + ++mHandledCount; + return mFloatReturn; + } + + void VoidSlotFloatValue3( float p1, float p2, float p3 ) + { + mFloatParam1 = p1; + mFloatParam2 = p2; + mFloatParam3 = p3; + mHandled = true; + ++mHandledCount; + } + + float FloatSlotFloatValue3( float p1, float p2, float p3 ) + { + mFloatParam1 = p1; + mFloatParam2 = p2; + mFloatParam3 = p3; + mHandled = true; + ++mHandledCount; + return mFloatReturn; + } + + int mIntParam1, mIntParam2, mIntParam3; + float mFloatParam1, mFloatParam2, mFloatParam3; + bool mBoolReturn; + int mIntReturn; + float mFloatReturn; + bool mHandled; + int mHandledCount; +}; + +/** + * A version of TestSlotHandler which disconnects during the callback + */ +class TestSlotDisconnector : public ConnectionTracker +{ +public: + + TestSlotDisconnector() + : mIntParam1( 0 ), + mIntParam2( 0 ), + mIntParam3( 0 ), + mFloatParam1( 0.0f ), + mFloatParam2( 0.0f ), + mBoolReturn( false ), + mIntReturn( 0 ), + mFloatReturn( 0.0f ), + mHandled( false ) + { + } + + void Reset() + { + mIntParam1 = 0; + mIntParam2 = 0; + mIntParam3 = 0; + mFloatParam1 = 0.0f; + mFloatParam2 = 0.0f; + mBoolReturn = false; + mIntReturn = 0; + mFloatReturn = 0.0f; + mHandled = false; + } + + void VoidConnectVoid( TestSignals::VoidRetNoParamSignal& signal ) + { + mVoidSignalVoid = &signal; + signal.Connect( this, &TestSlotDisconnector::VoidSlotVoid ); + } + + void VoidSlotVoid() + { + mVoidSignalVoid->Disconnect( this, &TestSlotDisconnector::VoidSlotVoid ); + mHandled = true; + } + + void VoidConnectIntRef( TestSignals::VoidRet1RefParamSignal& signal ) + { + mVoidSignalIntRef = &signal; + signal.Connect( this, &TestSlotDisconnector::VoidSlotIntRef ); + } + + void VoidSlotIntRef( int& p1 ) + { + mVoidSignalIntRef->Disconnect( this, &TestSlotDisconnector::VoidSlotIntRef ); + mIntParam1 = p1; + mHandled = true; + } + + void VoidSlotIntValue( int p1 ) + { + mIntParam1 = p1; + mHandled = true; + } + + void VoidSlotIntValueIntValue( int p1, int p2 ) + { + mIntParam1 = p1; + mIntParam2 = p2; + mHandled = true; + } + + bool BoolSlotFloatValue( float p1 ) + { + mFloatParam1 = p1; + mHandled = true; + return mBoolReturn; + } + + bool BoolSlotFloatValueIntValue( float p1, int p2 ) + { + mFloatParam1 = p1; + mIntParam2 = p2; + mHandled = true; + return mBoolReturn; + } + + int IntSlotFloatValueIntValue( float p1, int p2 ) + { + mFloatParam1 = p1; + mIntParam2 = p2; + mHandled = true; + return mIntReturn; + } + + float FloatSlotVoid() + { + mHandled = true; + return mFloatReturn; + } + + float FloatSlotFloatValueFloatValue( float p1, float p2 ) + { + mFloatParam1 = p1; + mFloatParam2 = p2; + mHandled = true; + return mFloatReturn; + } + + TestSignals::VoidRetNoParamSignal* mVoidSignalVoid; + TestSignals::VoidRet1RefParamSignal* mVoidSignalIntRef; + + int mIntParam1, mIntParam2, mIntParam3; + float mFloatParam1, mFloatParam2; + bool mBoolReturn; + int mIntReturn; + float mFloatReturn; + bool mHandled; +}; + +/** + * A more complicated version of TestSlotDisconnector, which disconnects some but not all callbacks + */ +class TestSlotMultiDisconnector : public ConnectionTracker +{ +public: + + static const int NUM_SLOTS = 10; + + TestSlotMultiDisconnector() + : mVoidSignalVoid( NULL ) + { + Reset(); + } + + void Reset() + { + for( int i=0; iDisconnect( this, &TestSlotMultiDisconnector::Slot1 ); + mVoidSignalVoid->Disconnect( this, &TestSlotMultiDisconnector::Slot3 ); + mVoidSignalVoid->Disconnect( this, &TestSlotMultiDisconnector::Slot5 ); + mVoidSignalVoid->Disconnect( this, &TestSlotMultiDisconnector::Slot7 ); + mVoidSignalVoid->Disconnect( this, &TestSlotMultiDisconnector::Slot9 ); + } + + void Slot4() + { + mSlotHandled[4] = true; + } + + void Slot5() + { + mSlotHandled[5] = true; + } + + void Slot6() + { + mSlotHandled[6] = true; + } + + void Slot7() + { + mSlotHandled[7] = true; + } + + void Slot8() + { + mSlotHandled[8] = true; + } + + void Slot9() + { + mSlotHandled[9] = true; + } + + TestSignals::VoidRetNoParamSignal* mVoidSignalVoid; + + bool mSlotHandled[NUM_SLOTS]; +}; + + +/** + * A version of TestSlotHandler which disconnects during the callback + */ +class TestEmitDuringCallback : public ConnectionTracker +{ +public: + + TestEmitDuringCallback() + : mVoidSignalVoid( NULL ), + mFloatRet0ParamSignal( NULL), + mFloatRet1ParamSignal( NULL ), + mFloatRet2ParamSignal( NULL ), + mFloatRet3ParamSignal( NULL ), + mHandled( false ) + { + } + + void VoidConnectVoid( TestSignals::VoidRetNoParamSignal& signal ) + { + mVoidSignalVoid = &signal; + signal.Connect( this, &TestEmitDuringCallback::VoidSlotVoid ); + } + + void FloatRet0ParamConnect( TestSignals::FloatRet0ParamSignal& signal ) + { + mFloatRet0ParamSignal = &signal; + signal.Connect( this, &TestEmitDuringCallback::FloatRet0Param ); + } + void FloatRet1ParamConnect( TestSignals::FloatRet1ParamSignal& signal ) + { + mFloatRet1ParamSignal = &signal; + signal.Connect( this, &TestEmitDuringCallback::FloatRet1Param ); + } + void FloatRet2ParamConnect( TestSignals::FloatRet2ValueParamSignal& signal ) + { + mFloatRet2ParamSignal = &signal; + signal.Connect( this, &TestEmitDuringCallback::FloatRet2Param ); + } + void FloatRet3ParamConnect( TestSignals::FloatRet3ValueParamSignal& signal ) + { + mFloatRet3ParamSignal = &signal; + signal.Connect( this, &TestEmitDuringCallback::FloatRet3Param ); + } + + void DeleteDuringEmitConnect( TestSignals::VoidRetNoParamSignal& signal ) + { + mVoidSignalVoid = &signal; + signal.Connect( this, &TestEmitDuringCallback::DeleteSignalDuringEmit ); + } + + void VoidSlotVoid() + { + // Emitting during Emit is very bad! + mVoidSignalVoid->Emit(); + mHandled = true; + } + + void DeleteSignalDuringEmit() + { + // deleting the signal during the emit + delete mVoidSignalVoid; + } + + float FloatRet0Param() + { + // Emitting during Emit is very bad! + mHandled = true; + return mFloatRet0ParamSignal->Emit(); + } + float FloatRet1Param( float x ) + { + // Emitting during Emit is very bad! + mHandled = true; + return mFloatRet1ParamSignal->Emit(x); + } + float FloatRet2Param( float x, float y ) + { + // Emitting during Emit is very bad! + mHandled = true; + return mFloatRet2ParamSignal->Emit( x, y ); + } + float FloatRet3Param( float x, float y, float z) + { + // Emitting during Emit is very bad! + mHandled = true; + return mFloatRet3ParamSignal->Emit( x, y, z ); + } + + TestSignals::VoidRetNoParamSignal* mVoidSignalVoid; + TestSignals::FloatRet0ParamSignal* mFloatRet0ParamSignal; + TestSignals::FloatRet1ParamSignal* mFloatRet1ParamSignal; + TestSignals::FloatRet2ValueParamSignal* mFloatRet2ParamSignal; + TestSignals::FloatRet3ValueParamSignal* mFloatRet3ParamSignal; + + + bool mHandled; +}; + + +/** + * A version of TestSlotHandler which uses SlotDelegate + */ +class TestSlotDelegateHandler // This does not inherit from ConnectionTrackerInterface! +{ +public: + + TestSlotDelegateHandler() + : mSlotDelegate( this ), + mIntParam1( 0 ), + mIntParam2( 0 ), + mIntParam3( 0 ), + mFloatParam1( 0.0f ), + mFloatParam2( 0.0f ), + mFloatParam3( 0.0f ), + mBoolReturn( false ), + mIntReturn( 0 ), + mFloatReturn( 0.0f ), + mHandled( false ), + mHandledCount( 0 ) + { + } + + void Reset() + { + mIntParam1 = 0; + mIntParam2 = 0; + mIntParam3 = 0; + mFloatParam1 = 0.0f; + mFloatParam2 = 0.0f; + mFloatParam3 = 0.0f; + mBoolReturn = false; + mIntReturn = 0; + mFloatReturn = 0.0f; + mHandled = false; + } + + void VoidSlotVoid() + { + mHandled = true; + ++mHandledCount; + } + + void AlternativeVoidSlotVoid() + { + mHandled = true; + ++mHandledCount; + } + + void VoidSlotIntRef( int& p1 ) + { + mIntParam1 = p1; + mHandled = true; + ++mHandledCount; + } + + void VoidSlotIntValue( int p1 ) + { + mIntParam1 = p1; + mHandled = true; + ++mHandledCount; + } + + void VoidDuplicateSlotIntValue( int p1 ) + { + mIntParam2 = p1; + mHandled = true; + ++mHandledCount; + } + + void VoidSlotIntValueIntValue( int p1, int p2 ) + { + mIntParam1 = p1; + mIntParam2 = p2; + mHandled = true; + ++mHandledCount; + } + + bool BoolSlotFloatValue( float p1 ) + { + mFloatParam1 = p1; + mHandled = true; + ++mHandledCount; + return mBoolReturn; + } + + bool BoolSlotFloatValueIntValue( float p1, int p2 ) + { + mFloatParam1 = p1; + mIntParam2 = p2; + mHandled = true; + ++mHandledCount; + return mBoolReturn; + } + + int IntSlotFloatValueIntValue( float p1, int p2 ) + { + mFloatParam1 = p1; + mIntParam2 = p2; + mHandled = true; + ++mHandledCount; + return mIntReturn; + } + + float FloatSlotVoid() + { + mHandled = true; + ++mHandledCount; + return mFloatReturn; + } + + float FloatSlotFloatValueFloatValue( float p1, float p2 ) + { + mFloatParam1 = p1; + mFloatParam2 = p2; + mHandled = true; + ++mHandledCount; + return mFloatReturn; + } + + void VoidSlotFloatValue3( float p1, float p2, float p3 ) + { + mFloatParam1 = p1; + mFloatParam2 = p2; + mFloatParam3 = p3; + mHandled = true; + ++mHandledCount; + } + + float FloatSlotFloatValue3( float p1, float p2, float p3 ) + { + mFloatParam1 = p1; + mFloatParam2 = p2; + mFloatParam3 = p3; + mHandled = true; + ++mHandledCount; + return mFloatReturn; + } + + SlotDelegate mSlotDelegate; + + int mIntParam1, mIntParam2, mIntParam3; + float mFloatParam1, mFloatParam2, mFloatParam3; + bool mBoolReturn; + int mIntReturn; + float mFloatReturn; + bool mHandled; + int mHandledCount; +}; + +/** + * Test that reimplmenting ConnectionTrackerInterface actually works. + * This basic connection tracker only allows one callback to be connected. + */ +class TestBasicConnectionTrackerInterface : public ConnectionTrackerInterface +{ +public: + + TestBasicConnectionTrackerInterface() + : mCallbackHandled( false ), + mCallback( NULL ), + mSlotObserver( NULL ) + { + } + + ~TestBasicConnectionTrackerInterface() + { + if( mSlotObserver && mCallback ) + { + // Notify signal since the slot has been destroyed + mSlotObserver->SlotDisconnected( mCallback ); + // mCallback and mSlotObserver are not owned + } + } + + /** + * An example slot + */ + void VoidSlotVoid() + { + mCallbackHandled = true; + } + + /** + * @copydoc ConnectionTrackerInterface::GetConnectionCount + */ + virtual std::size_t GetConnectionCount() const + { + if( mCallback ) + { + return 1u; + } + + return 0u; + } + + /** + * @copydoc ConnectionTrackerInterface::SignalConnected + */ + virtual void SignalConnected( SlotObserver* slotObserver, CallbackBase* callback ) + { + DALI_ASSERT_ALWAYS( NULL == mCallback && "Only one connection supported!" ); + + mCallback = callback; + mSlotObserver = slotObserver; + } + + /** + * @copydoc ConnectionTrackerInterface::SignalDisconnected + */ + virtual void SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback ) + { + if( mSlotObserver == slotObserver ) + { + mSlotObserver = NULL; + mCallback = NULL; + // mCallback and mSlotObserver are not owned + } + } + + /** + * RemoveNullCallback, + * testing what occurs when we pass a callback that doesn't exist + */ + void RemoveNullCallback() + { + mSlotObserver->SlotDisconnected( NULL ); + } + +private: + + TestBasicConnectionTrackerInterface( const TestBasicConnectionTrackerInterface& ); ///< undefined copy constructor + TestBasicConnectionTrackerInterface& operator=( const TestBasicConnectionTrackerInterface& ); ///< undefined assignment operator + +public: + + bool mCallbackHandled; + +private: + + CallbackBase* mCallback; ///< callback, has ownership + SlotObserver* mSlotObserver; ///< a pointer to the slot observer (not owned) +}; + + + + +// for testing static function callbacks +class StaticFunctionHandlers +{ +public: + StaticFunctionHandlers() + { + staticFunctionHandled = false; + } + void Reset() + { + staticFunctionHandled = false; + } + + static void VoidSlotVoid() + { + staticFunctionHandled = true; + } + static void VoidSlot1Param( int p1 ) + { + staticFunctionHandled = true; + } + static void VoidSlot2Param( int p1, int p2 ) + { + staticFunctionHandled = true; + } + static void VoidSlot3Param( int p1, int p2, int p3 ) + { + staticFunctionHandled = true; + } + + static float RetSlot0Param( ) + { + staticFunctionHandled = true; + return 0; + } + static float RetSlot1Param( float p1 ) + { + staticFunctionHandled = true; + return 0; + } + static float RetSlot2Param( float p1, float p2 ) + { + staticFunctionHandled = true; + return 0; + } + static float RetSlot3Param( float p1, float p2, float p3 ) + { + staticFunctionHandled = true; + return 0; + } + + static bool staticFunctionHandled; +}; + + +/** + * test functor, we store a reference to a bool which is outside of the functor + * so when the functor is copied, the copy can reference the original data + */ +struct TestFunctor +{ + TestFunctor( bool& functorCalled): + mFunctorCalled( functorCalled ) + { + }; + + void operator()() + { + mFunctorCalled = true; + } + + bool& mFunctorCalled; +}; + +struct VoidFunctorVoid +{ + VoidFunctorVoid( bool& functorCalled): + mFunctorCalled( functorCalled ) + { + + } + + void operator()() + { + mFunctorCalled = true; + } + + bool& mFunctorCalled; +}; + +#endif // #define SIGNAL_HELPER diff --git a/automated-tests/src/common/testcase.h b/automated-tests/src/common/testcase.h new file mode 100644 index 0000000..011a452 --- /dev/null +++ b/automated-tests/src/common/testcase.h @@ -0,0 +1,18 @@ +#ifndef _TESTCASE_H_ +#define _TESTCASE_H_ + +/* pointer to startup/cleanup functions */ +typedef void (*void_fun_ptr)(void); + +/* pointer to testcase functions */ +typedef int (*tc_fun_ptr)(void); + +/* struct describing specific testcase */ +typedef struct testcase_s { + const char* name; + tc_fun_ptr function; + void_fun_ptr startup; + void_fun_ptr cleanup; +} testcase; + +#endif // _TESTCASE_H_ diff --git a/automated-tests/src/dali-devel/CMakeLists.txt b/automated-tests/src/dali-devel/CMakeLists.txt new file mode 100644 index 0000000..84d2028 --- /dev/null +++ b/automated-tests/src/dali-devel/CMakeLists.txt @@ -0,0 +1,67 @@ +SET(PKG_NAME "dali-devel") + +SET(EXEC_NAME "tct-${PKG_NAME}-core") +SET(RPM_NAME "core-${PKG_NAME}-tests") + +SET(CAPI_LIB "dali-devel") + +SET(TC_SOURCES + utc-Dali-Actor.cpp + utc-Dali-Atlas.cpp + utc-Dali-Context.cpp + utc-Dali-Constrainer.cpp + utc-Dali-CullFace.cpp + utc-Dali-DistanceField.cpp + utc-Dali-Geometry.cpp + utc-Dali-Hash.cpp + utc-Dali-HitTestAlgorithm.cpp + utc-Dali-Material.cpp + utc-Dali-Mutex.cpp + utc-Dali-PropertyBuffer.cpp + utc-Dali-Renderer.cpp + utc-Dali-Sampler.cpp + utc-Dali-Scripting.cpp + utc-Dali-Shader.cpp + utc-Dali-WeakHandle.cpp +) + +LIST(APPEND TC_SOURCES + ../dali/dali-test-suite-utils/mesh-builder.cpp + ../dali/dali-test-suite-utils/dali-test-suite-utils.cpp + ../dali/dali-test-suite-utils/test-harness.cpp + ../dali/dali-test-suite-utils/test-application.cpp + ../dali/dali-test-suite-utils/test-gesture-manager.cpp + ../dali/dali-test-suite-utils/test-gl-abstraction.cpp + ../dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp + ../dali/dali-test-suite-utils/test-native-image.cpp + ../dali/dali-test-suite-utils/test-platform-abstraction.cpp + ../dali/dali-test-suite-utils/test-render-controller.cpp + ../dali/dali-test-suite-utils/test-trace-call-stack.cpp +) + +PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED + dali-core +) + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${${CAPI_LIB}_CFLAGS_OTHER} -O0 -ggdb --coverage -Wall -Werror=return-type") + +FOREACH(directory ${${CAPI_LIB}_LIBRARY_DIRS}) + SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -L${directory}") +ENDFOREACH(directory ${CAPI_LIB_LIBRARY_DIRS}) + +INCLUDE_DIRECTORIES( + ../../.. + . + ${${CAPI_LIB}_INCLUDE_DIRS} + ../dali/dali-test-suite-utils +) + +ADD_EXECUTABLE(${EXEC_NAME} ${EXEC_NAME}.cpp ${TC_SOURCES}) +TARGET_LINK_LIBRARIES(${EXEC_NAME} + ${${CAPI_LIB}_LIBRARIES} + -lpthread +) + +INSTALL(PROGRAMS ${EXEC_NAME} + DESTINATION ${BIN_DIR}/${EXEC_NAME} +) diff --git a/automated-tests/src/dali-devel/tct-dali-devel-core.cpp b/automated-tests/src/dali-devel/tct-dali-devel-core.cpp new file mode 100644 index 0000000..69d3233 --- /dev/null +++ b/automated-tests/src/dali-devel/tct-dali-devel-core.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include "tct-dali-devel-core.h" + +int main(int argc, char * const argv[]) +{ + int result = TestHarness::EXIT_STATUS_BAD_ARGUMENT; + + const char* optString = "r"; + bool optRerunFailed(false); + + int nextOpt = 0; + do + { + nextOpt = getopt( argc, argv, optString ); + switch(nextOpt) + { + case 'r': + optRerunFailed = true; + break; + case '?': + TestHarness::Usage(argv[0]); + exit(TestHarness::EXIT_STATUS_BAD_ARGUMENT); + break; + } + } while( nextOpt != -1 ); + + if( optind == argc ) // no testcase name in argument list + { + result = TestHarness::RunAllInParallel(argv[0], tc_array, optRerunFailed); + } + else + { + // optind is index of next argument - interpret as testcase name + result = TestHarness::FindAndRunTestCase(tc_array, argv[optind]); + } + return result; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-Actor.cpp b/automated-tests/src/dali-devel/utc-Dali-Actor.cpp new file mode 100644 index 0000000..7322fa4 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-Actor.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +//& set: DaliActor + +using std::string; +using namespace Dali; + + +int UtcDaliActorAddRendererP(void) +{ + tet_infoline("Testing Actor::AddRenderer"); + TestApplication application; + + Actor actor = Actor::New(); + + DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION ); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(1.0f); + Renderer renderer = Renderer::New(geometry, material); + + actor.AddRenderer( renderer ); + DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetRendererAt(0), renderer, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliActorAddRendererN(void) +{ + tet_infoline("Testing Actor::AddRenderer"); + TestApplication application; + + Actor actor = Actor::New(); + Renderer renderer; + + // try illegal Add + try + { + actor.AddRenderer( renderer ); + tet_printf("Assertion test failed - no Exception\n" ); + tet_result(TET_FAIL); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "Renderer handle is empty", TEST_LOCATION); + DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION ); + } + catch(...) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + END_TEST; +} + +int UtcDaliActorAddRendererOnStage(void) +{ + tet_infoline("Testing Actor::AddRenderer"); + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(0); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(1.0f); + Renderer renderer = Renderer::New(geometry, material); + + application.SendNotification(); + application.Render(0); + + try + { + actor.AddRenderer( renderer ); + tet_result(TET_PASS); + } + catch(...) + { + tet_result(TET_FAIL); + } + + END_TEST; +} + +int UtcDaliActorRemoveRendererP(void) +{ + tet_infoline("Testing Actor::RemoveRenderer"); + TestApplication application; + + Actor actor = Actor::New(); + + DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION ); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(1.0f); + Renderer renderer = Renderer::New(geometry, material); + + actor.AddRenderer( renderer ); + DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetRendererAt(0), renderer, TEST_LOCATION ); + + actor.RemoveRenderer(0); + DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION ); + + + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-Atlas.cpp b/automated-tests/src/dali-devel/utc-Dali-Atlas.cpp new file mode 100644 index 0000000..ef83df1 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-Atlas.cpp @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; + +namespace +{ +static const char* gTestImageFilename = "icon_wrt.png"; + +void PrepareResourceImage( TestApplication& application, unsigned int imageHeight, unsigned int imageWidth, Pixel::Format pixelFormat ) +{ + TestPlatformAbstraction& platform = application.GetPlatform(); + platform.SetClosestImageSize(Vector2( 16, 16)); + + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, imageWidth, imageHeight, imageWidth, imageHeight ); + unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat ); + unsigned int initialColor = 0xFF; + memset( pixbuffer, initialColor, imageHeight*imageWidth*bytesPerPixel); + + Integration::ResourcePointer resourcePtr(bitmap); + platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr ); +} + +} + +void utc_dali_atlas_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_atlas_cleanup(void) +{ + test_return_value = TET_PASS; +} + +// 1.1 +int UtcDaliAtlasNew01(void) +{ + TestApplication application; + + // invoke default handle constructor + Atlas atlas; + + DALI_TEST_CHECK( !atlas ); + + // initialise handle + atlas = Atlas::New( 16, 16 ); + + DALI_TEST_CHECK( atlas ); + END_TEST; +} + + +// 1.2 +int UtcDaliAtlasUpload01(void) +{ + TestApplication application; + + Atlas atlas = Atlas::New( 16, 16, Pixel::RGBA8888 ); + DALI_TEST_CHECK( atlas ); + + // Using correct pixel format + PixelBuffer* buffer = new PixelBuffer[16 * 16]; + BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 ); + DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) ); + + PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 ); + DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 0 ) ); + + END_TEST; +} + +// 1.3 +int UtcDaliAtlasUpload02(void) +{ + TestApplication application; + + Atlas atlas = Atlas::New( 10, 10, Pixel::RGBA8888 ); + DALI_TEST_CHECK( atlas ); + + // Using INCORRECT pixel format + PixelBuffer* buffer = new PixelBuffer[16 * 16]; + BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::A8 ); + DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) ); + + PrepareResourceImage( application, 16, 16, Pixel::A8 ); + DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 0 ) ); + + END_TEST; +} + +// 1.4 +int UtcDaliAtlasUpload03(void) +{ + TestApplication application; + + Atlas atlas = Atlas::New( 10, 10, Pixel::RGBA8888 ); + DALI_TEST_CHECK( atlas ); + + // Using image too big for atlas + PixelBuffer* buffer = new PixelBuffer[16 * 16]; + BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 ); + DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) ); + + PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 ); + DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 0 ) ); + + END_TEST; +} + +// 1.5 +int UtcDaliAtlasUpload04(void) +{ + TestApplication application; + + Atlas atlas = Atlas::New( 32, 32, Pixel::RGBA8888 ); + DALI_TEST_CHECK( atlas ); + + // Using valid offsets + PixelBuffer* buffer = new PixelBuffer[16 * 16]; + BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 ); + + DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) ); + DALI_TEST_CHECK( atlas.Upload( image, 16, 0 ) ); + DALI_TEST_CHECK( atlas.Upload( image, 0, 16 ) ); + DALI_TEST_CHECK( atlas.Upload( image, 16, 16 ) ); + + PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 ); + DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 0 ) ); + DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 16, 0 ) ); + DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 16 ) ); + DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 16, 16 ) ); + + END_TEST; +} + +// 1.6 +int UtcDaliAtlasUpload05(void) +{ + TestApplication application; + + Atlas atlas = Atlas::New( 32, 32, Pixel::RGBA8888 ); + DALI_TEST_CHECK( atlas ); + + // Using invalid offsets + PixelBuffer* buffer = new PixelBuffer[16 * 16]; + BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 ); + + DALI_TEST_CHECK( !atlas.Upload( image, 0, 17 ) ); + DALI_TEST_CHECK( !atlas.Upload( image, 17, 0 ) ); + DALI_TEST_CHECK( !atlas.Upload( image, 17, 17 ) ); + DALI_TEST_CHECK( !atlas.Upload( image, 99, 0 ) ); + DALI_TEST_CHECK( !atlas.Upload( image, 0, 99 ) ); + DALI_TEST_CHECK( !atlas.Upload( image, 99, 99 ) ); + + PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 ); + + DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 17 ) ); + DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 17, 0 ) ); + DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 17, 17 ) ); + DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 99, 0 ) ); + DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 99 ) ); + DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 99, 99 ) ); + + END_TEST; +} + diff --git a/automated-tests/src/dali-devel/utc-Dali-Constrainer.cpp b/automated-tests/src/dali-devel/utc-Dali-Constrainer.cpp new file mode 100644 index 0000000..076a9c2 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-Constrainer.cpp @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include + +using namespace Dali; +using namespace Dali::Internal; + +namespace +{ + +static void SetupPath( Dali::Path& path) +{ + path.AddPoint(Vector3( 30.0, 80.0, 0.0)); + path.AddPoint(Vector3( 70.0, 120.0, 0.0)); + path.AddPoint(Vector3(100.0, 100.0, 0.0)); + + //Control points for first segment + path.AddControlPoint( Vector3( 39.0, 90.0, 0.0) ); + path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) ); + + //Control points for second segment + path.AddControlPoint(Vector3( 78.0, 120.0, 0.0) ); + path.AddControlPoint(Vector3( 93.0, 104.0, 0.0) ); +} + +static void SetupPathConstrainer( Dali::PathConstrainer& PathConstrainer) +{ + PathConstrainer.SetProperty( Dali::PathConstrainer::Property::FORWARD, Vector3(1.0f,0.0f,0.0f) ); + + Dali::Property::Array points; + points.Resize(3); + points[0] = Vector3( 30.0, 80.0, 0.0); + points[1] = Vector3( 70.0, 120.0, 0.0); + points[2] = Vector3(100.0, 100.0, 0.0); + PathConstrainer.SetProperty( Dali::PathConstrainer::Property::POINTS, points ); + + points.Resize(4); + points[0] = Vector3( 39.0, 90.0, 0.0); + points[1] = Vector3( 56.0, 119.0, 0.0); + points[2] = Vector3( 78.0, 120.0, 0.0); + points[3] = Vector3( 93.0, 104.0, 0.0); + PathConstrainer.SetProperty( Dali::PathConstrainer::Property::CONTROL_POINTS, points ); +} + +static void SetupLinearConstrainerUniformProgress( Dali::LinearConstrainer& linearConstrainer) +{ + Dali::Property::Array points; + points.Resize(3); + points[0] = 0.0f; + points[1] = 1.0f; + points[2] = 0.0f; + linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::VALUE, points ); +} + +static void SetupLinearConstrainerNonUniformProgress( Dali::LinearConstrainer& linearConstrainer) +{ + Dali::Property::Array points; + points.Resize(3); + points[0] = 0.0f; + points[1] = 1.0f; + points[2] = 0.0f; + linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::VALUE, points ); + + points[0] = 0.0f; + points[1] = 0.25f; + points[2] = 1.0f; + linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::PROGRESS, points ); +} + +} // anonymous namespace + +//PathConstrainer test cases +int UtcPathConstrainerApply(void) +{ + TestApplication application; + + Dali::Actor actor = Dali::Actor::New(); + + // Register a float property + Property::Index index = actor.RegisterProperty( "t", 0.0f ); + + Dali::Stage::GetCurrent().Add(actor); + + //Create a Path + Dali::Path path = Dali::Path::New(); + SetupPath(path); + + //Create a PathConstrainer + Dali::PathConstrainer pathConstrainer = Dali::PathConstrainer::New(); + SetupPathConstrainer( pathConstrainer ); + + //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t" + Vector2 range( 0.0f, 1.0f ); + pathConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION), Property(actor,index), range ); + + //Create an animation to animate the custom property + float durationSeconds(1.0f); + Dali::Animation animation = Dali::Animation::New(durationSeconds); + animation.AnimateTo(Dali::Property(actor,index),1.0f); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 20% progress */); + + Vector3 position, tangent; + path.Sample(0.2f, position, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 40% progress */); + path.Sample(0.4f, position, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 60% progress */); + path.Sample(0.6f, position, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 80% progress */); + path.Sample(0.8f, position, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 100% progress */); + path.Sample(1.0f, position, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* beyond the animation duration*/); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + END_TEST; +} + +int UtcPathConstrainerApplyRange(void) +{ + TestApplication application; + + Dali::Actor actor = Dali::Actor::New(); + + // Register a float property + Property::Index index = actor.RegisterProperty( "t", 0.0f ); + Dali::Stage::GetCurrent().Add(actor); + + //Create a Path + Dali::Path path = Dali::Path::New(); + SetupPath(path); + + //Create a PathConstrainer + Dali::PathConstrainer pathConstrainer = Dali::PathConstrainer::New(); + SetupPathConstrainer( pathConstrainer ); + + //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t" + Vector2 range( 100.0f, 300.0f ); + pathConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION), Property(actor,index), range ); + + + //Create an animation to animate the custom property + float durationSeconds(1.0f); + Dali::Animation animation = Dali::Animation::New(durationSeconds); + animation.AnimateTo(Dali::Property(actor,index),400.0f); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + + Vector3 position, tangent; + float tValue; + actor.GetProperty(index).Get(tValue); + float currentCursor = ( tValue - range.x ) / (range.y-range.x); + path.Sample(currentCursor, position, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + actor.GetProperty(index).Get(tValue); + currentCursor = ( tValue - range.x ) / (range.y-range.x); + path.Sample(currentCursor, position, tangent ); + path.Sample(0.5, position, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + actor.GetProperty(index).Get(tValue); + currentCursor = ( tValue - range.x ) / (range.y-range.x); + path.Sample(currentCursor, position, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 100% progress */); + actor.GetProperty(index).Get(tValue); + currentCursor = ( tValue - range.x ) / (range.y-range.x); + path.Sample(currentCursor, position, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* beyond the animation duration*/); + actor.GetProperty(index).Get(tValue); + currentCursor = ( tValue - range.x ) / (range.y-range.x); + path.Sample(currentCursor, position, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + END_TEST; +} + +int UtcPathConstrainerDestroy(void) +{ + TestApplication application; + + Dali::Actor actor = Dali::Actor::New(); + + // Register a float property + Property::Index index = actor.RegisterProperty( "t", 0.0f ); + Dali::Stage::GetCurrent().Add(actor); + + { + //Create a Path + Dali::Path path = Dali::Path::New(); + SetupPath(path); + + //Create a PathConstrainer + Dali::PathConstrainer pathConstrainer = Dali::PathConstrainer::New(); + SetupPathConstrainer( pathConstrainer ); + + //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t" + Vector2 range( 0.0f, 1.0f ); + pathConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION), Property(actor,index), range ); + + //Test that the constraint is correctly applied + actor.SetProperty(index,0.5f); + application.SendNotification(); + application.Render(static_cast(1.0f)); + + Vector3 position, tangent; + path.Sample(0.5f, position, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + } + + //PathConstrainer has been destroyed. Constraint in the actor should have been removed + actor.SetProperty(index,0.75f); + application.SendNotification(); + application.Render(static_cast(1.0f)); + + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION ); + + END_TEST; +} + +int UtcPathConstrainerRemove(void) +{ + TestApplication application; + + Dali::Actor actor = Dali::Actor::New(); + + // Register a float property + Property::Index index = actor.RegisterProperty( "t", 0.0f ); + Dali::Stage::GetCurrent().Add(actor); + + //Create a Path + Dali::Path path = Dali::Path::New(); + SetupPath(path); + + //Create a PathConstrainer + Dali::PathConstrainer pathConstrainer = Dali::PathConstrainer::New(); + SetupPathConstrainer( pathConstrainer ); + + //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t" + Vector2 range( 0.0f, 1.0f ); + pathConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION), Property(actor,index), range ); + + //Test that the constraint is correctly applied + actor.SetProperty(index,0.5f); + application.SendNotification(); + application.Render(static_cast(1.0f)); + + Vector3 position, tangent; + path.Sample(0.5f, position, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + //Remove constraint + pathConstrainer.Remove( actor ); + actor.SetProperty(index,0.75f); + application.SendNotification(); + application.Render(static_cast(1.0f)); + + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION ); + + END_TEST; +} + +//LinearConstrainer test cases +int UtcLinearConstrainerDownCast(void) +{ + TestApplication application; + Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New(); + + BaseHandle handle( linearConstrainer ); + Dali::LinearConstrainer linearConstrainer2 = Dali::LinearConstrainer::DownCast( handle ); + DALI_TEST_EQUALS( (bool)linearConstrainer2, true, TEST_LOCATION ); + + BaseHandle handle2; + Dali:: LinearConstrainer linearConstrainer3 = Dali::LinearConstrainer::DownCast( handle2 ); + DALI_TEST_EQUALS( (bool)linearConstrainer3, false, TEST_LOCATION ); + + END_TEST; +} + +int UtcLinearConstrainerCopyConstructor(void) +{ + TestApplication application; + Dali::LinearConstrainer linearConstrainer; + DALI_TEST_EQUALS( (bool)linearConstrainer, false, TEST_LOCATION ); + + linearConstrainer = Dali::LinearConstrainer::New(); + DALI_TEST_EQUALS( (bool)linearConstrainer, true, TEST_LOCATION ); + + // call the copy constructor + Dali::LinearConstrainer linearConstrainer2( linearConstrainer ); + DALI_TEST_EQUALS( (bool)linearConstrainer2, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcLinearConstrainerApply(void) +{ + TestApplication application; + + Dali::Actor actor = Dali::Actor::New(); + + // Register a float property + Property::Index index = actor.RegisterProperty( "t", 0.0f ); + + Dali::Stage::GetCurrent().Add(actor); + + + //Create a LinearConstrainer without specifying progress for values + Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New(); + SetupLinearConstrainerUniformProgress( linearConstrainer ); + + //Apply the linear constraint to the actor's position. The source property for the constraint will be the custom property "t" + Vector2 range( 0.0f, 1.0f ); + linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range ); + + //Create an animation to animate the custom property + float durationSeconds(1.0f); + Dali::Animation animation = Dali::Animation::New(durationSeconds); + animation.AnimateTo(Dali::Property(actor,index),1.0f); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 100% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* beyond the animation duration*/); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION ); + + //Setup a LinearConstrainer specifying the progress for each value + linearConstrainer.Remove(actor); + SetupLinearConstrainerNonUniformProgress( linearConstrainer ); + linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range ); + + actor.SetProperty(index,0.0f); + animation.Play(); + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 2.0f/3.0f, Math::MACHINE_EPSILON_1, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f/3.0f, Math::MACHINE_EPSILON_1, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 100% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* beyond the animation duration*/); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION ); + + END_TEST; +} + +int UtcLinearConstrainerApplyRange(void) +{ + TestApplication application; + + Dali::Actor actor = Dali::Actor::New(); + + // Register a float property + Property::Index index = actor.RegisterProperty( "t", 100.0f ); + Dali::Stage::GetCurrent().Add(actor); + + //Create a LinearConstrainer + Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New(); + SetupLinearConstrainerUniformProgress( linearConstrainer ); + + //Apply the linear constraint to the actor's position. The source property for the constraint will be the custom property "t" + Vector2 range( 100.0f, 300.0f ); + linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range ); + + + //Create an animation to animate the custom property + float durationSeconds(1.0f); + Dali::Animation animation = Dali::Animation::New(durationSeconds); + animation.AnimateTo(Dali::Property(actor,index),300.0f); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 100% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* beyond the animation duration*/); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION ); + + END_TEST; +} + +int UtcLinearConstrainerDestroy(void) +{ + TestApplication application; + + Dali::Actor actor = Dali::Actor::New(); + + // Register a float property + Property::Index index = actor.RegisterProperty( "t", 0.0f ); + Dali::Stage::GetCurrent().Add(actor); + + { + //Create a LinearConstrainer + Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New(); + SetupLinearConstrainerUniformProgress( linearConstrainer ); + + //Apply the linear constraint to the actor's position. The source property for the constraint will be the custom property "t" + Vector2 range( 0.0f, 1.0f ); + linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range ); + + //Test that the constraint is correctly applied + actor.SetProperty(index,0.5f); + application.SendNotification(); + application.Render(static_cast(1.0f)); + + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION ); + + } + + //LinearConstrainer has been destroyed. Constraint in the actor should have been removed + actor.SetProperty(index,0.75f); + application.SendNotification(); + application.Render(static_cast(1.0f)); + + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION ); + + END_TEST; +} + +int UtcLinearConstrainerRemove(void) +{ + TestApplication application; + + Dali::Actor actor = Dali::Actor::New(); + + // Register a float property + Property::Index index = actor.RegisterProperty( "t", 0.0f ); + Dali::Stage::GetCurrent().Add(actor); + + //Create a LinearConstrainer + Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New(); + SetupLinearConstrainerUniformProgress( linearConstrainer ); + + //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t" + Vector2 range( 0.0f, 1.0f ); + linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range ); + + //Test that the constraint is correctly applied + actor.SetProperty(index,0.5f); + application.SendNotification(); + application.Render(static_cast(1.0f)); + + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION ); + + //Remove constraint + linearConstrainer.Remove( actor ); + actor.SetProperty(index,0.75f); + application.SendNotification(); + application.Render(static_cast(1.0f)); + + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-Context.cpp b/automated-tests/src/dali-devel/utc-Dali-Context.cpp new file mode 100644 index 0000000..bdc5190 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-Context.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + + +namespace +{ +// Size of the VertexAttributeArray enables +// GLES specification states that there's minimum of +const unsigned int TEST_MAX_ATTRIBUTE_CACHE_SIZE = 8; + +enum TestAttribType +{ + ATTRIB_UNKNOWN = -1, + ATTRIB_POSITION, + ATTRIB_NORMAL, + ATTRIB_TEXCOORD, + ATTRIB_COLOR, + ATTRIB_BONE_WEIGHTS, + ATTRIB_BONE_INDICES, + ATTRIB_TYPE_LAST +}; + +// Create bitmap image +static BufferImage CreateBufferImage() +{ + BufferImage image = BufferImage::New(4,4,Pixel::RGBA8888); + + return image; +} + +static ImageActor CreateImageActor() +{ + BufferImage image = CreateBufferImage(); + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("Test ImageActor"); + return actor; +} + +} // anonymous namespace + + +// Positive test case for a method +int UtcDaliContextVertexAttribStartup(void) +{ + tet_infoline("Testing vertex attrib initial state in context"); + + TestApplication application; + + // start up + application.SendNotification(); + application.Render(); + application.Render(); + + // context class should initially set the vertex attrib locations to disable + // Make sure it has been modified + DALI_TEST_CHECK(application.GetGlAbstraction().GetVertexAttribArrayChanged()); + + // check the locations + for (unsigned int i = 0; i < TEST_MAX_ATTRIBUTE_CACHE_SIZE; i++) + { + DALI_TEST_CHECK( application.GetGlAbstraction().GetVertexAttribArrayState(i) == false); + } + + tet_result(TET_PASS); + END_TEST; +} + +// Tests to make the attribs only get set once when continually rendering an image actor +int UtcDaliContextVertexAttribImageRendering(void) +{ + tet_infoline("Testing vertex attrib rendering state in context with images"); + + TestApplication application; + + // start up + application.SendNotification(); + application.Render(); + application.Render(); + + // the vertex attribs get modified on startup to set them to disabled + // clear the flag to say they've changed + application.GetGlAbstraction().ClearVertexAttribArrayChanged(); + + + // create a test image actor + ImageActor imageActor(CreateImageActor()); + Stage::GetCurrent().Add(imageActor); + + + application.SendNotification(); + application.Render(); + application.Render(); + + // check to make sure the state has changed (the image renderer will enable some + // locations). + DALI_TEST_CHECK(application.GetGlAbstraction().GetVertexAttribArrayChanged()); + + // Now check to make sure the state is cached, and isn't being set each frame. + application.GetGlAbstraction().ClearVertexAttribArrayChanged(); + + application.Render(); + application.Render(); + application.Render(); + + // if it has changed then the caching has failed + DALI_TEST_CHECK(application.GetGlAbstraction().GetVertexAttribArrayChanged() == false); + + + tet_result(TET_PASS); + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-CullFace.cpp b/automated-tests/src/dali-devel/utc-Dali-CullFace.cpp new file mode 100644 index 0000000..5d980fe --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-CullFace.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +using namespace Dali; + +void cull_face_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void cull_face_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliSetGetCullFaceP(void) +{ + TestApplication application; + + ImageActor imageActor = ImageActor::New(); + + DALI_TEST_CHECK( CullNone == GetCullFace( imageActor ) ); + + SetCullFace( imageActor, CullBack ); + + DALI_TEST_CHECK( CullBack == GetCullFace( imageActor ) ); + + END_TEST; +} + +int UtcDaliSetCullFaceN(void) +{ + TestApplication application; + + try + { + ImageActor imageActor; + SetCullFace( imageActor, CullBack ); + DALI_TEST_CHECK( false ); // Should not reach here. + } + catch( ... ) + { + DALI_TEST_CHECK( true ); // Should throw + } + END_TEST; +} + +int UtcDaliGetCullFaceN(void) +{ + TestApplication application; + + try + { + ImageActor imageActor; + CullFaceMode mode = GetCullFace( imageActor ); + (void) mode; + DALI_TEST_CHECK( false ); // Should not reach here. + } + catch( ... ) + { + DALI_TEST_CHECK( true ); // Should throw + } + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-DistanceField.cpp b/automated-tests/src/dali-devel/utc-Dali-DistanceField.cpp new file mode 100644 index 0000000..b9ab2da --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-DistanceField.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include + +#include +#include +#include + +using std::max; +using namespace Dali; + +namespace +{ + +static const float ROTATION_EPSILON = 0.0001f; + +static unsigned char sourceImage[] = +{ + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF +}; + +} // anonymous namespace + + + +int UtcDaliGenerateDistanceField(void) +{ + unsigned char distanceField[4*4]; + + GenerateDistanceFieldMap(sourceImage, Size(8.0f, 8.0f), distanceField, Size(4.0f, 4.0f), 0, Size(4.0f, 4.0f)); + + if(distanceField[0] <= distanceField[5] && + distanceField[5] <= distanceField[10] && + distanceField[10] <= distanceField[15]) + { + tet_result(TET_PASS); + } + else + { + tet_result(TET_FAIL); + } + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-Geometry.cpp b/automated-tests/src/dali-devel/utc-Dali-Geometry.cpp new file mode 100644 index 0000000..7933b06 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-Geometry.cpp @@ -0,0 +1,670 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +using namespace Dali; + +#include + +void geometry_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void geometry_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +void TestConstraintNoBlue( Vector4& current, const PropertyInputContainer& inputs ) +{ + current.b = 0.0f; +} + +struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; }; + +PropertyBuffer CreateVertexBuffer( const std::string& aPosition, const std::string& aTexCoord ) +{ + const float halfQuadSize = .5f; + TexturedQuadVertex texturedQuadVertexData[4] = { + { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) }, + { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) }, + { Vector2(-halfQuadSize, halfQuadSize), Vector2(0.f, 1.f) }, + { Vector2( halfQuadSize, halfQuadSize), Vector2(1.f, 1.f) } }; + + Property::Map vertexFormat; + vertexFormat[aPosition] = Property::VECTOR2; + vertexFormat[aTexCoord] = Property::VECTOR2; + + PropertyBuffer vertexData = PropertyBuffer::New( vertexFormat, 4 ); + vertexData.SetData(texturedQuadVertexData); + + return vertexData; +} + +PropertyBuffer CreateIndexBuffer() +{ + unsigned short indexData[6] = { 0, 3, 1, 0, 2, 3 }; + Property::Map indexFormat; + indexFormat["indices"] = Property::INTEGER; + PropertyBuffer indices = PropertyBuffer::New( indexFormat, 3 ); + indices.SetData(indexData); + + return indices; +} + +} + + +int UtcDaliGeometryNew01(void) +{ + TestApplication application; + + Geometry geometry = Geometry::New(); + + DALI_TEST_EQUALS( (bool)geometry, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliGeometryNew02(void) +{ + TestApplication application; + Geometry geometry; + DALI_TEST_EQUALS( (bool)geometry, false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliGeometryCopyConstructor(void) +{ + TestApplication application; + + Geometry geometry = Geometry::New(); + + Geometry geometryCopy(geometry); + + DALI_TEST_EQUALS( (bool)geometryCopy, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliGeometryAssignmentOperator(void) +{ + TestApplication application; + + Geometry geometry = Geometry::New(); + + Geometry geometry2; + DALI_TEST_EQUALS( (bool)geometry2, false, TEST_LOCATION ); + + geometry2 = geometry; + DALI_TEST_EQUALS( (bool)geometry2, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliGeometryDownCast01(void) +{ + TestApplication application; + + Geometry geometry = Geometry::New(); + + BaseHandle handle(geometry); + Geometry geometry2 = Geometry::DownCast(handle); + DALI_TEST_EQUALS( (bool)geometry2, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliGeometryDownCast02(void) +{ + TestApplication application; + + Handle handle = Handle::New(); // Create a custom object + Geometry geometry = Geometry::DownCast(handle); + DALI_TEST_EQUALS( (bool)geometry, false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliGeometryAddVertexBuffer(void) +{ + TestApplication application; + + tet_infoline("Test AddVertexBuffer"); + + PropertyBuffer vertexBuffer1 = CreateVertexBuffer("aPosition1", "aTexCoord1" ); + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer( vertexBuffer1 ); + + Material material = CreateMaterial(1.f); + Renderer renderer = Renderer::New(geometry, material); + Actor actor = Actor::New(); + actor.SetSize(Vector3::ONE * 100.f); + actor.AddRenderer(renderer); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + + { + const TestGlAbstraction::BufferDataCalls& bufferDataCalls = + application.GetGlAbstraction().GetBufferDataCalls(); + + DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION ); + + DALI_TEST_EQUALS( bufferDataCalls[0], 4*sizeof( TexturedQuadVertex ), TEST_LOCATION ); + } + + // add the second vertex buffer + application.GetGlAbstraction().ResetBufferDataCalls(); + + PropertyBuffer vertexBuffer2 = CreateVertexBuffer( "aPosition2", "aTexCoord2" ); + geometry.AddVertexBuffer( vertexBuffer2 ); + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + + { + const TestGlAbstraction::BufferDataCalls& bufferDataCalls = + application.GetGlAbstraction().GetBufferDataCalls(); + + //Check that only the new buffer gets uploaded + DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( bufferDataCalls[0], 4*sizeof( TexturedQuadVertex ), TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliGeometryGetNumberOfVertexBuffers(void) +{ + TestApplication application; + + tet_infoline("Test GetNumberOfVertexBuffers"); + PropertyBuffer vertexBuffer1 = CreateVertexBuffer("aPosition1", "aTexCoord1" ); + PropertyBuffer vertexBuffer2 = CreateVertexBuffer("aPosition2", "aTexCoord2" ); + PropertyBuffer vertexBuffer3 = CreateVertexBuffer("aPosition3", "aTexCoord3" ); + + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer( vertexBuffer1 ); + DALI_TEST_EQUALS( geometry.GetNumberOfVertexBuffers(), 1u, TEST_LOCATION ); + + geometry.AddVertexBuffer( vertexBuffer2 ); + geometry.AddVertexBuffer( vertexBuffer3 ); + DALI_TEST_EQUALS( geometry.GetNumberOfVertexBuffers(), 3u, TEST_LOCATION ); + + geometry.RemoveVertexBuffer( 2u ); + DALI_TEST_EQUALS( geometry.GetNumberOfVertexBuffers(), 2u, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliGeometryRemoveVertexBuffer(void) +{ + TestApplication application; + + tet_infoline("Test RemoveVertexBuffer"); + + PropertyBuffer vertexBuffer1 = CreateVertexBuffer("aPosition1", "aTexCoord1" ); + PropertyBuffer vertexBuffer2 = CreateVertexBuffer("aPosition2", "aTexCoord2" ); + + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer( vertexBuffer1 ); + + Material material = CreateMaterial(1.f); + Renderer renderer = Renderer::New(geometry, material); + Actor actor = Actor::New(); + actor.SetSize(Vector3::ONE * 100.f); + actor.AddRenderer(renderer); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( geometry.GetNumberOfVertexBuffers(), 1u, TEST_LOCATION ); + + geometry.RemoveVertexBuffer( 0 ); + geometry.AddVertexBuffer( vertexBuffer2 ); + DALI_TEST_EQUALS( geometry.GetNumberOfVertexBuffers(), 1u, TEST_LOCATION ); + + geometry.RemoveVertexBuffer( 0 ); + DALI_TEST_EQUALS( geometry.GetNumberOfVertexBuffers(), 0u, TEST_LOCATION ); + + //Todo: test by checking the BufferDataCalls + // make sure the vertex buffer in actually removed from gl + + END_TEST; +} + +int UtcDaliGeometrySetIndexBuffer(void) +{ + TestApplication application; + + tet_infoline("Test SetIndexBuffer"); + + PropertyBuffer vertexBuffer = CreateVertexBuffer("aPosition", "aTexCoord" ); + PropertyBuffer indexBuffer = CreateIndexBuffer( ); + + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer( vertexBuffer ); + + Material material = CreateMaterial(1.f); + Renderer renderer = Renderer::New(geometry, material); + Actor actor = Actor::New(); + actor.SetSize(Vector3::ONE * 100.f); + actor.AddRenderer(renderer); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + + { + const TestGlAbstraction::BufferDataCalls& bufferDataCalls = + application.GetGlAbstraction().GetBufferDataCalls(); + + DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION ); + + DALI_TEST_EQUALS( bufferDataCalls[0], 4*sizeof( TexturedQuadVertex ), TEST_LOCATION ); + } + + // Set index buffer + application.GetGlAbstraction().ResetBufferDataCalls(); + + geometry.SetIndexBuffer( indexBuffer ); + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + + { + const TestGlAbstraction::BufferDataCalls& bufferDataCalls = + application.GetGlAbstraction().GetBufferDataCalls(); + + //Only the index buffer should be uploaded + DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION ); + + // should be unsigned short instead of unsigned int + DALI_TEST_EQUALS( bufferDataCalls[0], 6*sizeof( unsigned short ), TEST_LOCATION ); + } + + + END_TEST; +} + +int UtcDaliGeometrySetGetGeometryType(void) +{ + TestApplication application; + + tet_infoline("Test SetGeometryType and GetGeometryType"); + + unsigned int numVertex = 4u; + PropertyBuffer vertexBuffer = CreateVertexBuffer("aPosition", "aTexCoord" ); + + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer( vertexBuffer ); + + Material material = CreateMaterial(1.f); + Renderer renderer = Renderer::New(geometry, material); + Actor actor = Actor::New(); + actor.SetSize(Vector3::ONE * 100.f); + actor.AddRenderer(renderer); + Stage::GetCurrent().Add(actor); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + + /****************************************************/ + // Default (TRIANGLES), no index buffer + drawTrace.Reset(); + drawTrace.Enable(true); + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + drawTrace.Enable( false ); + + // Test the default geometry type is GL_TRIANGLE + // no index buffer, call glDrawArrays, + DALI_TEST_EQUALS( drawTrace.CountMethod( "DrawArrays" ), 2, TEST_LOCATION); + std::stringstream out; + out << GL_TRIANGLES << ", " << 0 << ", " << numVertex; + DALI_TEST_EQUALS( drawTrace.TestMethodAndParams(1, "DrawArrays", out.str()), true, TEST_LOCATION); + + DALI_TEST_EQUALS( geometry.GetGeometryType(), Geometry::TRIANGLES, TEST_LOCATION); + + /*********************************************************/ + // LINES, no index buffer + geometry.SetGeometryType( Geometry::LINES ); + + drawTrace.Reset(); + drawTrace.Enable(true); + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + drawTrace.Enable( false ); + + // geometry type is set as GL_LINES + // no index buffer, call glDrawArrays, + DALI_TEST_EQUALS( drawTrace.CountMethod( "DrawArrays" ), 2, TEST_LOCATION); + out.str(""); + out << GL_LINES << ", " << 0 << ", " << numVertex; + DALI_TEST_EQUALS( drawTrace.TestMethodAndParams(1, "DrawArrays", out.str()), true, TEST_LOCATION); + + DALI_TEST_EQUALS( geometry.GetGeometryType(), Geometry::LINES, TEST_LOCATION); + + /*****************************************************/ + //POINTS + geometry.SetGeometryType( Geometry::POINTS ); + + drawTrace.Reset(); + drawTrace.Enable(true); + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + drawTrace.Enable( false ); + + // geometry type is set as GL_POINTS + // no index buffer, call glDrawArrays, + DALI_TEST_EQUALS( drawTrace.CountMethod( "DrawArrays" ), 2, TEST_LOCATION); + out.str(""); + out << GL_POINTS << ", " << 0 << ", " << numVertex; + DALI_TEST_EQUALS( drawTrace.TestMethodAndParams(1, "DrawArrays", out.str()), true, TEST_LOCATION); + + DALI_TEST_EQUALS( geometry.GetGeometryType(), Geometry::POINTS, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliGeometrySetGetRequireDepthTesting(void) +{ + TestApplication application; + + tet_infoline("Test SetRequiresDepthTesting, GetRequiresDepthTesting"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( geometry.GetRequiresDepthTesting(), false, TEST_LOCATION ); + + geometry.SetRequiresDepthTesting(true); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + application.SendNotification(); + application.Render(); +// TODO: Not supported yes +// TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace(); +// std::ostringstream out; +// out << GL_DEPTH_TEST; +// DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", out.str().c_str() ) ); + + DALI_TEST_EQUALS( geometry.GetRequiresDepthTesting(), true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliGeometryPropertyRequiresDepthTest(void) +{ + TestApplication application; + + tet_infoline("Test SetRequiresDepthTesting, GetRequiresDepthTesting"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( geometry.GetProperty(Geometry::Property::REQUIRES_DEPTH_TEST), false, TEST_LOCATION ); + + geometry.SetProperty(Geometry::Property::REQUIRES_DEPTH_TEST, true ); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + application.SendNotification(); + application.Render(); +// TODO: Not supported yes +// TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace(); +// std::ostringstream out; +// out << GL_DEPTH_TEST; +// DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", out.str().c_str() ) ); + + DALI_TEST_EQUALS( geometry.GetProperty(Geometry::Property::REQUIRES_DEPTH_TEST), true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliGeometryConstraint(void) +{ + TestApplication application; + + tet_infoline("Test that a custom geometry property can be constrained"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = geometry.RegisterProperty( "uFadeColor", initialColor ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( geometry.GetProperty(colorIndex), initialColor, TEST_LOCATION ); + + // Apply constraint + Constraint constraint = Constraint::New( geometry, colorIndex, TestConstraintNoBlue ); + constraint.Apply(); + application.SendNotification(); + application.Render(0); + + // Expect no blue component in either buffer - yellow + DALI_TEST_EQUALS( geometry.GetProperty(colorIndex), Color::YELLOW, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( geometry.GetProperty(colorIndex), Color::YELLOW, TEST_LOCATION ); + + geometry.RemoveConstraints(); + geometry.SetProperty(colorIndex, Color::WHITE ); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( geometry.GetProperty(colorIndex), Color::WHITE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliGeometryConstraint02(void) +{ + TestApplication application; + + tet_infoline("Test that a uniform map geometry property can be constrained"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = geometry.RegisterProperty( "uFadeColor", initialColor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION ); + + // Apply constraint + Constraint constraint = Constraint::New( geometry, colorIndex, TestConstraintNoBlue ); + constraint.Apply(); + application.SendNotification(); + application.Render(0); + + // Expect no blue component in either buffer - yellow + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + application.Render(0); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + geometry.RemoveConstraints(); + geometry.SetProperty(colorIndex, Color::WHITE ); + application.SendNotification(); + application.Render(0); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::WHITE, TEST_LOCATION ); + + END_TEST; +} + + + +int UtcDaliGeometryAnimatedProperty01(void) +{ + TestApplication application; + + tet_infoline("Test that a custom geometry property can be animated"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = geometry.RegisterProperty( "uFadeColor", initialColor ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( geometry.GetProperty(colorIndex), initialColor, TEST_LOCATION ); + + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, initialColor); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( geometry, colorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_EQUALS( geometry.GetProperty(colorIndex), Color::WHITE * 0.5f, TEST_LOCATION ); + + application.Render(500); + + DALI_TEST_EQUALS( geometry.GetProperty(colorIndex), Color::TRANSPARENT, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliGeometryAnimatedProperty02(void) +{ + TestApplication application; + + tet_infoline("Test that a uniform map geometry property can be animated"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = geometry.RegisterProperty( "uFadeColor", initialColor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION ); + + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, initialColor); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( geometry, colorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::WHITE * 0.5f, TEST_LOCATION ); + + application.Render(500); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::TRANSPARENT, TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-Hash.cpp b/automated-tests/src/dali-devel/utc-Dali-Hash.cpp new file mode 100644 index 0000000..79c3881 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-Hash.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +void utc_dali_hash_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_hash_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +int UtcDaliHash(void) +{ + // To fully test the Hash distribution we need to use a tool like http://code.google.com/p/smhasher/ + // DALi currently uses the hash for variable length strings which come from: + // shader vert+frag source, font family + style, image filename. + TestApplication application; + + tet_infoline("UtcDaliHash"); + + const std::string testString1( "highp vec4 glowColor = vec4( uGlowColor.rgb, uGlowColor.a * clampedColor.a );"); + const std::string testString2( "lowp vec4 glowColor = vec4( uGlowColor.rgb, uGlowColor.a * clampedColor.a );"); + + DALI_TEST_CHECK( Dali::CalculateHash( testString1 ) != Dali::CalculateHash( testString2 ) ); + DALI_TEST_CHECK( Dali::CalculateHash( testString1, testString2 ) != Dali::CalculateHash( testString2, testString1 ) ); + + END_TEST; +} + +int UtcDaliHashNegative(void) +{ + // negative test, check hash value == initial value + const std::string emptyString; + + DALI_TEST_CHECK( Dali::CalculateHash( emptyString ) != 0 ); + DALI_TEST_CHECK( Dali::CalculateHash( emptyString, emptyString ) != 0 ); + + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-HitTestAlgorithm.cpp b/automated-tests/src/dali-devel/utc-Dali-HitTestAlgorithm.cpp new file mode 100644 index 0000000..ae04a17 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-HitTestAlgorithm.cpp @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include + +using namespace Dali; + +namespace +{ + +/** + * The functor to be used in the hit-test algorithm to check whether the actor is hittable. + */ +bool IsActorHittableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType type) +{ + bool hittable = false; + + switch (type) + { + case Dali::HitTestAlgorithm::CHECK_ACTOR: + { + // Check whether the actor is visible and not fully transparent. + if( actor.IsVisible() + && actor.GetCurrentWorldColor().a > 0.01f) // not FULLY_TRANSPARENT + { + // Check whether the actor has the specific name "HittableActor" + if(actor.GetName() == "HittableActor") + { + hittable = true; + } + } + break; + } + case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE: + { + if( actor.IsVisible() ) // Actor is visible, if not visible then none of its children are visible. + { + hittable = true; + } + break; + } + default: + { + break; + } + } + + return hittable; +}; + + +bool DefaultIsActorTouchableFunction(Dali::Actor actor, Dali::HitTestAlgorithm::TraverseType type) +{ + bool hittable = false; + + switch (type) + { + case Dali::HitTestAlgorithm::CHECK_ACTOR: + { + if( actor.IsVisible() && + actor.IsSensitive() && + actor.GetCurrentWorldColor().a > 0.01f) + { + hittable = true; + } + break; + } + case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE: + { + if( actor.IsVisible() && // Actor is visible, if not visible then none of its children are visible. + actor.IsSensitive()) // Actor is sensitive, if insensitive none of its children should be hittable either. + { + hittable = true; + } + break; + } + default: + { + break; + } + } + + return hittable; +}; + +} // anonymous namespace + + +// Positive test case for a method +int UtcDaliHitTestAlgorithmWithFunctor(void) +{ + TestApplication application; + tet_infoline("Testing Dali::HitTestAlgorithm functor"); + + Stage stage = Stage::GetCurrent(); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + actor.SetName("NonHittableActor"); + stage.Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + Vector2 screenCoordinates( 10.0f, 10.0f ); + Vector2 localCoordinates; + actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + + // Perform a hit-test at the given screen coordinates + Dali::HitTestAlgorithm::Results results; + Dali::HitTestAlgorithm::HitTest( stage, screenCoordinates, results, IsActorHittableFunction ); + DALI_TEST_CHECK( results.actor != actor ); + + actor.SetName("HittableActor"); + + results.actor = Actor(); + results.actorCoordinates = Vector2::ZERO; + + // Perform a hit-test at the given screen coordinates + Dali::HitTestAlgorithm::HitTest( stage, screenCoordinates, results, IsActorHittableFunction ); + DALI_TEST_CHECK( results.actor == actor ); + DALI_TEST_EQUALS( localCoordinates, results.actorCoordinates, 0.1f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliHitTestAlgorithmWithFunctorOnRenderTask(void) +{ + TestApplication application; + tet_infoline("Testing Dali::HitTestAlgorithm functor, specific to a given render task"); + + Stage stage = Stage::GetCurrent(); + Size stageSize = stage.GetSize(); + RenderTaskList taskList = stage.GetRenderTaskList(); + + Actor actor[2]; + + for( int i=0; i<2; i++ ) + { + actor[i] = Actor::New(); + actor[i].SetSize(100.f, 100.f); + actor[i].SetParentOrigin(ParentOrigin::TOP_LEFT); + actor[i].SetAnchorPoint(AnchorPoint::TOP_LEFT); + actor[i].SetName("HittableActor"); + stage.Add(actor[i]); + } + Vector2 position( 50.f, 40.f ); + actor[1].SetPosition( position.x, position.y ); + + RenderTask renderTask[2]; + renderTask[0] = taskList.GetTask( 0u ); + + FrameBufferImage frameBufferImage = FrameBufferImage::New(stageSize.width, stageSize.height, Pixel::A8, Image::NEVER); + renderTask[1] = taskList.CreateTask(); + renderTask[1].SetSourceActor( actor[1] ); + renderTask[1].SetExclusive( true ); + renderTask[1].SetInputEnabled( true ); + renderTask[1].SetTargetFrameBuffer( frameBufferImage ); + renderTask[1].SetRefreshRate( RenderTask::REFRESH_ONCE ); + renderTask[1].SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION ); + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + // Perform a hit-test at the given screen coordinates with different render tasks + + Dali::HitTestAlgorithm::Results results; + Vector2 screenCoordinates( 25.f, 25.f ); + + Dali::HitTestAlgorithm::HitTest( renderTask[0], screenCoordinates, results, IsActorHittableFunction ); + DALI_TEST_CHECK( results.actor == actor[0] ); + DALI_TEST_EQUALS( screenCoordinates, results.actorCoordinates, 0.1f, TEST_LOCATION ); + + results.actor = Actor(); + results.actorCoordinates = Vector2::ZERO; + Dali::HitTestAlgorithm::HitTest( renderTask[1], screenCoordinates, results, IsActorHittableFunction ); + DALI_TEST_CHECK( !results.actor ); + DALI_TEST_EQUALS( Vector2::ZERO, results.actorCoordinates, 0.1f, TEST_LOCATION ); + + screenCoordinates.x = 80.f; + screenCoordinates.y = 70.f; + + results.actor = Actor(); + results.actorCoordinates = Vector2::ZERO; + Dali::HitTestAlgorithm::HitTest( renderTask[0], screenCoordinates, results, IsActorHittableFunction ); + DALI_TEST_CHECK( results.actor == actor[0] ); + DALI_TEST_EQUALS( screenCoordinates, results.actorCoordinates, 0.1f, TEST_LOCATION ); + + results.actor = Actor(); + results.actorCoordinates = Vector2::ZERO; + Dali::HitTestAlgorithm::HitTest( renderTask[1], screenCoordinates, results, IsActorHittableFunction ); + DALI_TEST_CHECK( results.actor == actor[1]); + DALI_TEST_EQUALS( screenCoordinates - position, results.actorCoordinates, 0.1f, TEST_LOCATION ); + + screenCoordinates.x = 120.f; + screenCoordinates.y = 130.f; + + results.actor = Actor(); + results.actorCoordinates = Vector2::ZERO; + Dali::HitTestAlgorithm::HitTest( renderTask[0], screenCoordinates, results, IsActorHittableFunction ); + DALI_TEST_CHECK( !results.actor ); + DALI_TEST_EQUALS( Vector2::ZERO, results.actorCoordinates, 0.1f, TEST_LOCATION ); + + results.actor = Actor(); + results.actorCoordinates = Vector2::ZERO; + Dali::HitTestAlgorithm::HitTest( renderTask[1], screenCoordinates, results, IsActorHittableFunction ); + DALI_TEST_CHECK( results.actor == actor[1]); + DALI_TEST_EQUALS( screenCoordinates - position, results.actorCoordinates, 0.1f, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliHitTestAlgorithmOrtho01(void) +{ + TestApplication application; + tet_infoline("Testing Dali::HitTestAlgorithm with parallel Ortho camera()"); + + Stage stage = Stage::GetCurrent(); + RenderTaskList renderTaskList = stage.GetRenderTaskList(); + RenderTask defaultRenderTask = renderTaskList.GetTask(0u); + Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor(); + + Vector2 stageSize ( stage.GetSize() ); + cameraActor.SetOrthographicProjection( stageSize ); + cameraActor.SetPosition(0.0f, 0.0f, 1600.0f); + + Vector2 actorSize( stageSize * 0.5f ); + // Create two actors with half the size of the stage and set them to be partially overlapping + Actor blue = Actor::New(); + blue.SetName( "Blue" ); + blue.SetAnchorPoint( AnchorPoint::CENTER ); + blue.SetParentOrigin( Vector3(1.0f/3.0f, 1.0f/3.0f, 0.5f) ); + blue.SetSize( actorSize ); + blue.SetZ(30.0f); + + Actor green = Actor::New( ); + green.SetName( "Green" ); + green.SetAnchorPoint( AnchorPoint::CENTER ); + green.SetParentOrigin( Vector3(2.0f/3.0f, 2.0f/3.0f, 0.5f) ); + green.SetSize( actorSize ); + + // Add the actors to the view + stage.Add( blue ); + stage.Add( green ); + + // Render and notify + application.SendNotification(); + application.Render(0); + application.Render(10); + + HitTestAlgorithm::Results results; + HitTest(stage, stageSize / 2.0f, results, &DefaultIsActorTouchableFunction); + DALI_TEST_CHECK( results.actor == green ); + DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 1.0f/6.0f, TEST_LOCATION ); + + HitTest(stage, stageSize / 3.0f, results, &DefaultIsActorTouchableFunction); + DALI_TEST_CHECK( results.actor == blue ); + DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION ); + + HitTest(stage, stageSize * 2.0f / 3.0f, results, &DefaultIsActorTouchableFunction); + DALI_TEST_CHECK( results.actor == green ); + DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliHitTestAlgorithmOrtho02(void) +{ + TestApplication application; + tet_infoline("Testing Dali::HitTestAlgorithm with offset Ortho camera()"); + + Stage stage = Stage::GetCurrent(); + RenderTaskList renderTaskList = stage.GetRenderTaskList(); + RenderTask defaultRenderTask = renderTaskList.GetTask(0u); + Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor(); + + Vector2 stageSize ( stage.GetSize() ); + cameraActor.SetOrthographicProjection(-stageSize.x * 0.3f, stageSize.x * 0.7f, + stageSize.y * 0.3f, -stageSize.y * 0.7f, + 800.0f, 4895.0f); + cameraActor.SetPosition(0.0f, 0.0f, 1600.0f); + + Vector2 actorSize( stageSize * 0.5f ); + // Create two actors with half the size of the stage and set them to be partially overlapping + Actor blue = Actor::New(); + blue.SetName( "Blue" ); + blue.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + blue.SetParentOrigin( Vector3(0.2f, 0.2f, 0.5f) ); + blue.SetSize( actorSize ); + blue.SetZ(30.0f); + + Actor green = Actor::New( ); + green.SetName( "Green" ); + green.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + green.SetParentOrigin( Vector3(0.4f, 0.4f, 0.5f) ); + green.SetSize( actorSize ); + + // Add the actors to the view + stage.Add( blue ); + stage.Add( green ); + + // Render and notify + application.SendNotification(); + application.Render(0); + application.Render(10); + + { + HitTestAlgorithm::Results results; + HitTest(stage, Vector2( 240.0f, 400.0f ), results, &DefaultIsActorTouchableFunction); + DALI_TEST_CHECK( results.actor == green ); + DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.6f, 0.01f, TEST_LOCATION ); + } + + { + HitTestAlgorithm::Results results; + HitTest(stage, Vector2( 0.001f, 0.001f ), results, &DefaultIsActorTouchableFunction); + DALI_TEST_CHECK( results.actor == blue ); + DALI_TEST_EQUALS( results.actorCoordinates, Vector2( 0.001f, 0.001f ), 0.001f, TEST_LOCATION ); + } + + { + HitTestAlgorithm::Results results; + HitTest(stage, stageSize, results, &DefaultIsActorTouchableFunction); + DALI_TEST_CHECK( ! results.actor ); + DALI_TEST_EQUALS( results.actorCoordinates, Vector2::ZERO, TEST_LOCATION ); + } + + // Just inside green + { + HitTestAlgorithm::Results results; + HitTest(stage, stageSize*0.69f, results, &DefaultIsActorTouchableFunction); + DALI_TEST_CHECK( results.actor == green ); + DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.98f, 0.01f, TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliHitTestAlgorithmStencil(void) +{ + TestApplication application; + tet_infoline("Testing Dali::HitTestAlgorithm with a stencil"); + + Stage stage = Stage::GetCurrent(); + Actor rootLayer = stage.GetRootLayer(); + rootLayer.SetName( "RootLayer" ); + + // Create a layer + Layer layer = Layer::New(); + layer.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + layer.SetParentOrigin( ParentOrigin::TOP_LEFT ); + layer.SetName( "layer" ); + stage.Add( layer ); + + // Create a stencil and add that to the layer + Actor stencil = ImageActor::New(Dali::BufferImage::WHITE() ); + stencil.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + stencil.SetParentOrigin( ParentOrigin::TOP_LEFT ); + stencil.SetSize( 50.0f, 50.0f ); + stencil.SetDrawMode( DrawMode::STENCIL ); + stencil.SetName( "stencil" ); + layer.Add( stencil ); + + // Create a renderable actor and add that to the layer + Actor layerHitActor = ImageActor::New(); + layerHitActor.SetSize( 100.0f, 100.0f ); + layerHitActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + layerHitActor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + layerHitActor.SetName( "layerHitActor" ); + layer.Add( layerHitActor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Hit within stencil and actor + { + HitTestAlgorithm::Results results; + HitTest(stage, Vector2( 10.0f, 10.0f ), results, &DefaultIsActorTouchableFunction); + DALI_TEST_CHECK( results.actor == layerHitActor ); + tet_printf( "Hit: %s\n", ( results.actor ? results.actor.GetName().c_str() : "NULL" ) ); + } + + // Hit within actor but outside of stencil, should hit the root-layer + { + HitTestAlgorithm::Results results; + HitTest(stage, Vector2( 60.0f, 60.0f ), results, &DefaultIsActorTouchableFunction); + DALI_TEST_CHECK( results.actor == rootLayer ); + tet_printf( "Hit: %s\n", ( results.actor ? results.actor.GetName().c_str() : "NULL" ) ); + } + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-Material.cpp b/automated-tests/src/dali-devel/utc-Dali-Material.cpp new file mode 100644 index 0000000..433520f --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-Material.cpp @@ -0,0 +1,1169 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +using namespace Dali; + +#include + +namespace +{ +void TestConstraintNoBlue( Vector4& current, const PropertyInputContainer& inputs ) +{ + current.b = 0.0f; +} +} + + +void material_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void material_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliMaterialNew01(void) +{ + TestApplication application; + + Shader shader = Shader::New("vertexSrc", "fragmentSrc"); + Material material = Material::New(shader); + + DALI_TEST_CHECK( material ); + END_TEST; +} + +int UtcDaliMaterialNew02(void) +{ + TestApplication application; + Material material; + DALI_TEST_CHECK( !material ); + END_TEST; +} + +int UtcDaliMaterialCopyConstructor(void) +{ + TestApplication application; + + Shader shader = Shader::New("vertexSrc", "fragmentSrc"); + Image image = BufferImage::New(32, 32, Pixel::RGBA8888); + Sampler sampler = Sampler::New(image, "sTexture"); + Material material = Material::New(shader); + material.AddSampler( sampler ); + + Material materialCopy(material); + + DALI_TEST_CHECK( materialCopy ); + DALI_TEST_EQUALS( materialCopy.GetSamplerAt(0), sampler, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialAssignmentOperator(void) +{ + TestApplication application; + + Shader shader = Shader::New("vertexSrc", "fragmentSrc"); + Image image = BufferImage::New(32, 32, Pixel::RGBA8888); + Sampler sampler = Sampler::New(image, "sTexture"); + Material material = Material::New(shader); + material.AddSampler( sampler ); + + Material material2; + DALI_TEST_CHECK( !material2 ); + + material2 = material; + DALI_TEST_CHECK( material2 ); + DALI_TEST_EQUALS( material2.GetSamplerAt(0), sampler, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialDownCast01(void) +{ + TestApplication application; + Shader shader = Shader::New("vertexSrc", "fragmentSrc"); + Material material = Material::New(shader); + + BaseHandle handle(material); + Material material2 = Material::DownCast(handle); + DALI_TEST_CHECK( material2 ); + + END_TEST; +} + +int UtcDaliMaterialDownCast02(void) +{ + TestApplication application; + + Handle handle = Handle::New(); // Create a custom object + Material material = Material::DownCast(handle); + DALI_TEST_CHECK( !material ); + END_TEST; +} + +int UtcDaliMaterialSetShader(void) +{ + TestApplication application; + + tet_infoline("Test SetShader(shader) "); + + Shader shader1 = Shader::New( "vertexSrc1", "fragmentSrc1" ); + shader1.RegisterProperty( "uFadeColor", Color::CYAN ); + + Shader shader2 = Shader::New( "vertexSrc1", "fragmentSrc1" ); + shader2.RegisterProperty( "uFadeColor", Color::MAGENTA ); + + // shader1 + Material material = Material::New(shader1); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + application.SendNotification(); + application.Render(0); + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::CYAN, TEST_LOCATION ); + + // shader2 + material.SetShader( shader2 ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::MAGENTA, TEST_LOCATION ); + + // shader1 + material.SetShader( shader1 ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::CYAN, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialGetShader(void) +{ + TestApplication application; + + tet_infoline("Test GetShader() "); + + Shader shader1 = Shader::New( "vertexSrc1", "fragmentSrc1" ); + Shader shader2 = Shader::New( "vertexSrc1", "fragmentSrc1" ); + + // shader1 + Material material = Material::New(shader1); + DALI_TEST_EQUALS( shader1, material.GetShader(), TEST_LOCATION ); + + // shader2 + material.SetShader( shader2 ); + DALI_TEST_EQUALS( shader2, material.GetShader(), TEST_LOCATION ); + + // shader1 + material.SetShader( shader1 ); + DALI_TEST_EQUALS( shader1, material.GetShader(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialAddSampler(void) +{ + TestApplication application; + + tet_infoline("Test AddSampler(sampler)"); + + Image image = BufferImage::New(32, 32, Pixel::RGBA8888); + Sampler sampler1 = Sampler::New(image, "sTexture1"); + Sampler sampler2 = Sampler::New(image, "sTexture2"); + + Material material = CreateMaterial(0.5f); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetParentOrigin( ParentOrigin::CENTER ); + actor.SetSize(400, 400); + Stage::GetCurrent().Add( actor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + int textureUnit=-1; + + material.AddSampler( sampler1 ); + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK( gl.GetUniformValue( "sTexture1", textureUnit ) ); + DALI_TEST_EQUALS( textureUnit, 0, TEST_LOCATION ); + + material.AddSampler( sampler2 ); + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK( gl.GetUniformValue( "sTexture2", textureUnit ) ); + DALI_TEST_EQUALS( textureUnit, 1, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialGetNumberOfSampler(void) +{ + TestApplication application; + + tet_infoline("Test GetNumberOfSampler()"); + + Image image = BufferImage::New(32, 32, Pixel::RGBA8888); + Sampler sampler0 = Sampler::New(image, "sTexture0"); + Sampler sampler1 = Sampler::New(image, "sTexture1"); + Sampler sampler2 = Sampler::New(image, "sTexture2"); + Sampler sampler3 = Sampler::New(image, "sTexture3"); + Sampler sampler4 = Sampler::New(image, "sTexture4"); + + Material material = CreateMaterial(0.5f); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetParentOrigin( ParentOrigin::CENTER ); + actor.SetSize(400, 400); + Stage::GetCurrent().Add( actor ); + + material.AddSampler( sampler0 ); + material.AddSampler( sampler1 ); + DALI_TEST_EQUALS( material.GetNumberOfSamplers(), 2u, TEST_LOCATION ); + + material.AddSampler( sampler2 ); + material.AddSampler( sampler3 ); + material.AddSampler( sampler4 ); + DALI_TEST_EQUALS( material.GetNumberOfSamplers(), 5u, TEST_LOCATION ); + + material.RemoveSampler(3); // remove sampler3 + DALI_TEST_EQUALS( material.GetNumberOfSamplers(), 4u, TEST_LOCATION ); + + material.RemoveSampler(3); // remove sampler4 + material.RemoveSampler(0); // remove sampler0 + DALI_TEST_EQUALS( material.GetNumberOfSamplers(), 2u, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialRemoveSampler(void) +{ + TestApplication application; + + tet_infoline("Test RemoveSampler(index)"); + Image image = BufferImage::New(32, 32, Pixel::RGBA8888); + Sampler sampler1 = Sampler::New(image, "sTexture1"); + Sampler sampler2 = Sampler::New(image, "sTexture2"); + + Material material = CreateMaterial(0.5f); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetParentOrigin( ParentOrigin::CENTER ); + actor.SetSize(400, 400); + Stage::GetCurrent().Add( actor ); + + material.AddSampler( sampler1 ); + material.AddSampler( sampler2 ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + int textureUnit=-1; + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK( gl.GetUniformValue( "sTexture1", textureUnit ) ); + DALI_TEST_EQUALS( textureUnit, 0, TEST_LOCATION ); + DALI_TEST_CHECK( gl.GetUniformValue( "sTexture2", textureUnit ) ); + DALI_TEST_EQUALS( textureUnit, 1, TEST_LOCATION ); + + material.RemoveSampler(0); // remove sampler1 + application.SendNotification(); + application.Render(); + // Todo: test the sampler is removed from gl, cannot pass this test with current implementation + //DALI_TEST_CHECK( ! gl.GetUniformValue( "sTexture1", textureUnit ) ); + DALI_TEST_EQUALS( material.GetNumberOfSamplers(), 1u, TEST_LOCATION ); + + material.RemoveSampler(0); // remove sampler2 + application.SendNotification(); + application.Render(); + // Todo: test the sampler is removed from gl, cannot pass this test with current implementation + //DALI_TEST_CHECK( ! gl.GetUniformValue( "sTexture2", textureUnit ) ); + DALI_TEST_EQUALS( material.GetNumberOfSamplers(), 0u, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialGetSamplerAt(void) +{ + TestApplication application; + + tet_infoline("Test GetSamplerAt(index)"); + + Image image = BufferImage::New(16, 16, Pixel::RGBA8888); + Sampler sampler1 = Sampler::New(image, "sTexture1"); + Sampler sampler2 = Sampler::New(image, "sTexture2"); + Sampler sampler3 = Sampler::New(image, "sTexture3"); + + Material material = CreateMaterial(0.5f); + material.AddSampler( sampler1 ); + material.AddSampler( sampler2 ); + material.AddSampler( sampler3 ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetParentOrigin( ParentOrigin::CENTER ); + actor.SetSize(400, 400); + Stage::GetCurrent().Add( actor ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( material.GetSamplerAt( 0 ), sampler1, TEST_LOCATION ); + DALI_TEST_EQUALS( material.GetSamplerAt( 1 ), sampler2, TEST_LOCATION ); + DALI_TEST_EQUALS( material.GetSamplerAt( 2 ), sampler3, TEST_LOCATION ); + + Sampler sampler = material.GetSamplerAt( 1 ); + DALI_TEST_EQUALS( sampler.GetImage().GetWidth(), 16u, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialSetFaceCullingMode(void) +{ + TestApplication application; + + tet_infoline("Test SetFaceCullingMode(cullingMode)"); + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(0.5f); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& cullFaceStack = gl.GetCullFaceTrace(); + cullFaceStack.Reset(); + gl.EnableCullFaceCallTrace(true); + + material.SetFaceCullingMode( Material::CULL_BACK_AND_FRONT); + application.SendNotification(); + application.Render(); + + // Todo: test the glCullFace(GL_FRONT_AND_BACK) is actually been called, cannot pass this test with current implementation + DALI_TEST_EQUALS( cullFaceStack.CountMethod( "CullFace" ), 0, TEST_LOCATION); + //string parameter("GL_FRONT_AND_BACK" ); + //DALI_TEST_CHECK( cullFaceStack.TestMethodAndParams(0, "CullFace", parameter) ); + + END_TEST; +} + +int UtcDaliMaterialBlendingOptions01(void) +{ + TestApplication application; + + tet_infoline("Test SetBlendFunc(src, dest) "); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(0.5f); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + material.SetBlendFunc(BlendingFactor::ONE_MINUS_SRC_COLOR, BlendingFactor::SRC_ALPHA_SATURATE); + + // Test that Set was successful: + { + BlendingFactor::Type srcFactorRgb( BlendingFactor::ZERO ); + BlendingFactor::Type destFactorRgb( BlendingFactor::ZERO ); + BlendingFactor::Type srcFactorAlpha( BlendingFactor::ZERO ); + BlendingFactor::Type destFactorAlpha( BlendingFactor::ZERO ); + material.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha ); + + DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_SRC_COLOR, srcFactorRgb, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::SRC_ALPHA_SATURATE, destFactorRgb, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_SRC_COLOR, srcFactorAlpha, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::SRC_ALPHA_SATURATE, destFactorAlpha, TEST_LOCATION ); + } + + application.SendNotification(); + application.Render(); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + + DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_SRC_COLOR, glAbstraction.GetLastBlendFuncSrcRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_SRC_ALPHA_SATURATE, glAbstraction.GetLastBlendFuncDstRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_SRC_COLOR, glAbstraction.GetLastBlendFuncSrcAlpha(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_SRC_ALPHA_SATURATE, glAbstraction.GetLastBlendFuncDstAlpha(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialBlendingOptions02(void) +{ + TestApplication application; + + tet_infoline("Test SetBlendFunc(srcRgb, destRgb, srcAlpha, destAlpha) "); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(0.5f); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + material.SetBlendFunc( BlendingFactor::CONSTANT_COLOR, BlendingFactor::ONE_MINUS_CONSTANT_COLOR, + BlendingFactor::CONSTANT_ALPHA, BlendingFactor::ONE_MINUS_CONSTANT_ALPHA ); + + // Test that Set was successful: + { + BlendingFactor::Type srcFactorRgb( BlendingFactor::ZERO ); + BlendingFactor::Type destFactorRgb( BlendingFactor::ZERO ); + BlendingFactor::Type srcFactorAlpha( BlendingFactor::ZERO ); + BlendingFactor::Type destFactorAlpha( BlendingFactor::ZERO ); + material.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha ); + + DALI_TEST_EQUALS( BlendingFactor::CONSTANT_COLOR, srcFactorRgb, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_CONSTANT_COLOR, destFactorRgb, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::CONSTANT_ALPHA, srcFactorAlpha, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_CONSTANT_ALPHA, destFactorAlpha, TEST_LOCATION ); + } + + application.SendNotification(); + application.Render(); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + DALI_TEST_EQUALS( (GLenum)GL_CONSTANT_COLOR, glAbstraction.GetLastBlendFuncSrcRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_CONSTANT_COLOR, glAbstraction.GetLastBlendFuncDstRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_CONSTANT_ALPHA, glAbstraction.GetLastBlendFuncSrcAlpha(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_CONSTANT_ALPHA, glAbstraction.GetLastBlendFuncDstAlpha(), TEST_LOCATION ); + + END_TEST; +} + + + +int UtcDaliMaterialBlendingOptions03(void) +{ + TestApplication application; + + tet_infoline("Test GetBlendEquation() defaults "); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(0.5f); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + // Test the defaults as documented in blending.h + { + BlendingEquation::Type equationRgb( BlendingEquation::SUBTRACT ); + BlendingEquation::Type equationAlpha( BlendingEquation::SUBTRACT ); + material.GetBlendEquation( equationRgb, equationAlpha ); + DALI_TEST_EQUALS( BlendingEquation::ADD, equationRgb, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingEquation::ADD, equationAlpha, TEST_LOCATION ); + } + + END_TEST; +} + + +int UtcDaliMaterialBlendingOptions04(void) +{ + TestApplication application; + + tet_infoline("Test SetBlendEquation() "); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(0.5f); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + // Test the single blending equation setting + { + material.SetBlendEquation( BlendingEquation::REVERSE_SUBTRACT ); + BlendingEquation::Type equationRgba( BlendingEquation::SUBTRACT ); + material.GetBlendEquation( equationRgba, equationRgba ); + DALI_TEST_EQUALS( BlendingEquation::REVERSE_SUBTRACT, equationRgba, TEST_LOCATION ); + } + + material.SetBlendEquation( BlendingEquation::REVERSE_SUBTRACT, BlendingEquation::REVERSE_SUBTRACT ); + + // Test that Set was successful + { + BlendingEquation::Type equationRgb( BlendingEquation::SUBTRACT ); + BlendingEquation::Type equationAlpha( BlendingEquation::SUBTRACT ); + material.GetBlendEquation( equationRgb, equationAlpha ); + DALI_TEST_EQUALS( BlendingEquation::REVERSE_SUBTRACT, equationRgb, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingEquation::REVERSE_SUBTRACT, equationAlpha, TEST_LOCATION ); + } + + // Render & check GL commands + application.SendNotification(); + application.Render(); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + DALI_TEST_EQUALS( (GLenum)GL_FUNC_REVERSE_SUBTRACT, glAbstraction.GetLastBlendEquationRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_FUNC_REVERSE_SUBTRACT, glAbstraction.GetLastBlendEquationAlpha(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialSetBlendMode01(void) +{ + TestApplication application; + + tet_infoline("Test setting the blend mode to on with an opaque color renders with blending enabled"); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(1.0f); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + material.SetBlendMode(BlendingMode::ON); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace(); + std::ostringstream blendStr; + blendStr << GL_BLEND; + DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) ); + + END_TEST; +} + + +int UtcDaliMaterialSetBlendMode02(void) +{ + TestApplication application; + + tet_infoline("Test setting the blend mode to off with a transparent color renders with blending disabled (and not enabled)"); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(0.5f); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + material.SetBlendMode(BlendingMode::OFF); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace(); + std::ostringstream blendStr; + blendStr << GL_BLEND; + DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) ); + + END_TEST; +} + +int UtcDaliMaterialSetBlendMode03(void) +{ + TestApplication application; + + tet_infoline("Test setting the blend mode to auto with a transparent material color renders with blending enabled"); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(0.5f); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + material.SetBlendMode(BlendingMode::AUTO); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace(); + std::ostringstream blendStr; + blendStr << GL_BLEND; + DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) ); + + END_TEST; +} + +int UtcDaliMaterialSetBlendMode04(void) +{ + TestApplication application; + + tet_infoline("Test setting the blend mode to auto with an opaque color renders with blending disabled"); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(1.0f); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + material.SetBlendMode(BlendingMode::AUTO); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace(); + std::ostringstream blendStr; + blendStr << GL_BLEND; + DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) ); + + END_TEST; +} + +int UtcDaliMaterialSetBlendMode04b(void) +{ + TestApplication application; + + tet_infoline("Test setting the blend mode to auto with an opaque material color and a transparent actor color renders with blending enabled"); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(1.0f); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + actor.SetColor( Vector4(1.0f, 0.0f, 1.0f, 0.5f) ); + Stage::GetCurrent().Add(actor); + + material.SetBlendMode(BlendingMode::AUTO); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace(); + std::ostringstream blendStr; + blendStr << GL_BLEND; + DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) ); + + END_TEST; +} + +int UtcDaliMaterialSetBlendMode04c(void) +{ + TestApplication application; + + tet_infoline("Test setting the blend mode to auto with an opaque material color and an opaque actor color renders with blending disabled"); + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(1.0f); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + actor.SetColor( Color::MAGENTA ); + Stage::GetCurrent().Add(actor); + + material.SetBlendMode(BlendingMode::AUTO); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace(); + std::ostringstream blendStr; + blendStr << GL_BLEND; + DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) ); + + END_TEST; +} + +int UtcDaliMaterialSetBlendMode05(void) +{ + TestApplication application; + + tet_infoline("Test setting the blend mode to auto with an opaque color and an image with an alpha channel renders with blending enabled"); + + Geometry geometry = CreateQuadGeometry(); + BufferImage image = BufferImage::New( 40, 40, Pixel::RGBA8888 ); + Material material = CreateMaterial(1.0f, image); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + material.SetBlendMode(BlendingMode::AUTO); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace(); + std::ostringstream blendStr; + blendStr << GL_BLEND; + DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) ); + + END_TEST; +} + +int UtcDaliMaterialSetBlendMode06(void) +{ + TestApplication application; + tet_infoline("Test setting the blend mode to auto with an opaque color and an image without an alpha channel and a shader with the hint OUTPUT_IS_TRANSPARENT renders with blending enabled"); + + Geometry geometry = CreateQuadGeometry(); + Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_TRANSPARENT ); + Material material = Material::New(shader); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + material.SetBlendMode(BlendingMode::AUTO); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace(); + std::ostringstream blendStr; + blendStr << GL_BLEND; + DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) ); + + END_TEST; +} + + +//Todo: test the Shader::HINT_OUTPUT_IS_OPAQUE would disable the blending, the test cannot pass with current implementation +/*int UtcDaliMaterialSetBlendMode07(void) +{ + TestApplication application; + tet_infoline("Test setting the blend mode to auto with a transparent color and an image without an alpha channel and a shader with the hint OUTPUT_IS_OPAQUE renders with blending disabled"); + Geometry geometry = CreateQuadGeometry(); + Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_OPAQUE ); + Material material = Material::New(shader); + material.SetProperty(Material::Property::COLOR, Color::TRANSPARENT); + + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + material.SetBlendMode(BlendingMode::AUTO); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace(); + std::ostringstream blendStr; + blendStr << GL_BLEND; + DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) ); + + END_TEST; +}*/ + +int UtcDaliMaterialSetBlendMode08(void) +{ + TestApplication application; + tet_infoline("Test setting the blend mode to auto with an opaque color and an image without an alpha channel and a shader with the hint OUTPUT_IS_OPAQUE renders with blending disabled"); + + Geometry geometry = CreateQuadGeometry(); + Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_OPAQUE ); + Material material = Material::New(shader); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + BufferImage image = BufferImage::New( 50, 50, Pixel::RGB888 ); + Sampler sampler = Sampler::New( image, "sTexture" ); + material.AddSampler( sampler ); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + material.SetBlendMode(BlendingMode::AUTO); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + + application.SendNotification(); + application.Render(); + + TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace(); + std::ostringstream blendStr; + blendStr << GL_BLEND; + DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) ); + + END_TEST; +} + +int UtcDaliMaterialGetBlendMode(void) +{ + TestApplication application; + + tet_infoline("Test GetBlendMode()"); + + Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_OPAQUE ); + Material material = Material::New(shader); + + // default value + DALI_TEST_EQUALS( material.GetBlendMode(), BlendingMode::OFF, TEST_LOCATION ); + + // AUTO + material.SetBlendMode(BlendingMode::AUTO); + DALI_TEST_EQUALS( material.GetBlendMode(), BlendingMode::AUTO, TEST_LOCATION ); + + // ON + material.SetBlendMode(BlendingMode::ON); + DALI_TEST_EQUALS( material.GetBlendMode(), BlendingMode::ON, TEST_LOCATION ); + + // OFF + material.SetBlendMode(BlendingMode::OFF); + DALI_TEST_EQUALS( material.GetBlendMode(), BlendingMode::OFF, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialSetBlendColor(void) +{ + TestApplication application; + + tet_infoline("Test SetBlendColor(color)"); + + Geometry geometry = CreateQuadGeometry(); + Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_OPAQUE ); + Material material = Material::New(shader); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + BufferImage image = BufferImage::New( 50, 50, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New( image, "sTexture" ); + material.AddSampler( sampler ); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( glAbstraction.GetLastBlendColor(), Color::TRANSPARENT, TEST_LOCATION ); + + material.SetBlendColor( Color::MAGENTA ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( glAbstraction.GetLastBlendColor(), Color::MAGENTA, TEST_LOCATION ); + + Vector4 color( 0.1f, 0.2f, 0.3f, 0.4f ); + material.SetBlendColor( color ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( glAbstraction.GetLastBlendColor(), color, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialGetBlendColor(void) +{ + TestApplication application; + + tet_infoline("Test GetBlendColor()"); + + Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_OPAQUE ); + Material material = Material::New(shader); + + DALI_TEST_EQUALS( material.GetBlendColor(), Color::TRANSPARENT, TEST_LOCATION ); + + material.SetBlendColor( Color::MAGENTA ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( material.GetBlendColor(), Color::MAGENTA, TEST_LOCATION ); + + Vector4 color( 0.1f, 0.2f, 0.3f, 0.4f ); + material.SetBlendColor( color ); + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( material.GetBlendColor(), color, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialConstraint(void) +{ + TestApplication application; + + tet_infoline("Test that a custom material property can be constrained"); + + Shader shader = Shader::New( "VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = material.RegisterProperty( "uFadeColor", initialColor ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( material.GetProperty(colorIndex), initialColor, TEST_LOCATION ); + + // Apply constraint + Constraint constraint = Constraint::New( material, colorIndex, TestConstraintNoBlue ); + constraint.Apply(); + application.SendNotification(); + application.Render(0); + + // Expect no blue component in either buffer - yellow + DALI_TEST_EQUALS( material.GetProperty(colorIndex), Color::YELLOW, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( material.GetProperty(colorIndex), Color::YELLOW, TEST_LOCATION ); + + material.RemoveConstraints(); + material.SetProperty(colorIndex, Color::WHITE ); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( material.GetProperty(colorIndex), Color::WHITE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialConstraint02(void) +{ + TestApplication application; + + tet_infoline("Test that a uniform map material property can be constrained"); + + Shader shader = Shader::New( "VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = material.RegisterProperty( "uFadeColor", initialColor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION ); + + // Apply constraint + Constraint constraint = Constraint::New( material, colorIndex, TestConstraintNoBlue ); + constraint.Apply(); + application.SendNotification(); + application.Render(0); + + // Expect no blue component in either buffer - yellow + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + application.Render(0); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + material.RemoveConstraints(); + material.SetProperty(colorIndex, Color::WHITE ); + application.SendNotification(); + application.Render(0); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::WHITE, TEST_LOCATION ); + + END_TEST; +} + + + +int UtcDaliMaterialAnimatedProperty01(void) +{ + TestApplication application; + + tet_infoline("Test that a non-uniform material property can be animated"); + + Shader shader = Shader::New( "VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = material.RegisterProperty( "uFadeColor", initialColor ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( material.GetProperty(colorIndex), initialColor, TEST_LOCATION ); + + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, initialColor); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( material, colorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_EQUALS( material.GetProperty(colorIndex), Color::WHITE * 0.5f, TEST_LOCATION ); + + application.Render(500); + + DALI_TEST_EQUALS( material.GetProperty(colorIndex), Color::TRANSPARENT, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMaterialAnimatedProperty02(void) +{ + TestApplication application; + + tet_infoline("Test that a uniform map material property can be animated"); + + Shader shader = Shader::New( "VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = material.RegisterProperty( "uFadeColor", initialColor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION ); + + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, initialColor); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( material, colorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::WHITE * 0.5f, TEST_LOCATION ); + + application.Render(500); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::TRANSPARENT, TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-Mutex.cpp b/automated-tests/src/dali-devel/utc-Dali-Mutex.cpp new file mode 100644 index 0000000..290a826 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-Mutex.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include + +using Dali::Mutex; + +int UtcDaliMutexSingleThread(void) +{ + tet_infoline("Testing Dali::Mutex in a single thread"); + + { + Mutex mutex1; + DALI_TEST_EQUALS( false, mutex1.IsLocked(), TEST_LOCATION ); + } + + { + Mutex mutex2; + Mutex::ScopedLock lock( mutex2 ); + DALI_TEST_EQUALS( true, mutex2.IsLocked(), TEST_LOCATION ); + } + + Mutex mutex3; + { + Mutex::ScopedLock lock( mutex3 ); + } + DALI_TEST_EQUALS( false, mutex3.IsLocked(), TEST_LOCATION ); + + END_TEST; +} + +namespace // for local variables to avoid name clashes +{ +// make all these volatile to pre-empt any optimization screwing up the logic +volatile int gGlobalValue = 0; +volatile bool gWorkerThreadWait = true; +volatile enum ThreadState { INIT, RUN, LOCKING, TERMINATE } gWorkerThreadState = INIT; +Mutex* volatile gGlobalValueMutex; // volatile pointer to a mutex object +} +void* WorkerThread1( void* ptr ) +{ + gWorkerThreadState = RUN; + { + Mutex::ScopedLock lock( *gGlobalValueMutex ); + gWorkerThreadState = LOCKING; + gGlobalValue = -1; + while( gWorkerThreadWait ) // wait till we can exit + { + usleep( 1 ); // 1 microsecond + } + } + gWorkerThreadState = TERMINATE; + return NULL; +} + +int UtcDaliMutexMultiThread(void) +{ + tet_infoline("Testing Dali::Mutex multithreaded"); + + gGlobalValueMutex = new Dali::Mutex(); + + pthread_t thread1; + // initialize values + gGlobalValue = 0; + gWorkerThreadWait = true; + DALI_TEST_EQUALS( INIT, gWorkerThreadState, TEST_LOCATION ); + DALI_TEST_EQUALS( 0, gGlobalValue, TEST_LOCATION ); + DALI_TEST_EQUALS( false, gGlobalValueMutex->IsLocked(), TEST_LOCATION ); + + // lock the mutex + { + Mutex::ScopedLock lock( *gGlobalValueMutex ); + DALI_TEST_EQUALS( true, gGlobalValueMutex->IsLocked(), TEST_LOCATION ); + pthread_create( &thread1, NULL, &WorkerThread1, NULL ); + // wait till the thread is in run state + while( RUN != gWorkerThreadState ) + { + usleep( 1 ); // 1 microsecond + } + // now the thread is running and mutex is still locked by this thread so value is not changed + DALI_TEST_EQUALS( true, gGlobalValueMutex->IsLocked(), TEST_LOCATION ); + DALI_TEST_EQUALS( 0, gGlobalValue, TEST_LOCATION ); + // drop out of scope, releases our lock + } + // now child thread is allowed to change the value + // wait till the thread is in locking state + while( LOCKING != gWorkerThreadState ) + { + usleep( 1 ); // 1 microsecond + } + // mutex is locked, but not by us, by the child thread + DALI_TEST_EQUALS( true, gGlobalValueMutex->IsLocked(), TEST_LOCATION ); + // value is changed + DALI_TEST_EQUALS( -1, gGlobalValue, TEST_LOCATION ); + // let worker finish + gWorkerThreadWait = false; + // wait till the thread is terminated state + while( TERMINATE != gWorkerThreadState ) + { + usleep( 1 ); // 1 microsecond + } + DALI_TEST_EQUALS( false, gGlobalValueMutex->IsLocked(), TEST_LOCATION ); + void* exitValue; + pthread_join( thread1, &exitValue ); + + END_TEST; +} + +int UtcDaliMutexNonCopyable(void) +{ + // we want to make sure that mutex is not copyable (its copy constructor is not defined) + // this test will stop compiling if Mutex has compiler generated copy constructor + DALI_COMPILE_TIME_ASSERT( !__has_trivial_copy( Mutex ) ); + + DALI_TEST_CHECK( true ); + END_TEST; +} + + diff --git a/automated-tests/src/dali-devel/utc-Dali-PropertyBuffer.cpp b/automated-tests/src/dali-devel/utc-Dali-PropertyBuffer.cpp new file mode 100644 index 0000000..55b3d10 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-PropertyBuffer.cpp @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +using namespace Dali; + +#include + +namespace +{ +void TestConstraintNoBlue( Vector4& current, const PropertyInputContainer& inputs ) +{ + current.b = 0.0f; +} +} + +void propertyBuffer_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void propertyBuffer_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliPropertyBufferNew01(void) +{ + TestApplication application; + + Property::Map texturedQuadVertexFormat; + texturedQuadVertexFormat["aPosition"] = Property::VECTOR2; + texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2; + + PropertyBuffer propertyBuffer = PropertyBuffer::New( texturedQuadVertexFormat, 4 ); + + DALI_TEST_EQUALS( (bool)propertyBuffer, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyBufferNew02(void) +{ + TestApplication application; + PropertyBuffer propertyBuffer; + DALI_TEST_EQUALS( (bool)propertyBuffer, false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyBufferDownCast01(void) +{ + TestApplication application; + + Property::Map texturedQuadVertexFormat; + texturedQuadVertexFormat["aPosition"] = Property::VECTOR2; + texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2; + + PropertyBuffer propertyBuffer = PropertyBuffer::New( texturedQuadVertexFormat, 4 ); + + BaseHandle handle(propertyBuffer); + PropertyBuffer propertyBuffer2 = PropertyBuffer::DownCast(handle); + DALI_TEST_EQUALS( (bool)propertyBuffer2, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyBufferDownCast02(void) +{ + TestApplication application; + + Handle handle = Handle::New(); // Create a custom object + PropertyBuffer propertyBuffer = PropertyBuffer::DownCast(handle); + DALI_TEST_EQUALS( (bool)propertyBuffer, false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyBufferCopyConstructor(void) +{ + TestApplication application; + + PropertyBuffer propertyBuffer = CreatePropertyBuffer(); + + PropertyBuffer propertyBufferCopy(propertyBuffer); + + DALI_TEST_EQUALS( (bool)propertyBufferCopy, true, TEST_LOCATION ); + DALI_TEST_EQUALS( propertyBufferCopy.GetSize(), 4u, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyBufferAssignmentOperator(void) +{ + TestApplication application; + + PropertyBuffer propertyBuffer = CreatePropertyBuffer(); + + PropertyBuffer propertyBuffer2; + DALI_TEST_EQUALS( (bool)propertyBuffer2, false, TEST_LOCATION ); + + propertyBuffer2 = propertyBuffer; + DALI_TEST_EQUALS( (bool)propertyBuffer2, true, TEST_LOCATION ); + DALI_TEST_EQUALS( propertyBuffer2.GetSize(), 4u, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyBufferConstraint01(void) +{ + TestApplication application; + + tet_infoline("Test that a non-uniform propertyBuffer property can be constrained"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer propertyBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(propertyBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = propertyBuffer.RegisterProperty( "uFadeColor", initialColor ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( propertyBuffer.GetProperty(colorIndex), initialColor, TEST_LOCATION ); + + // Apply constraint + Constraint constraint = Constraint::New( propertyBuffer, colorIndex, TestConstraintNoBlue ); + constraint.Apply(); + application.SendNotification(); + application.Render(0); + + // Expect no blue component in either buffer - yellow + DALI_TEST_EQUALS( propertyBuffer.GetProperty(colorIndex), Color::YELLOW, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( propertyBuffer.GetProperty(colorIndex), Color::YELLOW, TEST_LOCATION ); + + propertyBuffer.RemoveConstraints(); + propertyBuffer.SetProperty(colorIndex, Color::WHITE ); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( propertyBuffer.GetProperty(colorIndex), Color::WHITE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyBufferConstraint02(void) +{ + TestApplication application; + + tet_infoline("Test that a uniform map propertyBuffer property can be constrained"); + + Shader shader = Shader::New( "VertexSource", "FragmentSource" ); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer propertyBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(propertyBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = propertyBuffer.RegisterProperty( "uFadeColor", initialColor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION ); + + // Apply constraint + Constraint constraint = Constraint::New( propertyBuffer, colorIndex, TestConstraintNoBlue ); + constraint.Apply(); + application.SendNotification(); + application.Render(0); + + // Expect no blue component in either buffer - yellow + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + application.Render(0); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + propertyBuffer.RemoveConstraints(); + propertyBuffer.SetProperty(colorIndex, Color::WHITE ); + application.SendNotification(); + application.Render(0); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::WHITE, TEST_LOCATION ); + + END_TEST; +} + + + +int UtcDaliPropertyBufferAnimatedProperty01(void) +{ + TestApplication application; + + tet_infoline("Test that a non-uniform propertyBuffer property can be animated"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer propertyBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(propertyBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = propertyBuffer.RegisterProperty( "uFadeColor", initialColor ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( propertyBuffer.GetProperty(colorIndex), initialColor, TEST_LOCATION ); + + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, initialColor); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( propertyBuffer, colorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_EQUALS( propertyBuffer.GetProperty(colorIndex), Color::WHITE * 0.5f, TEST_LOCATION ); + + application.Render(500); + + DALI_TEST_EQUALS( propertyBuffer.GetProperty(colorIndex), Color::TRANSPARENT, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyBufferAnimatedProperty02(void) +{ + TestApplication application; + + tet_infoline("Test that a uniform map propertyBuffer property can be animated"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer propertyBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(propertyBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = propertyBuffer.RegisterProperty( "uFadeColor", initialColor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION ); + + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, initialColor); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( propertyBuffer, colorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::WHITE * 0.5f, TEST_LOCATION ); + + application.Render(500); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::TRANSPARENT, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyBufferSetData01(void) +{ + TestApplication application; + + Property::Map texturedQuadVertexFormat; + texturedQuadVertexFormat["aPosition"] = Property::VECTOR2; + texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2; + + PropertyBuffer propertyBuffer = PropertyBuffer::New( texturedQuadVertexFormat, 4 ); + DALI_TEST_EQUALS( (bool)propertyBuffer, true, TEST_LOCATION ); + + const float halfQuadSize = .5f; + struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; }; + TexturedQuadVertex texturedQuadVertexData[4] = { + { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) }, + { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) }, + { Vector2(-halfQuadSize, halfQuadSize), Vector2(0.f, 1.f) }, + { Vector2( halfQuadSize, halfQuadSize), Vector2(1.f, 1.f) } }; + + propertyBuffer.SetData( texturedQuadVertexData ); + + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer( propertyBuffer ); + + Material material = CreateMaterial(1.f); + Renderer renderer = Renderer::New(geometry, material); + Actor actor = Actor::New(); + actor.SetSize(Vector3::ONE * 100.f); + actor.AddRenderer(renderer); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + + const TestGlAbstraction::BufferDataCalls& bufferDataCalls = + application.GetGlAbstraction().GetBufferDataCalls(); + + DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION ); + + DALI_TEST_EQUALS( bufferDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyBufferSetData02(void) +{ + TestApplication application; + + Property::Map texturedQuadVertexFormat; + texturedQuadVertexFormat["aPosition"] = Property::VECTOR2; + texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2; + + PropertyBuffer propertyBuffer = PropertyBuffer::New( texturedQuadVertexFormat, 4 ); + DALI_TEST_EQUALS( (bool)propertyBuffer, true, TEST_LOCATION ); + + const float halfQuadSize = .5f; + struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; }; + TexturedQuadVertex texturedQuadVertexData[4] = { + { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) }, + { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) }, + { Vector2(-halfQuadSize, halfQuadSize), Vector2(0.f, 1.f) }, + { Vector2( halfQuadSize, halfQuadSize), Vector2(1.f, 1.f) } }; + + propertyBuffer.SetData( texturedQuadVertexData ); + + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer( propertyBuffer ); + + Material material = CreateMaterial(1.f); + Renderer renderer = Renderer::New(geometry, material); + Actor actor = Actor::New(); + actor.SetSize(Vector3::ONE * 100.f); + actor.AddRenderer(renderer); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + + { + const TestGlAbstraction::BufferDataCalls& bufferDataCalls = + application.GetGlAbstraction().GetBufferDataCalls(); + + DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION ); + + DALI_TEST_EQUALS( bufferDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION ); + } + + // Re-upload the data on the propertyBuffer + propertyBuffer.SetData( texturedQuadVertexData ); + + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + + { + const TestGlAbstraction::BufferSubDataCalls& bufferSubDataCalls = + application.GetGlAbstraction().GetBufferSubDataCalls(); + + const TestGlAbstraction::BufferDataCalls& bufferDataCalls = + application.GetGlAbstraction().GetBufferDataCalls(); + + DALI_TEST_EQUALS( bufferSubDataCalls.size(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION ); + + if ( bufferSubDataCalls.size() ) + { + DALI_TEST_EQUALS( bufferSubDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION ); + + } + } + + END_TEST; +} + +int UtcDaliPropertyBufferSetGetSize01(void) +{ + TestApplication application; + + Property::Map texturedQuadVertexFormat; + texturedQuadVertexFormat["aPosition"] = Property::VECTOR2; + texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2; + + PropertyBuffer propertyBuffer = PropertyBuffer::New( texturedQuadVertexFormat, 4u ); + DALI_TEST_EQUALS( (bool)propertyBuffer, true, TEST_LOCATION ); + + size_t size = propertyBuffer.GetSize(); + DALI_TEST_EQUALS( size, 4u, TEST_LOCATION ); + + propertyBuffer.SetSize( 10u ); + size = propertyBuffer.GetSize(); + DALI_TEST_EQUALS( size, 10u, TEST_LOCATION ); + + END_TEST; +} + +//Todo: also test that the SetSize function is equivalent to setting the property SIZE +int UtcDaliPropertyBufferSetGetSize02(void) +{ + TestApplication application; + + Property::Map texturedQuadVertexFormat; + texturedQuadVertexFormat["aPosition"] = Property::VECTOR2; + texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2; + + int size = 5u; + PropertyBuffer propertyBuffer = PropertyBuffer::New( texturedQuadVertexFormat, size ); + DALI_TEST_EQUALS( propertyBuffer.GetProperty(PropertyBuffer::Property::SIZE), size, TEST_LOCATION ); + DALI_TEST_EQUALS( propertyBuffer.GetSize(), size, TEST_LOCATION ); + + size += 3u; + propertyBuffer.SetSize( size ); + DALI_TEST_EQUALS( propertyBuffer.GetProperty(PropertyBuffer::Property::SIZE), size, TEST_LOCATION ); + DALI_TEST_EQUALS( propertyBuffer.GetSize(), size, TEST_LOCATION ); + + size += 2u; + propertyBuffer.SetProperty(PropertyBuffer::Property::SIZE, size ); + DALI_TEST_EQUALS( propertyBuffer.GetSize(), size, TEST_LOCATION ); + + END_TEST; +} + diff --git a/automated-tests/src/dali-devel/utc-Dali-Renderer.cpp b/automated-tests/src/dali-devel/utc-Dali-Renderer.cpp new file mode 100644 index 0000000..ce0489e --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-Renderer.cpp @@ -0,0 +1,1077 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +using namespace Dali; + +#include + +namespace +{ +void TestConstraintNoBlue( Vector4& current, const PropertyInputContainer& inputs ) +{ + current.b = 0.0f; +} +} + +void renderer_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void renderer_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +int UtcDaliRendererNew01(void) +{ + TestApplication application; + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(1.0f); + Renderer renderer = Renderer::New(geometry, material); + + DALI_TEST_EQUALS( (bool)renderer, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRendererNew02(void) +{ + TestApplication application; + Renderer renderer; + DALI_TEST_EQUALS( (bool)renderer, false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRendererCopyConstructor(void) +{ + TestApplication application; + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(1.0f); + Renderer renderer = Renderer::New(geometry, material); + + Renderer rendererCopy( renderer ); + DALI_TEST_EQUALS( (bool)rendererCopy, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererAssignmentOperator(void) +{ + TestApplication application; + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(1.0f); + Renderer renderer = Renderer::New(geometry, material); + + Renderer renderer2; + DALI_TEST_EQUALS( (bool)renderer2, false, TEST_LOCATION ); + + renderer2 = renderer; + DALI_TEST_EQUALS( (bool)renderer2, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRendererDownCast01(void) +{ + TestApplication application; + + Geometry geometry = CreateQuadGeometry(); + Material material = CreateMaterial(1.0f); + Renderer renderer = Renderer::New(geometry, material); + + BaseHandle handle(renderer); + Renderer renderer2 = Renderer::DownCast(handle); + DALI_TEST_EQUALS( (bool)renderer2, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRendererDownCast02(void) +{ + TestApplication application; + + Handle handle = Handle::New(); // Create a custom object + Renderer renderer = Renderer::DownCast(handle); + DALI_TEST_EQUALS( (bool)renderer, false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRendererSetGetGeometry(void) +{ + TestApplication application; + tet_infoline( "Test SetGeometry, GetGeometry" ); + + Geometry geometry1 = CreateQuadGeometry(); + geometry1.RegisterProperty( "uFadeColor", Color::RED ); + + Geometry geometry2 = CreateQuadGeometry(); + geometry2.RegisterProperty( "uFadeColor", Color::GREEN ); + + Material material = CreateMaterial(1.0f); + Renderer renderer = Renderer::New(geometry1, material); + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + application.SendNotification(); + application.Render(0); + + // Expect that the first geometry's fade color property is accessed + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::RED, TEST_LOCATION ); + + DALI_TEST_EQUALS( renderer.GetGeometry(), geometry1, TEST_LOCATION ); + + // Set geometry2 to the renderer + renderer.SetGeometry( geometry2 ); + + application.SendNotification(); + application.Render(0); + + // Expect that the second geometry's fade color property is accessed + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::GREEN, TEST_LOCATION ); + + DALI_TEST_EQUALS( renderer.GetGeometry(), geometry2, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererSetGetMaterial(void) +{ + TestApplication application; + tet_infoline( "Test SetMaterial, GetMaterial" ); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + glAbstraction.EnableCullFaceCallTrace(true); + + Material material1 = CreateMaterial(1.0f); + material1.RegisterProperty( "uFadeColor", Color::RED ); + + Material material2 = CreateMaterial(1.0f); + material2.RegisterProperty( "uFadeColor", Color::GREEN ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New(geometry, material1); + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + application.SendNotification(); + application.Render(0); + + // Expect that the first material's fade color property is accessed + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::RED, TEST_LOCATION ); + + DALI_TEST_EQUALS( renderer.GetMaterial(), material1, TEST_LOCATION ); + + // set the second material to the renderer + renderer.SetMaterial( material2 ); + + application.SendNotification(); + application.Render(0); + + // Expect that the second material's fade color property is accessed + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::GREEN, TEST_LOCATION ); + + DALI_TEST_EQUALS( renderer.GetMaterial(), material2, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererSetGetDepthIndex(void) +{ + TestApplication application; + + tet_infoline("Test SetDepthIndex, GetDepthIndex"); + + Material material = CreateMaterial(1.0f); + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New(geometry, material); + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( renderer.GetDepthIndex(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( renderer.GetProperty(Renderer::Property::DEPTH_INDEX), 0, TEST_LOCATION ); + + renderer.SetDepthIndex(1); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( renderer.GetDepthIndex(), 1, TEST_LOCATION ); + DALI_TEST_EQUALS( renderer.GetProperty(Renderer::Property::DEPTH_INDEX), 1, TEST_LOCATION ); + + renderer.SetDepthIndex(10); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( renderer.GetDepthIndex(), 10, TEST_LOCATION ); + DALI_TEST_EQUALS( renderer.GetProperty(Renderer::Property::DEPTH_INDEX), 10, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererConstraint01(void) +{ + TestApplication application; + + tet_infoline("Test that a non-uniform renderer property can be constrained"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = renderer.RegisterProperty( "uFadeColor", initialColor ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( renderer.GetProperty(colorIndex), initialColor, TEST_LOCATION ); + + // Apply constraint + Constraint constraint = Constraint::New( renderer, colorIndex, TestConstraintNoBlue ); + constraint.Apply(); + application.SendNotification(); + application.Render(0); + + // Expect no blue component in either buffer - yellow + DALI_TEST_EQUALS( renderer.GetProperty(colorIndex), Color::YELLOW, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( renderer.GetProperty(colorIndex), Color::YELLOW, TEST_LOCATION ); + + renderer.RemoveConstraints(); + renderer.SetProperty(colorIndex, Color::WHITE ); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( renderer.GetProperty(colorIndex), Color::WHITE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererConstraint02(void) +{ + TestApplication application; + + tet_infoline("Test that a uniform map renderer property can be constrained"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = renderer.RegisterProperty( "uFadeColor", initialColor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION ); + + // Apply constraint + Constraint constraint = Constraint::New( renderer, colorIndex, TestConstraintNoBlue ); + constraint.Apply(); + application.SendNotification(); + application.Render(0); + + // Expect no blue component in either buffer - yellow + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + application.Render(0); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + renderer.RemoveConstraints(); + renderer.SetProperty(colorIndex, Color::WHITE ); + application.SendNotification(); + application.Render(0); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::WHITE, TEST_LOCATION ); + + END_TEST; +} + + + +int UtcDaliRendererAnimatedProperty01(void) +{ + TestApplication application; + + tet_infoline("Test that a non-uniform renderer property can be animated"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = renderer.RegisterProperty( "uFadeColor", initialColor ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( renderer.GetProperty(colorIndex), initialColor, TEST_LOCATION ); + + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, initialColor); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( renderer, colorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_EQUALS( renderer.GetProperty(colorIndex), Color::WHITE * 0.5f, TEST_LOCATION ); + + application.Render(500); + + DALI_TEST_EQUALS( renderer.GetProperty(colorIndex), Color::TRANSPARENT, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererAnimatedProperty02(void) +{ + TestApplication application; + + tet_infoline("Test that a uniform map renderer property can be animated"); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = renderer.RegisterProperty( "uFadeColor", initialColor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION ); + + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, initialColor); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( renderer, colorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::WHITE * 0.5f, TEST_LOCATION ); + + application.Render(500); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::TRANSPARENT, TEST_LOCATION ); + + END_TEST; +} + + + + +int UtcDaliRendererUniformMapPrecendence01(void) +{ + TestApplication application; + + tet_infoline("Test the uniform map precedence is applied properly"); + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + sampler.SetUniformName( "sEffectTexture" ); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.AddSampler( sampler ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer vertexBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + renderer.RegisterProperty( "uFadeColor", Color::RED ); + + actor.RegisterProperty( "uFadeColor", Color::GREEN ); + + Property::Index materialFadeColorIndex = material.RegisterProperty( "uFadeColor", Color::BLUE ); + + sampler.RegisterProperty( "uFadeColor", Color::CYAN ); + shader.RegisterProperty( "uFadeColor", Color::MAGENTA ); + + geometry.RegisterProperty( "uFadeColor", Color::YELLOW ); + + vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK ); + + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + // Expect that the renderer's fade color property is accessed + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::RED, TEST_LOCATION ); + + // Animate material's fade color property. Should be no change to uniform + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Color::WHITE); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( material, materialFadeColorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::RED, TEST_LOCATION ); + + application.Render(500); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::RED, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererUniformMapPrecendence02(void) +{ + TestApplication application; + + tet_infoline("Test the uniform map precedence is applied properly"); + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + sampler.SetUniformName( "sEffectTexture" ); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.AddSampler( sampler ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer vertexBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + // Don't add property / uniform map to renderer + + actor.RegisterProperty( "uFadeColor", Color::GREEN ); + + Property::Index materialFadeColorIndex = material.RegisterProperty( "uFadeColor", Color::BLUE ); + + sampler.RegisterProperty( "uFadeColor", Color::CYAN ); + shader.RegisterProperty( "uFadeColor", Color::MAGENTA ); + + geometry.RegisterProperty( "uFadeColor", Color::YELLOW ); + + vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK ); + + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + // Expect that the actor's fade color property is accessed + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::GREEN, TEST_LOCATION ); + + // Animate material's fade color property. Should be no change to uniform + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Color::WHITE); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( material, materialFadeColorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::GREEN, TEST_LOCATION ); + + application.Render(500); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::GREEN, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliRendererUniformMapPrecendence03(void) +{ + TestApplication application; + + tet_infoline("Test the uniform map precedence is applied properly"); + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + sampler.SetUniformName( "sEffectTexture" ); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.AddSampler( sampler ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer vertexBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + // Don't add property / uniform map to renderer or actor + + material.RegisterProperty( "uFadeColor", Color::BLUE ); + + sampler.RegisterProperty( "uFadeColor", Color::CYAN ); + shader.RegisterProperty( "uFadeColor", Color::MAGENTA ); + + Property::Index geometryFadeColorIndex = geometry.RegisterProperty( "uFadeColor", Color::YELLOW ); + + vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK ); + + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + // Expect that the material's fade color property is accessed + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::BLUE, TEST_LOCATION ); + + // Animate geometry's fade color property. Should be no change to uniform + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Color::WHITE); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( geometry, geometryFadeColorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::BLUE, TEST_LOCATION ); + + application.Render(500); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::BLUE, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliRendererUniformMapPrecendence04(void) +{ + TestApplication application; + + tet_infoline("Test the uniform map precedence is applied properly"); + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + sampler.SetUniformName( "sEffectTexture" ); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.AddSampler( sampler ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer vertexBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + // Don't add property / uniform map to renderer/actor/material + + sampler.RegisterProperty( "uFadeColor", Color::CYAN ); + shader.RegisterProperty( "uFadeColor", Color::MAGENTA ); + + Property::Index geometryFadeColorIndex = geometry.RegisterProperty( "uFadeColor", Color::YELLOW ); + + vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK ); + + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + // Expect that the sampler's fade color property is accessed + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::CYAN, TEST_LOCATION ); + + // Animate geometry's fade color property. Should be no change to uniform + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Color::WHITE); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( geometry, geometryFadeColorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::CYAN, TEST_LOCATION ); + + application.Render(500); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::CYAN, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererUniformMapPrecendence05(void) +{ + TestApplication application; + + tet_infoline("Test the uniform map precedence is applied properly"); + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + sampler.SetUniformName( "sEffectTexture" ); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.AddSampler( sampler ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer vertexBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + // Don't add property / uniform map to renderer/actor/material/sampler + + shader.RegisterProperty( "uFadeColor", Color::MAGENTA ); + + Property::Index geometryFadeColorIndex = geometry.RegisterProperty( "uFadeColor", Color::YELLOW ); + + vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK ); + + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + // Expect that the shader's fade color property is accessed + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::MAGENTA, TEST_LOCATION ); + + // Animate geometry's fade color property. Should be no change to uniform + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Color::WHITE); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( geometry, geometryFadeColorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::MAGENTA, TEST_LOCATION ); + + application.Render(500); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::MAGENTA, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererUniformMapPrecendence06(void) +{ + TestApplication application; + + tet_infoline("Test the uniform map precedence is applied properly"); + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + sampler.SetUniformName( "sEffectTexture" ); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.AddSampler( sampler ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer vertexBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + // Don't add property / uniform map to renderer/actor/material/sampler/shader + + geometry.RegisterProperty( "uFadeColor", Color::YELLOW ); + + Property::Index vertexFadeColorIndex = vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK ); + + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + // Expect that the geometry's fade color property is accessed + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + // Animate vertex buffer's fade color property. Should be no change to uniform + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Color::WHITE); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( vertexBuffer, vertexFadeColorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + application.Render(500); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRendererUniformMapPrecendence07(void) +{ + TestApplication application; + + tet_infoline("Test the uniform map precedence is applied properly"); + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + sampler.SetUniformName( "sEffectTexture" ); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.AddSampler( sampler ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer vertexBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + // Don't add property / uniform map to renderer/actor/material/sampler/shader/geometry + + Property::Index vertexFadeColorIndex = vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + // Expect that the vertex buffer's fade color property is accessed + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::BLACK, TEST_LOCATION ); + + // Animate vertex buffer's fade color property. Should change the uniform + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Color::WHITE); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( vertexBuffer, vertexFadeColorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::WHITE*0.5f, TEST_LOCATION ); + + application.Render(500); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::TRANSPARENT, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliRendererUniformMapMultipleUniforms01(void) +{ + TestApplication application; + + tet_infoline("Test the uniform maps are collected from all objects (same type)"); + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + sampler.SetUniformName( "sEffectTexture" ); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.AddSampler( sampler ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer vertexBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + renderer.RegisterProperty( "uUniform1", Color::RED ); + actor.RegisterProperty( "uUniform2", Color::GREEN ); + material.RegisterProperty( "uUniform3", Color::BLUE ); + sampler.RegisterProperty( "uUniform4", Color::CYAN ); + shader.RegisterProperty( "uUniform5", Color::MAGENTA ); + geometry.RegisterProperty( "uUniform6", Color::YELLOW ); + vertexBuffer.RegisterProperty( "uUniform7", Color::BLACK ); + + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + // Expect that each of the object's uniforms are set + Vector4 uniform1Value(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uUniform1", uniform1Value ) ); + DALI_TEST_EQUALS( uniform1Value, Color::RED, TEST_LOCATION ); + + Vector4 uniform2Value(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uUniform2", uniform2Value ) ); + DALI_TEST_EQUALS( uniform2Value, Color::GREEN, TEST_LOCATION ); + + Vector4 uniform3Value(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uUniform3", uniform3Value ) ); + DALI_TEST_EQUALS( uniform3Value, Color::BLUE, TEST_LOCATION ); + + Vector4 uniform4Value(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uUniform4", uniform4Value ) ); + DALI_TEST_EQUALS( uniform4Value, Color::CYAN, TEST_LOCATION ); + + Vector4 uniform5Value(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uUniform5", uniform5Value ) ); + DALI_TEST_EQUALS( uniform5Value, Color::MAGENTA, TEST_LOCATION ); + + Vector4 uniform6Value(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uUniform6", uniform6Value ) ); + DALI_TEST_EQUALS( uniform6Value, Color::YELLOW, TEST_LOCATION ); + + Vector4 uniform7Value(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uUniform7", uniform7Value ) ); + DALI_TEST_EQUALS( uniform7Value, Color::BLACK, TEST_LOCATION ); + + + END_TEST; +} + + +int UtcDaliRendererUniformMapMultipleUniforms02(void) +{ + TestApplication application; + + tet_infoline("Test the uniform maps are collected from all objects (different types)"); + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + sampler.SetUniformName( "sEffectTexture" ); + + Shader shader = Shader::New("VertexSource", "FragmentSource"); + Material material = Material::New( shader ); + material.AddSampler( sampler ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + PropertyBuffer vertexBuffer = CreatePropertyBuffer(); + Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + Property::Value value1(Color::RED); + renderer.RegisterProperty( "uFadeColor", value1 ); + + Property::Value value2(1.0f); + actor.RegisterProperty( "uFadeProgress", value2 ); + + Property::Value value3(Vector3(0.5f, 0.5f, 1.0f)); + material.RegisterProperty( "uFadePosition", value3); + + Property::Value value4(Vector2(0.5f, 1.0f)); + sampler.RegisterProperty( "uFadeUV", value4 ); + + Property::Value value5(Matrix3::IDENTITY); + shader.RegisterProperty( "uANormalMatrix", value5 ); + + Property::Value value6(Matrix::IDENTITY); + geometry.RegisterProperty( "uAWorldMatrix", value6 ); + + Property::Value value7(7); + vertexBuffer.RegisterProperty( "uAnotherFadeColor", value7 ); + + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + // Expect that each of the object's uniforms are set + Vector4 uniform1Value(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", uniform1Value ) ); + DALI_TEST_EQUALS( uniform1Value, value1.Get(), TEST_LOCATION ); + + float uniform2Value(0.0f); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeProgress", uniform2Value ) ); + DALI_TEST_EQUALS( uniform2Value, value2.Get(), TEST_LOCATION ); + + Vector3 uniform3Value(Vector3::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadePosition", uniform3Value ) ); + DALI_TEST_EQUALS( uniform3Value, value3.Get(), TEST_LOCATION ); + + Vector2 uniform4Value(Vector2::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeUV", uniform4Value ) ); + DALI_TEST_EQUALS( uniform4Value, value4.Get(), TEST_LOCATION ); + + Matrix3 uniform5Value; + DALI_TEST_CHECK( gl.GetUniformValue( "uANormalMatrix", uniform5Value ) ); + DALI_TEST_EQUALS( uniform5Value, value5.Get(), TEST_LOCATION ); + + Matrix uniform6Value; + DALI_TEST_CHECK( gl.GetUniformValue( "uAWorldMatrix", uniform6Value ) ); + DALI_TEST_EQUALS( uniform6Value, value6.Get(), TEST_LOCATION ); + + int uniform7Value = 0; + DALI_TEST_CHECK( gl.GetUniformValue( "uAnotherFadeColor", uniform7Value ) ); + DALI_TEST_EQUALS( uniform7Value, value7.Get(), TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-Sampler.cpp b/automated-tests/src/dali-devel/utc-Dali-Sampler.cpp new file mode 100644 index 0000000..4cecb5f --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-Sampler.cpp @@ -0,0 +1,448 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +using namespace Dali; + +#include + +void sampler_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void sampler_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliSamplerNew01(void) +{ + TestApplication application; + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + + DALI_TEST_EQUALS( (bool)sampler, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSamplerNew02(void) +{ + TestApplication application; + Sampler sampler; + DALI_TEST_EQUALS( (bool)sampler, false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSamplerCopyConstructor(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Handle::Handle(const Handle&)"); + + // Initialize an object, ref count == 1 + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + + DALI_TEST_EQUALS(1, sampler.GetBaseObject().ReferenceCount(), TEST_LOCATION); + + // Copy the object, ref count == 2 + Sampler copy(sampler); + DALI_TEST_CHECK(copy); + if (copy) + { + DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION); + } + + END_TEST; +} + + +int UtcDaliSamplerDownCast01(void) +{ + TestApplication application; + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + + BaseHandle handle(sampler); + Sampler sampler2 = Sampler::DownCast(handle); + DALI_TEST_EQUALS( (bool)sampler2, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSamplerDownCast02(void) +{ + TestApplication application; + + BaseHandle handle; + Sampler sampler = Sampler::DownCast(handle); + DALI_TEST_EQUALS( (bool)sampler, false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSamplerAssignmentOperator(void) +{ + TestApplication application; + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler1 = Sampler::New(image, "sTexture"); + + Sampler sampler2; + + DALI_TEST_CHECK(!(sampler1 == sampler2)); + + sampler2 = sampler1; + + DALI_TEST_CHECK(sampler1 == sampler2); + + sampler2 = Sampler::New(image, "sTexture"); + + DALI_TEST_CHECK(!(sampler1 == sampler2)); + + END_TEST; +} + +int UtcDaliSamplerSetUniformName01(void) +{ + TestApplication application; + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + sampler.SetUniformName( "sEffectTexture" ); + + Material material = CreateMaterial(1.0f); + material.AddSampler( sampler ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetParentOrigin( ParentOrigin::CENTER ); + actor.SetSize(400, 400); + + Stage::GetCurrent().Add( actor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(); + + int textureUnit=-1; + DALI_TEST_CHECK( gl.GetUniformValue( "sEffectTexture", textureUnit ) ); + DALI_TEST_EQUALS( textureUnit, 0, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliSamplerSetUniformName02(void) +{ + TestApplication application; + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Image image2 = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler1 = Sampler::New(image, "sTexture"); + sampler1.SetUniformName( "sEffectTexture" ); + + Sampler sampler2 = Sampler::New(image2, "sTexture2"); + + Material material = CreateMaterial(1.0f); + material.AddSampler( sampler1 ); + material.AddSampler( sampler2 ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetParentOrigin( ParentOrigin::CENTER ); + actor.SetSize(400, 400); + + Stage::GetCurrent().Add( actor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(); + + int textureUnit=-1; + DALI_TEST_CHECK( gl.GetUniformValue( "sEffectTexture", textureUnit ) ); + DALI_TEST_EQUALS( textureUnit, 0, TEST_LOCATION ); + + DALI_TEST_CHECK( gl.GetUniformValue( "sTexture2", textureUnit ) ); + DALI_TEST_EQUALS( textureUnit, 1, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliSamplerSetGetImage(void) +{ + TestApplication application; + + Image image1 = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Image image2 = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image1, "sTexture"); + + DALI_TEST_CHECK(image1 == sampler.GetImage()); + + sampler.SetImage( image2 ); + DALI_TEST_CHECK(!(image1 == sampler.GetImage())); + DALI_TEST_CHECK(image2 == sampler.GetImage()); + + END_TEST; +} + +int UtcSamplerSetFilterMode(void) +{ + TestApplication application; + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + + Material material = CreateMaterial(1.0f); + material.AddSampler( sampler ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetParentOrigin( ParentOrigin::CENTER ); + actor.SetSize(400, 400); + Stage::GetCurrent().Add( actor ); + + float initialValue = 1.0f; + sampler.RegisterProperty("uWidthClamp", initialValue ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + /**************************************************************/ + // Default/Default + TraceCallStack& texParameterTrace = gl.GetTexParameterTrace(); + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + sampler.SetFilterMode( Sampler::DEFAULT, Sampler::DEFAULT ); + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify gl state + + // There are two calls to TexParameteri when the texture is first created + // Texture mag filter is not called as the first time set it uses the system default + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 3, TEST_LOCATION); + + std::stringstream out; + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_LINEAR; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(2, "TexParameteri", out.str()), true, TEST_LOCATION); + + /**************************************************************/ + // Default/Default + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + sampler.SetFilterMode( Sampler::DEFAULT, Sampler::DEFAULT ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify gl state + + // Should not make any calls when settings are the same + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 0, TEST_LOCATION); + + /**************************************************************/ + // Nearest/Nearest + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + sampler.SetFilterMode( Sampler::NEAREST, Sampler::NEAREST ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify actor gl state + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 2, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_NEAREST; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MAG_FILTER << ", " << GL_NEAREST; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(1, "TexParameteri", out.str()), true, TEST_LOCATION); + + /**************************************************************/ + // Nearest/Linear + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + sampler.SetFilterMode( Sampler::NEAREST, Sampler::LINEAR ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify actor gl state + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 1, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MAG_FILTER << ", " << GL_LINEAR; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION); + + /**************************************************************/ + // NONE/NONE + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + sampler.SetFilterMode( Sampler::NONE, Sampler::NONE ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify actor gl state + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 1, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_NEAREST_MIPMAP_LINEAR; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION); + + END_TEST; +} + +int UtcSamplerSetWrapMode(void) +{ + TestApplication application; + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + + Material material = CreateMaterial(1.0f); + material.AddSampler( sampler ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetParentOrigin( ParentOrigin::CENTER ); + actor.SetSize(400, 400); + Stage::GetCurrent().Add( actor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + //**************************************** + // CLAMP_TO_EDGE / CLAMP_TO_EDGE + TraceCallStack& texParameterTrace = gl.GetTexParameterTrace(); + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify gl state + + // There are two calls to TexParameteri when the texture is first created + // Texture mag filter is not called as the first time set it uses the system default + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 3, TEST_LOCATION); + + std::stringstream out; + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_WRAP_S << ", " << GL_CLAMP_TO_EDGE; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_WRAP_T << ", " << GL_CLAMP_TO_EDGE; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(1, "TexParameteri", out.str()), true, TEST_LOCATION); + + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + sampler.SetWrapMode( Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify gl state + + // Should not make any calls when settings are the same + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 0, TEST_LOCATION); + + //Todo: Test the other wrap mode ( REPEAT, MIRRORED_REPEAT ) , currently not support!! + + END_TEST; +} + +int UtcSamplerSetAffectsTransparency(void) +{ + TestApplication application; + + Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 ); + Sampler sampler = Sampler::New(image, "sTexture"); + + Material material = CreateMaterial(1.0f); + material.AddSampler( sampler ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetParentOrigin( ParentOrigin::CENTER ); + actor.SetSize(400, 400); + Stage::GetCurrent().Add( actor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + // Test SetAffectsTransparency( false ) + sampler.SetAffectsTransparency( false ); + + gl.EnableCullFaceCallTrace(true); + application.SendNotification(); + application.Render(); + + TraceCallStack& glEnableStack = gl.GetCullFaceTrace(); + std::ostringstream blendStr; + blendStr << GL_BLEND; + DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) ); + + // Test SetAffectsTransparency( true ) + sampler.SetAffectsTransparency( true ); + + glEnableStack.Reset(); + gl.EnableCullFaceCallTrace(true); + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) ); + + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-Scripting.cpp b/automated-tests/src/dali-devel/utc-Dali-Scripting.cpp new file mode 100644 index 0000000..e001a89 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-Scripting.cpp @@ -0,0 +1,1039 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include + +using namespace Dali; +using namespace Dali::Scripting; + +namespace +{ + +const StringEnum COLOR_MODE_VALUES[] = +{ + { "USE_OWN_COLOR", USE_OWN_COLOR }, + { "USE_PARENT_COLOR", USE_PARENT_COLOR }, + { "USE_OWN_MULTIPLY_PARENT_COLOR", USE_OWN_MULTIPLY_PARENT_COLOR }, + { "USE_OWN_MULTIPLY_PARENT_ALPHA", USE_OWN_MULTIPLY_PARENT_ALPHA }, +}; +const unsigned int COLOR_MODE_VALUES_COUNT = sizeof( COLOR_MODE_VALUES ) / sizeof( COLOR_MODE_VALUES[0] ); + +const StringEnum POSITION_INHERITANCE_MODE_VALUES[] = +{ + { "INHERIT_PARENT_POSITION", INHERIT_PARENT_POSITION }, + { "USE_PARENT_POSITION", USE_PARENT_POSITION }, + { "USE_PARENT_POSITION_PLUS_LOCAL_POSITION", USE_PARENT_POSITION_PLUS_LOCAL_POSITION }, + { "DONT_INHERIT_POSITION", DONT_INHERIT_POSITION }, +}; +const unsigned int POSITION_INHERITANCE_MODE_VALUES_COUNT = sizeof( POSITION_INHERITANCE_MODE_VALUES ) / sizeof( POSITION_INHERITANCE_MODE_VALUES[0] ); + +const StringEnum DRAW_MODE_VALUES[] = +{ + { "NORMAL", DrawMode::NORMAL }, + { "OVERLAY_2D", DrawMode::OVERLAY_2D }, + { "STENCIL", DrawMode::STENCIL }, +}; +const unsigned int DRAW_MODE_VALUES_COUNT = sizeof( DRAW_MODE_VALUES ) / sizeof( DRAW_MODE_VALUES[0] ); + + +//////////////////////////////////////////////////////////////////////////////// +// Helpers for string to enum comparisons for Image and Image loading parameters +//////////////////////////////////////////////////////////////////////////////// + +/** + * Template to check enumerations of type T, with a class of type X + */ +template< typename T, typename X > +void TestEnumStrings( + Property::Map& map, // The map used to create instance of type X + const char * const keyName, // the name of the key to iterate through + const StringEnum* values, // An array of string values + unsigned int num, // Number of items in the array + T ( X::*method )() const, // The member method of X to call to get the enum + X ( *creator ) ( const Property::Value& ) // The method which creates an instance of type X +) +{ + // get the key reference so we can change its value + Property::Value* value = map.Find( keyName ); + for ( unsigned int i = 0; i < num; ++i ) + { + *value = values[i].string; + tet_printf("Checking: %s: %s\n", keyName, values[i].string ); + X instance = creator( map ); + DALI_TEST_EQUALS( values[i].value, ( instance.*method )(), TEST_LOCATION ); + } +} + +/// Helper method to create ResourceImage using property +ResourceImage NewResourceImage( const Property::Value& map ) +{ + ResourceImage image = ResourceImage::DownCast( NewImage( map ) ); + return image; +} + +/// Helper method to create ResourceImage using property +BufferImage NewBufferImage( const Property::Value& map ) +{ + BufferImage image = BufferImage::DownCast( NewImage( map ) ); + return image; +} + +////////////////////////////////////////////////////////////////////////////// +// Helpers for string to enum comparisons for Actor to Property::Map +////////////////////////////////////////////////////////////////////////////// + +/** + * Template to check enumerations of type T + */ +template< typename T > +void TestEnumStrings( + const char * const keyName, // The name of the key to check + TestApplication& application, // Reference to the application class + const StringEnum* values, // An array of string values + unsigned int num, // Number of items in the array + void ( Actor::*method )( T ) // The Actor member method to set the enumeration +) +{ + for ( unsigned int i = 0; i < num; ++i ) + { + tet_printf("Checking: %s: %s\n", keyName, values[i].string ); + + Actor actor = Actor::New(); + (actor.*method)( ( T ) values[i].value ); + + Stage::GetCurrent().Add( actor ); + application.SendNotification(); + application.Render(); + + Property::Map map; + CreatePropertyMap( actor, map ); + + DALI_TEST_CHECK( 0 < map.Count() ); + DALI_TEST_CHECK( NULL != map.Find( keyName ) ); + DALI_TEST_EQUALS( map.Find( keyName )->Get< std::string >(), values[i].string, TEST_LOCATION ); + + Stage::GetCurrent().Remove( actor ); + } +} + +////////////////////////////////////////////////////////////////////////////// + + +} // anon namespace + + + +int UtcDaliScriptingGetColorMode(void) +{ + for ( unsigned int i = 0; i < COLOR_MODE_VALUES_COUNT; ++i ) + { + tet_printf( "Checking %s == %d\n", COLOR_MODE_VALUES[i].string, COLOR_MODE_VALUES[i].value ); + DALI_TEST_EQUALS( COLOR_MODE_VALUES[i].value, GetColorMode( COLOR_MODE_VALUES[i].string ), TEST_LOCATION ); + DALI_TEST_EQUALS( COLOR_MODE_VALUES[i].string, GetColorMode( (ColorMode) COLOR_MODE_VALUES[i].value ), TEST_LOCATION ); + } + + DALI_TEST_EQUALS( USE_OWN_MULTIPLY_PARENT_ALPHA, GetColorMode("INVALID_ARG"), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliScriptingGetPositionInheritanceMode(void) +{ + for ( unsigned int i = 0; i < POSITION_INHERITANCE_MODE_VALUES_COUNT; ++i ) + { + tet_printf( "Checking %s == %d\n", POSITION_INHERITANCE_MODE_VALUES[i].string, POSITION_INHERITANCE_MODE_VALUES[i].value ); + DALI_TEST_EQUALS( POSITION_INHERITANCE_MODE_VALUES[i].value, GetPositionInheritanceMode( POSITION_INHERITANCE_MODE_VALUES[i].string ), TEST_LOCATION ); + DALI_TEST_EQUALS( POSITION_INHERITANCE_MODE_VALUES[i].string, GetPositionInheritanceMode( (PositionInheritanceMode) POSITION_INHERITANCE_MODE_VALUES[i].value ), TEST_LOCATION ); + } + + DALI_TEST_EQUALS( POSITION_INHERITANCE_MODE_VALUES[0].value, GetPositionInheritanceMode("INVALID_ARG"), TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliScriptingGetDrawMode(void) +{ + for ( unsigned int i = 0; i < DRAW_MODE_VALUES_COUNT; ++i ) + { + tet_printf( "Checking %s == %d\n", DRAW_MODE_VALUES[i].string, DRAW_MODE_VALUES[i].value ); + DALI_TEST_EQUALS( DRAW_MODE_VALUES[i].value, GetDrawMode( DRAW_MODE_VALUES[i].string ), TEST_LOCATION ); + DALI_TEST_EQUALS( DRAW_MODE_VALUES[i].string, GetDrawMode( (DrawMode::Type) DRAW_MODE_VALUES[i].value ), TEST_LOCATION ); + } + + DALI_TEST_EQUALS( DRAW_MODE_VALUES[0].value, GetDrawMode( "INVALID_ARG" ), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliScriptingGetAnchorConstant(void) +{ + DALI_TEST_EQUALS( Dali::ParentOrigin::TOP_LEFT, GetAnchorConstant( "TOP_LEFT" ), TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::ParentOrigin::TOP_CENTER, GetAnchorConstant( "TOP_CENTER" ), TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::ParentOrigin::TOP_RIGHT, GetAnchorConstant( "TOP_RIGHT" ), TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::ParentOrigin::CENTER_LEFT, GetAnchorConstant( "CENTER_LEFT" ), TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::ParentOrigin::CENTER, GetAnchorConstant( "CENTER" ), TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::ParentOrigin::CENTER_RIGHT, GetAnchorConstant( "CENTER_RIGHT" ), TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::ParentOrigin::BOTTOM_LEFT, GetAnchorConstant( "BOTTOM_LEFT" ), TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::ParentOrigin::BOTTOM_CENTER, GetAnchorConstant( "BOTTOM_CENTER" ), TEST_LOCATION ); + DALI_TEST_EQUALS( Dali::ParentOrigin::BOTTOM_RIGHT, GetAnchorConstant( "BOTTOM_RIGHT" ), TEST_LOCATION ); + + DALI_TEST_EQUALS( Vector3(), GetAnchorConstant("INVALID_ARG"), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative01(void) +{ + // Invalid filename + Property::Map map; + map[ "filename" ] = Vector3::ZERO; + // will give us an empty image handle + Image image = NewImage( map ); + DALI_TEST_CHECK( !image ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative02(void) +{ + TestApplication application; // Image needs application + // Invalid load-policy value type + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + map[ "load-policy" ] = Vector3::ZERO; + // will give us a valid image handle with default load policy + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + ResourceImage resImage = ResourceImage::DownCast( image ); + DALI_TEST_CHECK( resImage ); + DALI_TEST_EQUALS( resImage.GetLoadPolicy(), ResourceImage::IMMEDIATE, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative03(void) +{ + TestApplication application; // Image needs application + // Invalid load-policy value + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + map[ "load-policy" ] = "INVALID"; + // will give us a valid image with default load policy + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + ResourceImage resImage = ResourceImage::DownCast( image ); + DALI_TEST_CHECK( resImage ); + DALI_TEST_EQUALS( resImage.GetLoadPolicy(), ResourceImage::IMMEDIATE, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative04(void) +{ + TestApplication application; // Image needs application + // Invalid release-policy value type + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + map[ "release-policy" ] = Vector3::ZERO; + // will give us a valid image with default release policy + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + ResourceImage resImage = ResourceImage::DownCast( image ); + DALI_TEST_CHECK( resImage ); + DALI_TEST_EQUALS( resImage.GetReleasePolicy(), Image::NEVER, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative05(void) +{ + TestApplication application; // Image needs application + // Invalid release-policy value + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + map[ "release-policy" ] = "INVALID"; + // will give us a valid image with default release policy + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + ResourceImage resImage = ResourceImage::DownCast( image ); + DALI_TEST_CHECK( resImage ); + DALI_TEST_EQUALS( resImage.GetReleasePolicy(), Image::NEVER, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative06(void) +{ + TestApplication application; // Image needs application + // Invalid width and height + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + map[ "width" ] = "Invalid"; + map[ "height" ] = 100; + // will give us a valid image + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + ResourceImage resImage = ResourceImage::DownCast( image ); + DALI_TEST_CHECK( resImage ); + DALI_TEST_EQUALS( resImage.GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( resImage.GetHeight(), 100, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative07(void) +{ + TestApplication application; // Image needs application + // Invalid height + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + map[ "width" ] = 10; + map[ "height" ] = "Invalid"; + // will give us a valid image + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + ResourceImage resImage = ResourceImage::DownCast( image ); + DALI_TEST_CHECK( resImage ); + DALI_TEST_EQUALS( resImage.GetWidth(), 10, TEST_LOCATION ); + DALI_TEST_EQUALS( resImage.GetHeight(), 0, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative08(void) +{ + TestApplication application; // Image needs application + // Invalid fitting-mode + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + map[ "fitting-mode" ] = Vector3::ZERO; + // will give us a valid image + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + ResourceImage resImage = ResourceImage::DownCast( image ); + DALI_TEST_CHECK( resImage ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative09(void) +{ + TestApplication application; // Image needs application + // Invalid value + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + map[ "fitting-mode" ] = "INVALID"; + // will give us a valid image + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + ResourceImage resImage = ResourceImage::DownCast( image ); + DALI_TEST_CHECK( resImage ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative10(void) +{ + TestApplication application; // Image needs application + // Invalid scaling-mode + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + map[ "sampling-mode" ] = Vector3::ZERO; + // will give us a valid image + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + ResourceImage resImage = ResourceImage::DownCast( image ); + DALI_TEST_CHECK( resImage ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative12(void) +{ + TestApplication application; // Image needs application + // Invalid orientation-correction + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + map[ "orientation" ] = Vector3::ZERO; + // will give us a valid image + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + ResourceImage resImage = ResourceImage::DownCast( image ); + DALI_TEST_CHECK( resImage ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative13(void) +{ + TestApplication application; // Image needs application + // Invalid type + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + map[ "type" ] = Vector3::ZERO; + // will give us a valid image + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + ResourceImage resImage = ResourceImage::DownCast( image ); + DALI_TEST_CHECK( resImage ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative14(void) +{ + // Invalid value + Property::Map map; + map[ "type" ] = "INVALID"; + Image image = NewImage( map ); + DALI_TEST_CHECK( !image ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative15(void) +{ + // Invalid pixel-format + Property::Map map; + map[ "pixel-format" ] = Vector3::ZERO; + Image image = NewImage( map ); + DALI_TEST_CHECK( !image ); + END_TEST; +} + +int UtcDaliScriptingNewImageNegative16(void) +{ + // Invalid value + Property::Map map; + map[ "pixel-format" ] = "INVALID"; + Image image = NewImage( map ); + DALI_TEST_CHECK( !image ); + END_TEST; +} + +int UtcDaliScriptingNewImage01P(void) +{ + TestApplication application; // Image needs application + + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + + // Filename only + ResourceImage image = ResourceImage::DownCast( NewImage( map ) ); + DALI_TEST_EQUALS( "TEST_FILE", image.GetUrl(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliScriptingNewImage02P(void) +{ + TestApplication application; + + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + + // load-policy + map[ "load-policy" ] = ""; + const StringEnum values[] = + { + { "IMMEDIATE", ResourceImage::IMMEDIATE }, + { "ON_DEMAND", ResourceImage::ON_DEMAND } + }; + TestEnumStrings< ResourceImage::LoadPolicy, ResourceImage >( map, "load-policy", values, ( sizeof( values ) / sizeof ( values[0] ) ), &ResourceImage::GetLoadPolicy, &NewResourceImage ); + END_TEST; +} + +int UtcDaliScriptingNewImage03P(void) +{ + TestApplication application; + + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + + // release-policy + map[ "release-policy" ] = ""; + const StringEnum values[] = + { + { "UNUSED", Image::UNUSED }, + { "NEVER", Image::NEVER } + }; + TestEnumStrings< Image::ReleasePolicy, Image >( map, "release-policy", values, ( sizeof( values ) / sizeof ( values[0] ) ), &Image::GetReleasePolicy, &NewImage ); + END_TEST; +} + +int UtcDaliScriptingNewImage04P(void) +{ + TestApplication application; + + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + + // float width and height + map[ "width" ] = (float) 10.0f; + map[ "height" ] = (float) 20.0f; + Image image = NewImage( map ); + DALI_TEST_EQUALS( image.GetWidth(), 10.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( image.GetHeight(), 20.0f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliScriptingNewImage05P(void) +{ + TestApplication application; + + Property::Map map; + map[ "filename" ] = "TEST_FILE"; + + // width and height + map[ "width"] = 50; + map[ "height" ] = 70; + Image image = NewImage( map ); + DALI_TEST_EQUALS( image.GetWidth(), 50u, TEST_LOCATION ); + DALI_TEST_EQUALS( image.GetHeight(), 70u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliScriptingNewImage06P(void) +{ + TestApplication application; + + Property::Map map; + // type FrameBufferImage + map[ "type" ] = "FrameBufferImage"; + // width and height + map[ "width"] = 50; + map[ "height" ] = 70; + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + DALI_TEST_CHECK( FrameBufferImage::DownCast( image ) ); + END_TEST; +} + +int UtcDaliScriptingNewImage07P(void) +{ + TestApplication application; + + Property::Map map; + // type BufferImage + map[ "type" ] = "BufferImage"; + // width and height + map[ "width"] = 50; + map[ "height" ] = 70; + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + DALI_TEST_CHECK( BufferImage::DownCast( image ) ); + DALI_TEST_EQUALS( (BufferImage::DownCast( image )).GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliScriptingNewImage08P(void) +{ + TestApplication application; + + Property::Map map; + map[ "type" ] = "BufferImage"; + // width and height + map[ "width"] = 66; + map[ "height" ] = 99; + // pixel-format + map[ "pixel-format" ] = ""; + const StringEnum values[] = + { + { "A8", Pixel::A8 }, + { "L8", Pixel::L8 }, + { "LA88", Pixel::LA88 }, + { "RGB565", Pixel::RGB565 }, + { "BGR565", Pixel::BGR565 }, + { "RGBA4444", Pixel::RGBA4444 }, + { "BGRA4444", Pixel::BGRA4444 }, + { "RGBA5551", Pixel::RGBA5551 }, + { "BGRA5551", Pixel::BGRA5551 }, + { "RGB888", Pixel::RGB888 }, + { "RGB8888", Pixel::RGB8888 }, + { "BGR8888", Pixel::BGR8888 }, + { "RGBA8888", Pixel::RGBA8888 }, + { "BGRA8888", Pixel::BGRA8888 }, + // BufferImage does not support compressed formats + }; + TestEnumStrings< Pixel::Format, BufferImage >( map, "pixel-format", values, ( sizeof( values ) / sizeof ( values[0] ) ), &BufferImage::GetPixelFormat, &NewBufferImage ); + + END_TEST; +} + +int UtcDaliScriptingNewImage09P(void) +{ + TestApplication application; + + Property::Map map; + // type Image + map[ "type" ] = "ResourceImage"; + map[ "filename" ] = "TEST_FILE"; + + { + Image image = NewImage( map ); + DALI_TEST_CHECK( ResourceImage::DownCast( image ) ); + DALI_TEST_CHECK( !FrameBufferImage::DownCast( image ) ); + DALI_TEST_CHECK( !BufferImage::DownCast( image ) ); + } + END_TEST; +} + +int UtcDaliScriptingNewImage10P(void) +{ + TestApplication application; + + Property::Map map; + // type FrameBufferImage, empty size gives us stage size + map[ "type" ] = "FrameBufferImage"; + Image image = NewImage( map ); + DALI_TEST_CHECK( image ); + END_TEST; +} + +int UtcDaliScriptingNewShaderEffect(void) +{ + TestApplication application; + + Property::Map programMap; + programMap[ "vertex-filename" ] = "bump.vert"; + programMap[ "fragment-filename" ] = "bump.frag"; + + Property::Map imageMap; + imageMap[ "filename" ] = "image.png"; + + Property::Map map; + map[ "image" ] = imageMap; + map[ "program" ] = programMap; + map[ "uLightPosition" ] = Vector3( 0.0, 0.0, -1.5); + map[ "uAmbientLight" ] = (int)10; + + ShaderEffect shader = NewShaderEffect( map ); + + DALI_TEST_CHECK( shader ); + END_TEST; +} + +int UtcDaliScriptingNewActorNegative(void) +{ + TestApplication application; + + // Empty map + { + Actor handle = NewActor( Property::Map() ); + DALI_TEST_CHECK( !handle ); + } + + // Map with only properties + { + Property::Map map; + map[ "parent-origin" ] = ParentOrigin::TOP_CENTER; + map[ "anchor-point" ] = AnchorPoint::TOP_CENTER; + Actor handle = NewActor( map ); + DALI_TEST_CHECK( !handle ); + } + + // Add some signals to the map, we should have no signal connections as its not yet supported + { + Property::Map map; + map[ "type" ] = "Actor"; + map[ "signals" ] = Property::MAP; + Actor handle = NewActor( map ); + DALI_TEST_CHECK( handle ); + DALI_TEST_CHECK( !handle.WheelEventSignal().GetConnectionCount() ); + DALI_TEST_CHECK( !handle.OffStageSignal().GetConnectionCount() ); + DALI_TEST_CHECK( !handle.OnStageSignal().GetConnectionCount() ); + DALI_TEST_CHECK( !handle.TouchedSignal().GetConnectionCount() ); + } + END_TEST; +} + +int UtcDaliScriptingNewActorProperties(void) +{ + TestApplication application; + + Property::Map map; + map[ "type" ] = "Actor"; + map[ "size" ] = Vector3::ONE; + map[ "position" ] = Vector3::XAXIS; + map[ "scale" ] = Vector3::ONE; + map[ "visible" ] = false; + map[ "color" ] = Color::MAGENTA; + map[ "name" ] = "MyActor"; + map[ "color-mode" ] = "USE_PARENT_COLOR"; + map[ "inherit-shader-effect" ] = false; + map[ "sensitive" ] = false; + map[ "leave-required" ] = true; + map[ "position-inheritance" ] = "DONT_INHERIT_POSITION"; + map[ "draw-mode" ] = "STENCIL"; + map[ "inherit-orientation" ] = false; + map[ "inherit-scale" ] = false; + + // Default properties + { + Actor handle = NewActor( map ); + DALI_TEST_CHECK( handle ); + + Stage::GetCurrent().Add( handle ); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( handle.GetCurrentSize(), Vector3::ONE, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.GetCurrentPosition(), Vector3::XAXIS, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.GetCurrentScale(), Vector3::ONE, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.IsVisible(), false, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.GetCurrentColor(), Color::MAGENTA, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.GetName(), "MyActor", TEST_LOCATION ); + DALI_TEST_EQUALS( handle.GetColorMode(), USE_PARENT_COLOR, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.IsSensitive(), false, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.GetLeaveRequired(), true, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.GetPositionInheritanceMode(), DONT_INHERIT_POSITION, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.GetDrawMode(), DrawMode::STENCIL, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.IsOrientationInherited(), false, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.IsScaleInherited(), false, TEST_LOCATION ); + + Stage::GetCurrent().Remove( handle ); + } + + // Check Anchor point and parent origin vector3s + map[ "parent-origin" ] = ParentOrigin::TOP_CENTER; + map[ "anchor-point" ] = AnchorPoint::TOP_LEFT; + { + Actor handle = NewActor( map ); + DALI_TEST_CHECK( handle ); + + Stage::GetCurrent().Add( handle ); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( handle.GetCurrentParentOrigin(), ParentOrigin::TOP_CENTER, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.GetCurrentAnchorPoint(), AnchorPoint::TOP_LEFT, TEST_LOCATION ); + + Stage::GetCurrent().Remove( handle ); + } + + // Check Anchor point and parent origin STRINGS + map[ "parent-origin" ] = "TOP_LEFT"; + map[ "anchor-point" ] = "CENTER_LEFT"; + { + Actor handle = NewActor( map ); + DALI_TEST_CHECK( handle ); + + Stage::GetCurrent().Add( handle ); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( handle.GetCurrentParentOrigin(), ParentOrigin::TOP_LEFT, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.GetCurrentAnchorPoint(), AnchorPoint::CENTER_LEFT, TEST_LOCATION ); + + Stage::GetCurrent().Remove( handle ); + } + END_TEST; +} + +int UtcDaliScriptingNewActorChildren(void) +{ + TestApplication application; + + Property::Map map; + map[ "type" ] = "Actor"; + map[ "position" ] = Vector3::XAXIS; + + Property::Map child1Map; + child1Map[ "type" ] = "ImageActor"; + child1Map[ "position" ] = Vector3::YAXIS; + + Property::Array childArray; + childArray.PushBack( child1Map ); + map[ "actors" ] = childArray; + + // Create + Actor handle = NewActor( map ); + DALI_TEST_CHECK( handle ); + + Stage::GetCurrent().Add( handle ); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( handle.GetCurrentPosition(), Vector3::XAXIS, TEST_LOCATION ); + DALI_TEST_EQUALS( handle.GetChildCount(), 1u, TEST_LOCATION ); + + Actor child1 = handle.GetChildAt(0); + DALI_TEST_CHECK( child1 ); + DALI_TEST_CHECK( ImageActor::DownCast( child1 ) ); + DALI_TEST_EQUALS( child1.GetCurrentPosition(), Vector3::YAXIS, TEST_LOCATION ); + DALI_TEST_EQUALS( child1.GetChildCount(), 0u, TEST_LOCATION ); + + Stage::GetCurrent().Remove( handle ); + END_TEST; +} + + +int UtcDaliScriptingCreatePropertyMapActor(void) +{ + TestApplication application; + + // Actor Type + { + Actor actor = Actor::New(); + + Property::Map map; + CreatePropertyMap( actor, map ); + DALI_TEST_CHECK( !map.Empty() ); + DALI_TEST_CHECK( NULL != map.Find( "type" ) ); + DALI_TEST_EQUALS( map.Find( "type")->Get< std::string >(), "Actor", TEST_LOCATION ); + + Stage::GetCurrent().Remove( actor ); + } + + // ImageActor Type + { + Actor actor = ImageActor::New(); + + Property::Map map; + CreatePropertyMap( actor, map ); + DALI_TEST_CHECK( !map.Empty() ); + DALI_TEST_CHECK( NULL != map.Find( "type" ) ); + DALI_TEST_EQUALS( map.Find( "type" )->Get< std::string >(), "ImageActor", TEST_LOCATION ); + + Stage::GetCurrent().Remove( actor ); + } + + // Default properties + { + Actor actor = Actor::New(); + actor.SetSize( Vector3::ONE ); + actor.SetPosition( Vector3::XAXIS ); + actor.SetScale( Vector3::ZAXIS ); + actor.SetVisible( false ); + actor.SetColor( Color::MAGENTA ); + actor.SetName( "MyActor" ); + actor.SetAnchorPoint( AnchorPoint::CENTER_LEFT ); + actor.SetParentOrigin( ParentOrigin::TOP_RIGHT ); + actor.SetSensitive( false ); + actor.SetLeaveRequired( true ); + actor.SetInheritOrientation( false ); + actor.SetInheritScale( false ); + actor.SetSizeModeFactor( Vector3::ONE ); + + Stage::GetCurrent().Add( actor ); + application.SendNotification(); + application.Render(); + + Property::Map map; + CreatePropertyMap( actor, map ); + + DALI_TEST_CHECK( !map.Empty() ); + DALI_TEST_CHECK( NULL != map.Find( "size" ) ); + DALI_TEST_EQUALS( map.Find( "size" )->Get< Vector3 >(), Vector3::ONE, TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "position" ) ); + DALI_TEST_EQUALS( map.Find( "position" )->Get< Vector3 >(), Vector3::XAXIS, TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "scale" ) ); + DALI_TEST_EQUALS( map.Find( "scale" )->Get< Vector3 >(), Vector3::ZAXIS, TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "visible" ) ); + DALI_TEST_EQUALS( map.Find( "visible" )->Get< bool >(), false, TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "color" ) ); + DALI_TEST_EQUALS( map.Find( "color" )->Get< Vector4 >(), Color::MAGENTA, TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "name" ) ); + DALI_TEST_EQUALS( map.Find( "name")->Get< std::string >(), "MyActor", TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "anchor-point" ) ); + DALI_TEST_EQUALS( map.Find( "anchor-point" )->Get< Vector3 >(), AnchorPoint::CENTER_LEFT, TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "parent-origin" ) ); + DALI_TEST_EQUALS( map.Find( "parent-origin" )->Get< Vector3 >(), ParentOrigin::TOP_RIGHT, TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "sensitive" ) ); + DALI_TEST_EQUALS( map.Find( "sensitive" )->Get< bool >(), false, TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "leave-required" ) ); + DALI_TEST_EQUALS( map.Find( "leave-required" )->Get< bool >(), true, TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "inherit-orientation" ) ); + DALI_TEST_EQUALS( map.Find( "inherit-orientation" )->Get< bool >(), false, TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "inherit-scale" ) ); + DALI_TEST_EQUALS( map.Find( "inherit-scale" )->Get< bool >(), false, TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "size-mode-factor" ) ); + DALI_TEST_EQUALS( map.Find( "size-mode-factor" )->Get< Vector3 >(), Vector3::ONE, TEST_LOCATION ); + + Stage::GetCurrent().Remove( actor ); + } + + // ColorMode + TestEnumStrings< ColorMode >( "color-mode", application, COLOR_MODE_VALUES, COLOR_MODE_VALUES_COUNT, &Actor::SetColorMode ); + + // PositionInheritanceMode + TestEnumStrings< PositionInheritanceMode >( "position-inheritance", application, POSITION_INHERITANCE_MODE_VALUES, POSITION_INHERITANCE_MODE_VALUES_COUNT, &Actor::SetPositionInheritanceMode ); + + // DrawMode + TestEnumStrings< DrawMode::Type >( "draw-mode", application, DRAW_MODE_VALUES, DRAW_MODE_VALUES_COUNT, &Actor::SetDrawMode ); + + // Children + { + Actor actor = Actor::New(); + Actor child = ImageActor::New(); + actor.Add( child ); + + Stage::GetCurrent().Add( actor ); + application.SendNotification(); + application.Render(); + + Property::Map map; + CreatePropertyMap( actor, map ); + DALI_TEST_CHECK( !map.Empty() ); + + DALI_TEST_CHECK( NULL != map.Find( "type" ) ); + DALI_TEST_EQUALS( map.Find( "type" )->Get< std::string >(), "Actor", TEST_LOCATION ); + + DALI_TEST_CHECK( NULL != map.Find( "actors" ) ); + Property::Array children( map.Find( "actors")->Get< Property::Array >() ); + DALI_TEST_CHECK( !children.Empty() ); + Property::Map childMap( children[0].Get< Property::Map >() ); + DALI_TEST_CHECK( !childMap.Empty() ); + DALI_TEST_CHECK( childMap.Find( "type" ) ); + DALI_TEST_EQUALS( childMap.Find( "type" )->Get< std::string >(), "ImageActor", TEST_LOCATION ); + + Stage::GetCurrent().Remove( actor ); + } + END_TEST; +} + +int UtcDaliScriptingCreatePropertyMapImage(void) +{ + TestApplication application; + + // Empty + { + Image image; + Property::Map map; + CreatePropertyMap( image, map ); + DALI_TEST_CHECK( map.Empty() ); + } + + // Default + { + Image image = ResourceImage::New( "MY_PATH" ); + + Property::Map map; + CreatePropertyMap( image, map ); + DALI_TEST_CHECK( !map.Empty() ); + + DALI_TEST_CHECK( NULL != map.Find( "type" ) ); + DALI_TEST_EQUALS( map.Find( "type" )->Get< std::string >(), "ResourceImage", TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "filename" ) ); + DALI_TEST_EQUALS( map.Find( "filename" )->Get< std::string >(), "MY_PATH", TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "load-policy") ); + DALI_TEST_EQUALS( map.Find( "load-policy" )->Get< std::string >(), "IMMEDIATE", TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "release-policy") ); + DALI_TEST_EQUALS( map.Find( "release-policy" )->Get< std::string >(), "NEVER", TEST_LOCATION ); + DALI_TEST_CHECK( NULL == map.Find( "width" ) ); + DALI_TEST_CHECK( NULL == map.Find( "height" ) ); + } + + // Change values + { + ResourceImage image = ResourceImage::New( "MY_PATH", ResourceImage::ON_DEMAND, Image::UNUSED, ImageDimensions( 300, 400 ), FittingMode::FIT_WIDTH ); + + Property::Map map; + CreatePropertyMap( image, map ); + DALI_TEST_CHECK( !map.Empty() ); + + DALI_TEST_CHECK( NULL != map.Find( "type" ) ); + DALI_TEST_EQUALS( map.Find( "type" )->Get< std::string >(), "ResourceImage", TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "filename" ) ); + DALI_TEST_EQUALS( map.Find( "filename" )->Get< std::string >(), "MY_PATH", TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "load-policy") ); + DALI_TEST_EQUALS( map.Find( "load-policy" )->Get< std::string >(), "ON_DEMAND", TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "release-policy") ); + DALI_TEST_EQUALS( map.Find( "release-policy" )->Get< std::string >(), "UNUSED", TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "width" ) ); + DALI_TEST_EQUALS( map.Find( "width" )->Get< int >(), 300, TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "height" ) ); + DALI_TEST_EQUALS( map.Find( "height" )->Get< int >(), 400, TEST_LOCATION ); + } + + // BufferImage + { + Image image = BufferImage::New( 200, 300, Pixel::A8 ); + Property::Map map; + CreatePropertyMap( image, map ); + DALI_TEST_CHECK( NULL != map.Find( "type" ) ); + DALI_TEST_EQUALS( map.Find( "type" )->Get< std::string >(), "BufferImage", TEST_LOCATION ); + DALI_TEST_CHECK( NULL != map.Find( "pixel-format") ); + DALI_TEST_EQUALS( map.Find( "pixel-format" )->Get< std::string >(), "A8", TEST_LOCATION ); + } + + // FrameBufferImage + { + Image image = FrameBufferImage::New( 200, 300, Pixel::RGBA8888 ); + Property::Map map; + CreatePropertyMap( image, map ); + DALI_TEST_CHECK( NULL != map.Find( "type" ) ); + DALI_TEST_EQUALS( map.Find( "type" )->Get< std::string >(), "FrameBufferImage", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliScriptingGetEnumerationTemplates(void) +{ + const Scripting::StringEnum myTable[] = + { + { "ONE", 1 }, + { "TWO", 2 }, + { "THREE", 3 }, + { "FOUR", 4 }, + { "FIVE", 5 }, + }; + const unsigned int myTableCount = sizeof( myTable ) / sizeof( myTable[0] ); + + for ( unsigned int i = 0; i < myTableCount; ++i ) + { + tet_printf("Checking: %s\n", myTable[ i ].string ); + int value; + DALI_TEST_CHECK( GetEnumeration( myTable[ i ].string, myTable, myTableCount, value ) ); + DALI_TEST_EQUALS( myTable[ i ].value, value, TEST_LOCATION ); + } + + for ( unsigned int i = 0; i < myTableCount; ++i ) + { + tet_printf("Checking: %d\n", myTable[ i ].value ); + DALI_TEST_EQUALS( myTable[ i ].string, GetEnumerationName( myTable[ i ].value, myTable, myTableCount ), TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliScriptingGetEnumerationNameN(void) +{ + const char* value = GetEnumerationName( 10, NULL, 0 ); + DALI_TEST_CHECK( NULL == value ); + + value = GetEnumerationName( 10, NULL, 1 ); + DALI_TEST_CHECK( NULL == value ); + + END_TEST; +} + +int UtcDaliScriptingGetLinearEnumerationNameN(void) +{ + const char* value = GetLinearEnumerationName( 10, NULL, 0 ); + DALI_TEST_CHECK( NULL == value ); + + value = GetLinearEnumerationName( 10, NULL, 1 ); + DALI_TEST_CHECK( NULL == value ); + + END_TEST; +} + +int UtcDaliScriptingFindEnumIndexN(void) +{ + const Scripting::StringEnum myTable[] = + { + { "ONE", 1 }, + { "TWO", 2 }, + { "THREE", 3 }, + { "FOUR", 4 }, + { "FIVE", 5 }, + }; + const unsigned int myTableCount = sizeof( myTable ) / sizeof( myTable[0] ); + DALI_TEST_EQUALS( myTableCount, FindEnumIndex( "Foo", myTable, myTableCount ), TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-Shader.cpp b/automated-tests/src/dali-devel/utc-Dali-Shader.cpp new file mode 100644 index 0000000..5cf3a34 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-Shader.cpp @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include + +using namespace Dali; + +void utc_dali_shader_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_shader_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +static const char* VertexSource = +"This is a custom vertex shader\n" +"made on purpose to look nothing like a normal vertex shader inside dali\n"; + +static const char* FragmentSource = +"This is a custom fragment shader\n" +"made on purpose to look nothing like a normal fragment shader inside dali\n"; + + +void TestConstraintNoBlue( Vector4& current, const PropertyInputContainer& inputs ) +{ + current.b = 0.0f; +} + + +} // anon namespace + + +int UtcDaliShaderMethodNew01(void) +{ + TestApplication application; + + Shader shader = Shader::New( VertexSource, FragmentSource ); + DALI_TEST_EQUALS((bool)shader, true, TEST_LOCATION); + END_TEST; +} + +int UtcDaliShaderMethodNew02(void) +{ + TestApplication application; + + Shader shader; + DALI_TEST_EQUALS((bool)shader, false, TEST_LOCATION); + END_TEST; +} + +int UtcDaliShaderAssignmentOperator(void) +{ + TestApplication application; + + Shader shader1 = Shader::New(VertexSource, FragmentSource); + + Shader shader2; + + DALI_TEST_CHECK(!(shader1 == shader2)); + + shader2 = shader1; + + DALI_TEST_CHECK(shader1 == shader2); + + shader2 = Shader::New(VertexSource, FragmentSource);; + + DALI_TEST_CHECK(!(shader1 == shader2)); + + END_TEST; +} + +int UtcDaliShaderDownCast01(void) +{ + TestApplication application; + + Shader shader = Shader::New(VertexSource, FragmentSource); + + BaseHandle handle(shader); + Shader shader2 = Shader::DownCast(handle); + DALI_TEST_EQUALS( (bool)shader2, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliShaderDownCast02(void) +{ + TestApplication application; + + Handle handle = Handle::New(); // Create a custom object + Shader shader = Shader::DownCast(handle); + DALI_TEST_EQUALS( (bool)shader, false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliShaderConstraint01(void) +{ + TestApplication application; + + tet_infoline("Test that a non-uniform shader property can be constrained"); + + Shader shader = Shader::New(VertexSource, FragmentSource); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = shader.RegisterProperty( "uFadeColor", initialColor ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( shader.GetProperty(colorIndex), initialColor, TEST_LOCATION ); + + // Apply constraint + Constraint constraint = Constraint::New( shader, colorIndex, TestConstraintNoBlue ); + constraint.Apply(); + application.SendNotification(); + application.Render(0); + + // Expect no blue component in either buffer - yellow + DALI_TEST_EQUALS( shader.GetProperty(colorIndex), Color::YELLOW, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( shader.GetProperty(colorIndex), Color::YELLOW, TEST_LOCATION ); + + shader.RemoveConstraints(); + shader.SetProperty(colorIndex, Color::WHITE ); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( shader.GetProperty(colorIndex), Color::WHITE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliShaderConstraint02(void) +{ + TestApplication application; + + tet_infoline("Test that a uniform map shader property can be constrained"); + + Shader shader = Shader::New(VertexSource, FragmentSource); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = shader.RegisterProperty( "uFadeColor", initialColor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION ); + + // Apply constraint + Constraint constraint = Constraint::New( shader, colorIndex, TestConstraintNoBlue ); + constraint.Apply(); + application.SendNotification(); + application.Render(0); + + // Expect no blue component in either buffer - yellow + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + application.Render(0); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION ); + + shader.RemoveConstraints(); + shader.SetProperty(colorIndex, Color::WHITE ); + application.SendNotification(); + application.Render(0); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::WHITE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliShaderAnimatedProperty01(void) +{ + TestApplication application; + + tet_infoline("Test that a non-uniform shader property can be animated"); + + Shader shader = Shader::New(VertexSource, FragmentSource); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = shader.RegisterProperty( "uFadeColor", initialColor ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( shader.GetProperty(colorIndex), initialColor, TEST_LOCATION ); + + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, initialColor); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( shader, colorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_EQUALS( shader.GetProperty(colorIndex), Color::WHITE * 0.5f, TEST_LOCATION ); + + application.Render(500); + + DALI_TEST_EQUALS( shader.GetProperty(colorIndex), Color::TRANSPARENT, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliShaderAnimatedProperty02(void) +{ + TestApplication application; + + tet_infoline("Test that a uniform map shader property can be animated"); + + Shader shader = Shader::New(VertexSource, FragmentSource); + Material material = Material::New( shader ); + material.SetProperty(Material::Property::COLOR, Color::WHITE); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New( geometry, material ); + + Actor actor = Actor::New(); + actor.AddRenderer(renderer); + actor.SetSize(400, 400); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + + Vector4 initialColor = Color::WHITE; + Property::Index colorIndex = shader.RegisterProperty( "uFadeColor", initialColor ); + + TestGlAbstraction& gl = application.GetGlAbstraction(); + + application.SendNotification(); + application.Render(0); + + Vector4 actualValue(Vector4::ZERO); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION ); + + Animation animation = Animation::New(1.0f); + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, initialColor); + keyFrames.Add(1.0f, Color::TRANSPARENT); + animation.AnimateBetween( Property( shader, colorIndex ), keyFrames ); + animation.Play(); + + application.SendNotification(); + application.Render(500); + + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::WHITE * 0.5f, TEST_LOCATION ); + + application.Render(500); + DALI_TEST_CHECK( gl.GetUniformValue( "uFadeColor", actualValue ) ); + DALI_TEST_EQUALS( actualValue, Color::TRANSPARENT, TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali-devel/utc-Dali-WeakHandle.cpp b/automated-tests/src/dali-devel/utc-Dali-WeakHandle.cpp new file mode 100644 index 0000000..fedb2e1 --- /dev/null +++ b/automated-tests/src/dali-devel/utc-Dali-WeakHandle.cpp @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +using namespace Dali; + +namespace +{ + +/******************************************************************************* + * + * Custom Actor + * + ******************************************************************************/ +namespace Impl +{ +struct MyTestCustomActor : public CustomActorImpl +{ + typedef Signal< void ()> SignalType; + typedef Signal< void (float)> SignalTypeFloat; + + MyTestCustomActor() : CustomActorImpl( ActorFlags( REQUIRES_TOUCH_EVENTS ) ) + { } + + virtual ~MyTestCustomActor() + { } + + void ResetCallStack() + { + } + + // From CustomActorImpl + virtual void OnStageConnection( int depth ) + { + } + virtual void OnStageDisconnection() + { + } + virtual void OnChildAdd(Actor& child) + { + } + virtual void OnChildRemove(Actor& child) + { + } + virtual void OnSizeSet(const Vector3& targetSize) + { + } + virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize) + { + } + virtual bool OnTouchEvent(const TouchEvent& event) + { + return true; + } + virtual bool OnHoverEvent(const HoverEvent& event) + { + return true; + } + virtual bool OnWheelEvent(const WheelEvent& event) + { + return true; + } + virtual bool OnKeyEvent(const KeyEvent& event) + { + return true; + } + virtual void OnKeyInputFocusGained() + { + } + virtual void OnKeyInputFocusLost() + { + } + virtual Vector3 GetNaturalSize() + { + return Vector3( 0.0f, 0.0f, 0.0f ); + } + + virtual float GetHeightForWidth( float width ) + { + return 0.0f; + } + + virtual float GetWidthForHeight( float height ) + { + return 0.0f; + } + + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ) + { + } + + virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) + { + } + + virtual void OnCalculateRelayoutSize( Dimension::Type dimension ) + { + } + + virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension ) + { + return 0.0f; + } + + virtual void OnLayoutNegotiated( float size, Dimension::Type dimension ) + { + } + + virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) + { + return false; + } + +public: + + SignalType mSignal; +}; + +}; // namespace Impl + +class MyTestCustomActor : public CustomActor +{ +public: + + typedef Signal< void ()> SignalType; + typedef Signal< void (float)> SignalTypeFloat; + + MyTestCustomActor() + { + } + + static MyTestCustomActor New() + { + Impl::MyTestCustomActor* p = new Impl::MyTestCustomActor; + return MyTestCustomActor( *p ); // takes ownership + } + + virtual ~MyTestCustomActor() + { + } + + static MyTestCustomActor DownCast( BaseHandle handle ) + { + MyTestCustomActor result; + + CustomActor custom = Dali::CustomActor::DownCast( handle ); + if ( custom ) + { + CustomActorImpl& customImpl = custom.GetImplementation(); + + Impl::MyTestCustomActor* impl = dynamic_cast(&customImpl); + + if (impl) + { + result = MyTestCustomActor(customImpl.GetOwner()); + } + } + + return result; + } + + SignalType& GetCustomSignal() + { + Dali::RefObject& obj = GetImplementation(); + return static_cast( obj ).mSignal; + } + + MyTestCustomActor(Internal::CustomActor* internal) + : CustomActor(internal) + { + } + + MyTestCustomActor( Impl::MyTestCustomActor& impl ) + : CustomActor( impl ) + { + } +}; + +} + +int UtcDaliWeakHandleBaseConstructorVoid(void) +{ + TestApplication application; + tet_infoline("Testing Dali::WeakHandleBase::WeakHandleBase()"); + + WeakHandleBase object; + + DALI_TEST_CHECK(!object.GetBaseHandle()); + + END_TEST; +} + +int UtcDaliWeakHandleBaseConstructorWithHandle(void) +{ + TestApplication application; + tet_infoline("Testing Dali::WeakHandleBase::WeakHandleBase(Handle)"); + + Handle emptyHandle; + WeakHandleBase emptyObject(emptyHandle); + DALI_TEST_CHECK(!emptyObject.GetBaseHandle()); + + Actor actor = Actor::New(); + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + + END_TEST; +} + +int UtcDaliWeakHandleBaseCopyConstructor(void) +{ + TestApplication application; + tet_infoline("Testing Dali::WeakHandleBase::WeakHandleBase(const WeakHandleBase&)"); + + Actor actor = Actor::New(); + DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased + + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased + + WeakHandleBase copy(object); + DALI_TEST_CHECK(copy.GetBaseHandle() == actor); + DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased + + END_TEST; +} + +int UtcDaliWeakHandleBaseAssignmentOperator(void) +{ + TestApplication application; + tet_infoline("Testing Dali::WeakHandleBase::operator="); + + Actor actor = Actor::New(); + DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased + + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased + + WeakHandleBase copy = object; + DALI_TEST_CHECK(copy.GetBaseHandle() == actor); + DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased + + END_TEST; +} + +int UtcDaliWeakHandleBaseEqualityOperatorP(void) +{ + TestApplication application; + tet_infoline("Positive Test Dali::WeakHandleBase::operator=="); + + WeakHandleBase object; + WeakHandleBase theSameObject; + DALI_TEST_CHECK(object == theSameObject); + + Actor actor = Actor::New(); + + object = WeakHandleBase(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + + theSameObject = object; + DALI_TEST_CHECK(theSameObject.GetBaseHandle() == actor); + DALI_TEST_CHECK(object == theSameObject); + + END_TEST; +} + +int UtcDaliWeakHandleBaseEqualityOperatorN(void) +{ + TestApplication application; + tet_infoline("Negative Test Dali::WeakHandleBase::operator=="); + + Actor actor = Actor::New(); + + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + + Actor differentActor = Actor::New(); + WeakHandleBase aDifferentWeakHandleBase(differentActor); + + DALI_TEST_CHECK(!(object == aDifferentWeakHandleBase)); + + END_TEST; +} + +int UtcDaliWeakHandleBaseInequalityOperatorP(void) +{ + TestApplication application; + tet_infoline("Positive Test Dali::WeakHandleBase::operator!="); + + Actor actor = Actor::New(); + + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + + Actor differentActor = Actor::New(); + WeakHandleBase aDifferentWeakHandleBase(differentActor); + + DALI_TEST_CHECK(object != aDifferentWeakHandleBase); + END_TEST; +} + +int UtcDaliWeakHandleBaseInequalityOperatorN(void) +{ + TestApplication application; + tet_infoline("Negative Test Dali::WeakHandleBase::operator!="); + + Actor actor = Actor::New(); + + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + + WeakHandleBase theSameWeakHandleBase = object; + + DALI_TEST_CHECK(!(object != theSameWeakHandleBase)); + END_TEST; +} + +int UtcDaliWeakHandleBaseGetBaseHandle(void) +{ + TestApplication application; + tet_infoline("Testing Dali::WeakHandleBase::GetBaseHandle()"); + + Handle emptyHandle; + WeakHandleBase emptyObject(emptyHandle); + DALI_TEST_CHECK(!emptyObject.GetBaseHandle()); + + Actor actor = Actor::New(); + WeakHandleBase object(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == actor); + + WeakHandleBase theSameObject = WeakHandleBase(actor); + DALI_TEST_CHECK(object.GetBaseHandle() == theSameObject.GetBaseHandle()); + + Actor differentActor = Actor::New(); + WeakHandleBase aDifferentWeakHandleBase(differentActor); + DALI_TEST_CHECK(object.GetBaseHandle() != aDifferentWeakHandleBase.GetBaseHandle()); + + END_TEST; +} + +int UtcDaliWeakHandleGetHandle(void) +{ + TestApplication application; + tet_infoline("Testing Dali::WeakHandle::GetHandle()"); + + Actor actor = Actor::New(); + WeakHandle object(actor); + DALI_TEST_CHECK(object.GetHandle() == actor); + + MyTestCustomActor customActor = MyTestCustomActor::New(); + WeakHandle customObject(customActor); + DALI_TEST_CHECK(customObject.GetHandle() == customActor); + + DALI_TEST_CHECK(object.GetHandle() != customObject.GetHandle()); + + END_TEST; +} + + + diff --git a/automated-tests/src/dali-internal/CMakeLists.txt b/automated-tests/src/dali-internal/CMakeLists.txt new file mode 100644 index 0000000..8678b55 --- /dev/null +++ b/automated-tests/src/dali-internal/CMakeLists.txt @@ -0,0 +1,57 @@ +SET(PKG_NAME "dali-internal") + +SET(EXEC_NAME "tct-${PKG_NAME}-core") +SET(RPM_NAME "core-${PKG_NAME}-tests") + +SET(CAPI_LIB "dali-internal") + +SET(TC_SOURCES + utc-Dali-Internal-Handles.cpp + utc-Dali-Internal-ImageFactory.cpp + utc-Dali-Internal-ResourceClient.cpp + utc-Dali-Internal-Image-Culling.cpp + utc-Dali-Internal-FixedSizeMemoryPool.cpp + utc-Dali-Internal-MemoryPoolObjectAllocator.cpp + utc-Dali-Internal-FrustumCulling.cpp +) + +LIST(APPEND TC_SOURCES + ../dali/dali-test-suite-utils/mesh-builder.cpp + ../dali/dali-test-suite-utils/test-harness.cpp + ../dali/dali-test-suite-utils/dali-test-suite-utils.cpp + ../dali/dali-test-suite-utils/test-application.cpp + ../dali/dali-test-suite-utils/test-gesture-manager.cpp + ../dali/dali-test-suite-utils/test-gl-abstraction.cpp + ../dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp + ../dali/dali-test-suite-utils/test-native-image.cpp + ../dali/dali-test-suite-utils/test-platform-abstraction.cpp + ../dali/dali-test-suite-utils/test-render-controller.cpp + ../dali/dali-test-suite-utils/test-trace-call-stack.cpp +) + +PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED + dali-core +) + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${${CAPI_LIB}_CFLAGS_OTHER} -O0 -ggdb --coverage -Wall -Werror=return-type") + +FOREACH(directory ${${CAPI_LIB}_LIBRARY_DIRS}) + SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -L${directory}") +ENDFOREACH(directory ${CAPI_LIB_LIBRARY_DIRS}) + +INCLUDE_DIRECTORIES( + ../../.. + . + ${${CAPI_LIB}_INCLUDE_DIRS} + ../dali/dali-test-suite-utils + ../dali-devel +) + +ADD_EXECUTABLE(${EXEC_NAME} ${EXEC_NAME}.cpp ${TC_SOURCES}) +TARGET_LINK_LIBRARIES(${EXEC_NAME} + ${${CAPI_LIB}_LIBRARIES} +) + +INSTALL(PROGRAMS ${EXEC_NAME} + DESTINATION ${BIN_DIR}/${EXEC_NAME} +) diff --git a/automated-tests/src/dali-internal/tct-dali-internal-core.cpp b/automated-tests/src/dali-internal/tct-dali-internal-core.cpp new file mode 100644 index 0000000..359a7d2 --- /dev/null +++ b/automated-tests/src/dali-internal/tct-dali-internal-core.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include "tct-dali-internal-core.h" + +int main(int argc, char * const argv[]) +{ + int result = TestHarness::EXIT_STATUS_BAD_ARGUMENT; + + const char* optString = "r"; + bool optRerunFailed(false); + + int nextOpt = 0; + do + { + nextOpt = getopt( argc, argv, optString ); + switch(nextOpt) + { + case 'r': + optRerunFailed = true; + break; + case '?': + TestHarness::Usage(argv[0]); + exit(TestHarness::EXIT_STATUS_BAD_ARGUMENT); + break; + } + } while( nextOpt != -1 ); + + if( optind == argc ) // no testcase name in argument list + { + result = TestHarness::RunAllInParallel(argv[0], tc_array, optRerunFailed); + } + else + { + // optind is index of next argument - interpret as testcase name + result = TestHarness::FindAndRunTestCase(tc_array, argv[optind]); + } + return result; +} diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-FixedSizeMemoryPool.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-FixedSizeMemoryPool.cpp new file mode 100644 index 0000000..c4f653f --- /dev/null +++ b/automated-tests/src/dali-internal/utc-Dali-Internal-FixedSizeMemoryPool.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +// Internal headers are allowed here + +#include + +using namespace Dali; + +void utc_dali_internal_fixedsizememorypool_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_internal_fixedsizememorypool_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +unsigned int gTestObjectConstructed = 0; +unsigned int gTestObjectDestructed = 0; +unsigned int gTestObjectMethod = 0; +unsigned int gTestObjectDataAccess = 0; + +} // namespace + + +class TestObject +{ +public: + + TestObject() + : mData1( 0 ), + mData2( false ) + { + gTestObjectConstructed++; + } + + ~TestObject() + { + gTestObjectDestructed++; + } + + void Method() + { + gTestObjectMethod++; + } + + void DataAccess() + { + mData1++; + mData2 = true; + + gTestObjectDataAccess++; + } + +private: + + unsigned int mData1; + bool mData2; + +}; + +int UtcDaliFixedSizeMemoryPoolCreate(void) +{ + gTestObjectConstructed = 0; + gTestObjectDestructed = 0; + gTestObjectMethod = 0; + gTestObjectDataAccess = 0; + + Internal::FixedSizeMemoryPool memoryPool( Internal::TypeSizeWithAlignment< TestObject >::size ); + + TestObject* testObject1 = new (memoryPool.Allocate()) TestObject(); + DALI_TEST_CHECK( testObject1 ); + DALI_TEST_EQUALS( gTestObjectConstructed, 1U, TEST_LOCATION ); + + testObject1->Method(); + DALI_TEST_EQUALS( gTestObjectMethod, 1U, TEST_LOCATION ); + + testObject1->DataAccess(); + DALI_TEST_EQUALS( gTestObjectDataAccess, 1U, TEST_LOCATION ); + + testObject1->~TestObject(); + memoryPool.Free( testObject1 ); + DALI_TEST_EQUALS( gTestObjectDestructed, 1U, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliFixedSizeMemoryPoolStressTest(void) +{ + gTestObjectConstructed = 0; + gTestObjectDestructed = 0; + gTestObjectMethod = 0; + gTestObjectDataAccess = 0; + + const size_t initialCapacity = 32; + const size_t maximumCapacity = 1024; + + const unsigned int numObjects = 1024 * 1024; + + Internal::FixedSizeMemoryPool memoryPool( Internal::TypeSizeWithAlignment< TestObject >::size, initialCapacity, maximumCapacity ); + + Dali::Vector objects; + objects.Reserve( numObjects ); + + for( unsigned int i = 0; i < numObjects; ++i ) + { + TestObject* testObject = new ( memoryPool.Allocate() ) TestObject(); + DALI_TEST_CHECK( testObject ); + + objects.PushBack( testObject ); + } + + DALI_TEST_EQUALS( gTestObjectConstructed, numObjects, TEST_LOCATION ); + + for( unsigned int i = 0; i < numObjects; ++i ) + { + objects[i]->~TestObject(); + memoryPool.Free( objects[i] ); + } + + DALI_TEST_EQUALS( gTestObjectDestructed, numObjects, TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-FrustumCulling.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-FrustumCulling.cpp new file mode 100644 index 0000000..5a65c6d --- /dev/null +++ b/automated-tests/src/dali-internal/utc-Dali-Internal-FrustumCulling.cpp @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; + +#define MAKE_SHADER(A)#A + +const char* VERTEX_SHADER = MAKE_SHADER( +attribute mediump vec2 aPosition; +attribute mediump vec2 aTexCoord; +uniform mediump mat4 uMvpMatrix; +uniform mediump vec3 uSize; +varying mediump vec2 vTexCoord; + +void main() +{ + mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0); + vertexPosition.xyz *= uSize; + vertexPosition = uMvpMatrix * vertexPosition; + vTexCoord = aTexCoord; + gl_Position = vertexPosition; +} +); + +const char* FRAGMENT_SHADER = MAKE_SHADER( +uniform Sampler2D sTexture; +varying mediump vec2 vTexCoord; +void main() +{ + gl_FragColor = texture2D( sTexture, vTexCoord ); +} +); + +Geometry CreateGeometry() +{ + const float halfQuadSize = .5f; + struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; }; + TexturedQuadVertex texturedQuadVertexData[4] = { + { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) }, + { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) }, + { Vector2(-halfQuadSize, halfQuadSize), Vector2(0.f, 1.f) }, + { Vector2( halfQuadSize, halfQuadSize), Vector2(1.f, 1.f) } }; + + Property::Map texturedQuadVertexFormat; + texturedQuadVertexFormat["aPosition"] = Property::VECTOR2; + texturedQuadVertexFormat["aTexCoord"] = Property::VECTOR2; + PropertyBuffer texturedQuadVertices = PropertyBuffer::New( texturedQuadVertexFormat, 4 ); + texturedQuadVertices.SetData(texturedQuadVertexData); + + // Create indices + unsigned int indexData[6] = { 0, 3, 1, 0, 2, 3 }; + Property::Map indexFormat; + indexFormat["indices"] = Property::INTEGER; + PropertyBuffer indices = PropertyBuffer::New( indexFormat, sizeof(indexData)/sizeof(indexData[0]) ); + indices.SetData(indexData); + + // Create the geometry object + Geometry texturedQuadGeometry = Geometry::New(); + texturedQuadGeometry.AddVertexBuffer( texturedQuadVertices ); + texturedQuadGeometry.SetIndexBuffer( indices ); + + return texturedQuadGeometry; +} + +int UtcFrustumCullN(void) +{ + TestApplication application; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ]; + BufferImage image = BufferImage::New( pixelBuffer, 1, 1 ); + + Geometry geometry = CreateGeometry(); + Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) ); + Sampler sampler = Sampler::New( image, "sTexture" ); + material.AddSampler( sampler ); + Renderer renderer = Renderer::New( geometry, material ); + + Actor meshActor = Actor::New(); + meshActor.AddRenderer( renderer ); + meshActor.SetSize(400, 400); + drawTrace.Reset(); + + meshActor.SetParentOrigin( ParentOrigin::CENTER ); + meshActor.SetAnchorPoint( AnchorPoint::CENTER ); + Stage::GetCurrent().Add( meshActor ); + + application.SendNotification(); + application.Render(16); + DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) ); + END_TEST; +} + +int UtcFrustumLeftCullP(void) +{ + TestApplication application; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ]; + BufferImage image = BufferImage::New( pixelBuffer, 1, 1 ); + + Geometry geometry = CreateGeometry(); + Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) ); + Sampler sampler = Sampler::New( image, "sTexture" ); + material.AddSampler( sampler ); + Renderer renderer = Renderer::New( geometry, material ); + + Actor meshActor = Actor::New(); + meshActor.AddRenderer( renderer ); + meshActor.SetSize(400, 400); + drawTrace.Reset(); + + meshActor.SetParentOrigin( Vector3( -0.42f, 0.5f, 0.5f ) ); + meshActor.SetAnchorPoint( AnchorPoint::CENTER ); + Stage::GetCurrent().Add( meshActor ); + + application.SendNotification(); + application.Render(16); + + // This will be box culled + DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) ); + + drawTrace.Reset(); + meshActor.SetParentOrigin( Vector3( -0.5f, 0.5f, 0.5f ) ); + application.SendNotification(); + application.Render(16); + + // This will be sphere culled + DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) ); + END_TEST; +} + +int UtcFrustumRightCullP(void) +{ + TestApplication application; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ]; + BufferImage image = BufferImage::New( pixelBuffer, 1, 1 ); + + Geometry geometry = CreateGeometry(); + Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) ); + Sampler sampler = Sampler::New( image, "sTexture" ); + material.AddSampler( sampler ); + Renderer renderer = Renderer::New( geometry, material ); + + Actor meshActor = Actor::New(); + meshActor.AddRenderer( renderer ); + meshActor.SetSize(400, 400); + drawTrace.Reset(); + + meshActor.SetParentOrigin( Vector3( 1.42f, 0.5f, 0.5f ) ); + meshActor.SetAnchorPoint( AnchorPoint::CENTER ); + Stage::GetCurrent().Add( meshActor ); + + application.SendNotification(); + application.Render(16); + + // This should be box culled + DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) ); + + drawTrace.Reset(); + meshActor.SetParentOrigin( Vector3( 1.5f, 0.0f, 0.5f ) ); + application.SendNotification(); + application.Render(16); + + // This should be sphere culled + DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) ); + END_TEST; +} + +int UtcFrustumTopCullP(void) +{ + TestApplication application; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ]; + BufferImage image = BufferImage::New( pixelBuffer, 1, 1 ); + + Geometry geometry = CreateGeometry(); + Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) ); + Sampler sampler = Sampler::New( image, "sTexture" ); + material.AddSampler( sampler ); + Renderer renderer = Renderer::New( geometry, material ); + + Actor meshActor = Actor::New(); + meshActor.AddRenderer( renderer ); + meshActor.SetSize(400, 400); + drawTrace.Reset(); + + meshActor.SetParentOrigin( Vector3( 0.5f, -0.32f, 0.5f ) ); + meshActor.SetAnchorPoint( AnchorPoint::CENTER ); + Stage::GetCurrent().Add( meshActor ); + + application.SendNotification(); + application.Render(16); + + // This should be box culled + DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) ); + + drawTrace.Reset(); + meshActor.SetParentOrigin( Vector3( 0.5f, -0.5f, 0.5f ) ); + application.SendNotification(); + application.Render(16); + + // This will be sphere culled + DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) ); + END_TEST; +} + +int UtcFrustumBottomCullP(void) +{ + TestApplication application; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ]; + BufferImage image = BufferImage::New( pixelBuffer, 1, 1 ); + + Geometry geometry = CreateGeometry(); + Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) ); + Sampler sampler = Sampler::New( image, "sTexture" ); + material.AddSampler( sampler ); + Renderer renderer = Renderer::New( geometry, material ); + + Actor meshActor = Actor::New(); + meshActor.AddRenderer( renderer ); + meshActor.SetSize(400, 400); + drawTrace.Reset(); + + meshActor.SetParentOrigin( Vector3( 0.5f, 1.32f, 0.5f ) ); + meshActor.SetAnchorPoint( AnchorPoint::CENTER ); + Stage::GetCurrent().Add( meshActor ); + + application.SendNotification(); + application.Render(16); + + // This should be box culled + DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) ); + + drawTrace.Reset(); + meshActor.SetParentOrigin( Vector3( 0.5f, 1.5f, 0.5f ) ); + application.SendNotification(); + application.Render(16); + + // This will be sphere culled + DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) ); + END_TEST; +} + +int UtcFrustumNearCullP(void) +{ + TestApplication application; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ]; + BufferImage image = BufferImage::New( pixelBuffer, 1, 1 ); + + Geometry geometry = CreateGeometry(); + Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) ); + Sampler sampler = Sampler::New( image, "sTexture" ); + material.AddSampler( sampler ); + Renderer renderer = Renderer::New( geometry, material ); + + Actor meshActor = Actor::New(); + meshActor.AddRenderer( renderer ); + meshActor.SetSize(400, 400); + drawTrace.Reset(); + + meshActor.SetParentOrigin( Vector3( 0.5f, 0.5f, 7.0f ) ); + meshActor.SetAnchorPoint( AnchorPoint::CENTER ); + Stage::GetCurrent().Add( meshActor ); + + application.SendNotification(); + application.Render(16); + + // This will be sphere culled + DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) ); + END_TEST; +} + +int UtcFrustumFarCullP(void) +{ + TestApplication application; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ]; + BufferImage image = BufferImage::New( pixelBuffer, 1, 1 ); + + Geometry geometry = CreateGeometry(); + Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) ); + Sampler sampler = Sampler::New( image, "sTexture" ); + material.AddSampler( sampler ); + Renderer renderer = Renderer::New( geometry, material ); + + Actor meshActor = Actor::New(); + meshActor.AddRenderer( renderer ); + meshActor.SetSize(400, 400); + drawTrace.Reset(); + + meshActor.SetParentOrigin( Vector3( 0.5f, 0.5f, -7.0f ) ); + meshActor.SetAnchorPoint( AnchorPoint::CENTER ); + Stage::GetCurrent().Add( meshActor ); + + application.SendNotification(); + application.Render(16); + + // This will be sphere culled + DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) ); + END_TEST; +} + +int UtcFrustumCullDisabledP(void) +{ + TestApplication application; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ]; + BufferImage image = BufferImage::New( pixelBuffer, 1, 1 ); + + Geometry geometry = CreateGeometry(); + Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER, Shader::HINT_MODIFIES_GEOMETRY ) ); + Sampler sampler = Sampler::New( image, "sTexture" ); + material.AddSampler( sampler ); + Renderer renderer = Renderer::New( geometry, material ); + + Actor meshActor = Actor::New(); + meshActor.AddRenderer( renderer ); + meshActor.SetSize(400, 400); + drawTrace.Reset(); + + meshActor.SetParentOrigin( Vector3( 0.5f, 0.5f, -7.0f ) ); + meshActor.SetAnchorPoint( AnchorPoint::CENTER ); + Stage::GetCurrent().Add( meshActor ); + + application.SendNotification(); + application.Render(16); + + // This should not be culled + DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) ); + END_TEST; +} diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-Handles.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-Handles.cpp new file mode 100644 index 0000000..9d26c45 --- /dev/null +++ b/automated-tests/src/dali-internal/utc-Dali-Internal-Handles.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include + +// Internal headers are allowed here + + +using namespace Dali; + +void utc_dali_internal_handles_startup() +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_internal_handles_cleanup() +{ + test_return_value = TET_PASS; +} + + +int UtcDaliCameraActorConstructorRefObject(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CameraActor::CameraActor(Internal::CameraActor*)"); + + CameraActor actor(NULL); + + DALI_TEST_CHECK(!actor); + END_TEST; +} + +int UtcDaliImageActorConstructorRefObject(void) +{ + TestApplication application; + tet_infoline("Testing Dali::ImageActor::ImageActor(Internal::ImageActor*)"); + + ImageActor actor(NULL); + + DALI_TEST_CHECK(!actor); + END_TEST; +} + +int UtcDaliTextActorConstructorRefObject(void) +{ + TestApplication application; + tet_infoline("Testing Dali::TextActor::TextActor(Internal::TextActor*)"); + ImageActor actor(NULL); + DALI_TEST_CHECK(!actor); + END_TEST; +} diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-Image-Culling.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-Image-Culling.cpp new file mode 100644 index 0000000..7297524 --- /dev/null +++ b/automated-tests/src/dali-internal/utc-Dali-Internal-Image-Culling.cpp @@ -0,0 +1,847 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include + +#include + +using namespace Dali; + +void utc_dali_internal_image_culling_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_internal_image_culling_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +namespace +{ +#define NUM_ROWS 9 +#define NUM_COLS 9 +#define NUM_ROWS_PER_PANE 3 +#define NUM_COLS_PER_PANE 3 +const unsigned int TEXTURE_ID_OFFSET = 23; + +Image LoadImage( TestApplication& application, GLuint textureId, int width, int height ) +{ + Image image; + char* filename = NULL; + int numChars = asprintf(&filename, "image%u.png", textureId ); + + if( numChars > 0 ) + { + const Vector2 closestImageSize( width, height ); + application.GetPlatform().SetClosestImageSize(closestImageSize); + + image = ResourceImage::New( filename, ResourceImage::IMMEDIATE, Image::NEVER ); + free (filename); + } + DALI_TEST_CHECK(image); + application.SendNotification(); + application.Render(16); + + std::vector ids; + ids.push_back( textureId ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD ); + Integration::ResourcePointer resource(bitmap); + bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, width, height, width, height); + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + Integration::ResourceRequest* request = application.GetPlatform().GetRequest(); + DALI_TEST_CHECK( request != NULL ); + if(request) + { + application.GetPlatform().SetResourceLoaded(request->GetId(), request->GetType()->id, resource); + } + application.SendNotification(); + application.Render(16); + application.GetPlatform().ClearReadyResources(); + application.GetPlatform().DiscardRequest(); + application.SendNotification(); + application.Render(16); + + return image; +} + +ImageActor CreateOnStageActor(TestApplication& application, Image image, int width, int height, bool testDraw) +{ + ImageActor imageActor = ImageActor::New(image); + Stage::GetCurrent().Add(imageActor); + + imageActor.SetParentOrigin(ParentOrigin::CENTER); + application.SendNotification(); + application.Render(16); + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + + if(testDraw) + { + DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) ); + DALI_TEST_CHECK( textureTrace.FindMethod( "BindTexture" ) ); + const std::vector& textures = glAbstraction.GetBoundTextures(GL_TEXTURE0); + DALI_TEST_CHECK( textures.size() > 0 ); + if( textures.size() > 0 ) + { + DALI_TEST_CHECK( textures[0] == 23 ); + } + } + return imageActor; +} + + +void TestImageInside( TestApplication& application, int width, int height ) +{ + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + textureTrace.Enable(true); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + Image image = LoadImage( application, 23, width, height ); + + ImageActor imageActor = CreateOnStageActor(application, image, width, height, true); + imageActor.SetPosition(0.0f, 0.0f, 0.0f); + + Vector3 imageSize = imageActor.GetCurrentSize(); + DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION); + + drawTrace.Reset(); + imageActor.SetParentOrigin(ParentOrigin::TOP_LEFT); + application.SendNotification(); + application.Render(16); + DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) ); + + drawTrace.Reset(); + imageActor.SetParentOrigin(ParentOrigin::TOP_RIGHT); + application.SendNotification(); + application.Render(16); + DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) ); + + drawTrace.Reset(); + imageActor.SetParentOrigin(ParentOrigin::BOTTOM_RIGHT); + application.SendNotification(); + application.Render(16); + DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) ); + + drawTrace.Reset(); + imageActor.SetParentOrigin(ParentOrigin::BOTTOM_LEFT); + application.SendNotification(); + application.Render(16); + DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) ); +} + + +bool RepositionActor(TestApplication& application, Actor actor, float x, float y, bool inside) +{ + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + + drawTrace.Reset(); + actor.SetPosition( x, y, 0.0f); + application.SendNotification(); + application.Render(16); + + bool found = drawTrace.FindMethod( "DrawArrays" ); + return (inside && found) || (!inside && !found); +} + + +void RepositionActorWithAngle(TestApplication& application, Actor actor, float x, float y, float angle, bool inside) +{ + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + + drawTrace.Reset(); + actor.SetPosition( x, y, 0.0f); + actor.SetOrientation( Degree(angle), Vector3::ZAXIS ); + application.SendNotification(); + application.Render(16); + if( inside ) + { + bool found = drawTrace.FindMethod( "DrawArrays" ); + if( ! found ) tet_printf( "Not drawn: Position:(%3.0f, %3.0f)\n", x, y ); + DALI_TEST_CHECK( found ); + } + else + { + bool found = drawTrace.FindMethod( "DrawArrays" ); + if( found ) tet_printf( "Drawn when not needed: Position:(%3.0f, %3.0f)\n", x, y ); + DALI_TEST_CHECK( ! found ); + } +} + +void RepositionActorOutside(TestApplication& application, Actor actor, float x, float y, bool drawn ) +{ + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + + drawTrace.Reset(); + actor.SetPosition( x, y, 0.0f); + application.SendNotification(); + application.Render(16); + if( drawn ) + { + bool found = drawTrace.FindMethod( "DrawArrays" ); + if( ! found ) tet_printf( "Not drawn: Position:(%3.0f, %3.0f)\n", x, y ); + DALI_TEST_CHECK( found ); + } + else + { + bool found = drawTrace.FindMethod( "DrawArrays" ); + if( found ) tet_printf( "Drawn unnecessarily: Position:(%3.0f, %3.0f)\n", x, y ); + DALI_TEST_CHECK( ! found ); + } + +} + +void SphereTestImageAtBoundary( TestApplication& application, int width, int height ) +{ + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + textureTrace.Enable(true); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + Vector2 stageSize = Stage::GetCurrent().GetSize(); + + Image image = LoadImage(application, 23, width, height); + ImageActor imageActor = CreateOnStageActor(application, image, width, height, true); + + Vector3 imageSize = imageActor.GetCurrentSize(); + DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION); + + imageSize.z = 0.0f; + float radius = imageSize.Length() * 0.5f; // Radius of bounding box + tet_printf("Testing Stage Size: (%3.0f, %3.0f) image size:(%3.0f, %3.0f) := radius=%3.0f\n", + stageSize.x, stageSize.y, imageSize.x, imageSize.y, radius); + + for( int i=0; i<=radius; i++ ) + { + float x1 = -stageSize.x/2.0f - i; + float x2 = stageSize.x/2.0f + i; + float y1 = -stageSize.y/2.0f - i; + float y2 = stageSize.y/2.0f + i; + + //tet_printf("Testing i=%d\n",i); + + // Test paths marked with dots + // + . . . . . . + // .\_ ^ + // . \_ | within radius + // . \ v + // . +----- + // . | Stage + + for( int j=-10; j<=10; j++ ) + { + float x = ((stageSize.x+2*radius)/21.0f) * j; + float y = ((stageSize.y+2*radius)/21.0f) * j; + + RepositionActor( application, imageActor, x1, y, true ); + RepositionActor( application, imageActor, x2, y, true ); + RepositionActor( application, imageActor, x, y1, true ); + RepositionActor( application, imageActor, x, y2, true ); + } + } +} + +void OBBTestImageAtBoundary( TestApplication& application, int width, int height ) +{ + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + textureTrace.Enable(true); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + Vector2 stageSize = Stage::GetCurrent().GetSize(); + + Image image = LoadImage(application, 23, width, height); + ImageActor imageActor = CreateOnStageActor(application, image, width, height, true); + + Vector3 imageSize = imageActor.GetCurrentSize(); + DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION); + + imageSize.z = 0.0f; + tet_printf("Testing Stage Size: (%3.0f, %3.0f) image size:(%3.0f, %3.0f) \n", + stageSize.x, stageSize.y, imageSize.x, imageSize.y); + + int successCount = 0; + int totalCount = 0; + for( int i=0; i<100; i++ ) + { + float x1 = -stageSize.x/2.0f - imageSize.x*i/200.0f; + float x2 = stageSize.x/2.0f + imageSize.x*i/200.0f; + float y1 = -stageSize.y/2.0f - imageSize.y*i/200.0f; + float y2 = stageSize.y/2.0f + imageSize.y*i/200.0f; + + //tet_printf("Testing i=%d\n",i); + + // Test paths marked with dots + // + . . . . . . + // .\_ ^ + // . \_ | within radius + // . \ v + // . +----- + // . | Stage + + for( int j=-10; j<=10; j++ ) + { + float x = ((stageSize.x+imageSize.x/2.0f)/21.0f) * j; + float y = ((stageSize.y+imageSize.y/2.0f)/21.0f) * j; + + if(RepositionActor( application, imageActor, x1, y, true )) successCount++; + if(RepositionActor( application, imageActor, x2, y, true )) successCount++; + if(RepositionActor( application, imageActor, x, y1, true )) successCount++; + if(RepositionActor( application, imageActor, x, y2, true )) successCount++; + + totalCount += 4; + } + } + DALI_TEST_EQUALS(successCount, totalCount, TEST_LOCATION); + tet_printf( "Test succeeded with %d passes out of %d tests\n", successCount, totalCount); +} + + +void SphereTestImageOutsideBoundary( TestApplication& application, int width, int height ) +{ + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + textureTrace.Enable(true); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + Vector2 stageSize = Stage::GetCurrent().GetSize(); + + Image image = LoadImage( application, 23, width, height ); + + ImageActor imageActor = CreateOnStageActor(application, image, width, height, true); + Vector3 imageSize = imageActor.GetCurrentSize(); + DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION); + + imageSize.z = 0.0f; + float radius = imageSize.Length() * 0.5f; // Radius of bounding box + tet_printf("Testing Stage Size: (%3.0f, %3.0f) image size:(%3.0f, %3.0f) := radius=%3.0f\n", + stageSize.x, stageSize.y, imageSize.x, imageSize.y, radius); + + for( int i=0; i<100; i++ ) + { + // Try from 3 times + float x1 = -stageSize.x/2.0f - imageSize.x*i/200.0f; + float x2 = stageSize.x/2.0f + imageSize.x*i/200.0f; + float y1 = -stageSize.y/2.0f - imageSize.y*i/200.0f; + float y2 = stageSize.y/2.0f + imageSize.y*i/200.0f; + + + //tet_printf("Testing i=%d\n",i); + for( int j=-10; j<=10; j++ ) + { + float x = (stageSize.x/17.0f) * j; // use larger intervals to test more area + float y = (stageSize.y/17.0f) * j; + + RepositionActor( application, imageActor, x1, y, false ); + RepositionActor( application, imageActor, x2, y, false ); + RepositionActor( application, imageActor, x, y1, false ); + RepositionActor( application, imageActor, x, y2, false ); + } + } +} + +void OBBTestImageOutsideBoundary( TestApplication& application, int width, int height ) +{ + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + textureTrace.Enable(true); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + Vector2 stageSize = Stage::GetCurrent().GetSize(); + + Image image = LoadImage( application, 23, width, height ); + + ImageActor imageActor = CreateOnStageActor(application, image, width, height, true); + Vector3 imageSize = imageActor.GetCurrentSize(); + DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION); + + imageSize.z = 0.0f; + tet_printf("Testing Stage Size: (%3.0f, %3.0f) image size:(%3.0f, %3.0f)\n", + stageSize.x, stageSize.y, imageSize.x, imageSize.y); + + int successCount=0; + int totalCount=0; + + for( int i=0; i<=100; i++ ) + { + float x1 = -stageSize.x/2.0f - imageSize.x * (1.5f + i/100.0f); + float x2 = stageSize.x/2.0f + imageSize.x * (1.5f + i/100.0f); + float y1 = -stageSize.y/2.0f - imageSize.y * (1.5f + i/100.0f); + float y2 = stageSize.y/2.0f + imageSize.y * (1.5f + i/100.0f); + + for( int j=-10; j<=10; j++ ) + { + float x = (stageSize.x/17.0f) * j; // use larger intervals to test more area + float y = (stageSize.y/17.0f) * j; + + if(RepositionActor( application, imageActor, x1, y, false )) successCount++; + if(RepositionActor( application, imageActor, x2, y, false )) successCount++; + if(RepositionActor( application, imageActor, x, y1, false )) successCount++; + if(RepositionActor( application, imageActor, x, y2, false )) successCount++; + totalCount+=4; + } + } + DALI_TEST_EQUALS(successCount, totalCount, TEST_LOCATION); + tet_printf( "Test succeeded with %d passes out of %d tests\n", successCount, totalCount); +} + +void TestPlaneOfImages(TestApplication& application, float z) +{ + Vector2 stageSize = Stage::GetCurrent().GetSize(); + Vector2 imageSize = stageSize/3.0f; + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + + // Create a grid of 9 x 9 actors; only the central 3x3 are in viewport + + std::vector< Actor > actors; + for( int i = 0; i < NUM_ROWS*NUM_COLS; i++ ) + { + GLuint textureId = TEXTURE_ID_OFFSET+i; + Image image = LoadImage( application, textureId, imageSize.x, imageSize.y ); + ImageActor imageActor = CreateOnStageActor(application, image, imageSize.x, imageSize.y, false ); + actors.push_back(imageActor); + } + application.SendNotification(); + application.Render(16); + + drawTrace.Reset(); + textureTrace.Reset(); + drawTrace.Enable(true); + textureTrace.Enable(true); + application.GetGlAbstraction().ClearBoundTextures(); + + for( int row=0; row number of panes + // 3 per pane, splits into -1/3, 0, +1/3 + // number of lh planes * number of cols per plane + // Center column maps to zero, index of center column = num_cols / 2 rounded down + // index - that and divide by number of cols per pane. + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + float xOffset = (int)(col - (NUM_COLS/2)); + float yOffset = (int)(row - (NUM_ROWS/2)); + float x = stageSize.x*xOffset / (float)(NUM_COLS_PER_PANE); + float y = stageSize.y*yOffset / (float)(NUM_ROWS_PER_PANE); + actors[row*NUM_COLS+col].SetPosition( x, y, z ); + } + } + + application.SendNotification(); + application.Render(16); + + DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) ); + + typedef std::vector TexVec; + const TexVec& textures = glAbstraction.GetBoundTextures(GL_TEXTURE0); + DALI_TEST_CHECK( textures.size() >= NUM_ROWS_PER_PANE * NUM_COLS_PER_PANE ); + if( textures.size() > 0 ) + { + int foundCount=0; + int expectedCount = 0; + for(unsigned int row=0; row= NUM_ROWS_PER_PANE * NUM_COLS_PER_PANE ); + + tet_printf("Number of bound textures: %u\n", textures.size()); + tet_printf("Number of draw calls: %d\n", numDrawCalls); +} + +} // namespace + +int UtcDaliImageCulling_Inside01(void) +{ + tet_infoline( "Testing that 80x80 image positioned inside the stage is drawn\n"); + + TestApplication application; + + TestImageInside(application, 80, 80); + + END_TEST; +} + +int UtcDaliImageCulling_Inside02(void) +{ + tet_infoline( "Testing that 120x40 image positioned inside the stage is drawn\n"); + + TestApplication application; + + TestImageInside(application, 120, 40); + + END_TEST; +} + +int UtcDaliImageCulling_Inside03(void) +{ + tet_infoline( "Testing that 40x120 image positioned inside the stage is drawn\n"); + + TestApplication application; + + TestImageInside(application, 40, 120); + + END_TEST; +} + +int UtcDaliImageCulling_Inside04(void) +{ + tet_infoline( "Testing that 500x2 image positioned inside the stage is drawn\n"); + TestApplication application; + TestImageInside(application, 500, 2); + END_TEST; +} + +int UtcDaliImageCulling_Inside05(void) +{ + tet_infoline( "Testing that 2x500 image positioned inside the stage is drawn\n"); + TestApplication application; + TestImageInside(application, 2, 500); + END_TEST; +} + + +int UtcDaliImageCulling_WithinBoundary01(void) +{ + tet_infoline("Test that 80x80 image positioned outside the stage but with bounding box intersecting the stage is drawn\n"); + + TestApplication application; + OBBTestImageAtBoundary( application, 80, 80); + END_TEST; +} +int UtcDaliImageCulling_WithinBoundary02(void) +{ + tet_infoline("Test that 120x40 image positioned outside the stage but with bounding box intersecting the stage is drawn\n"); + + TestApplication application; + OBBTestImageAtBoundary( application, 120, 40 ); + END_TEST; +} +int UtcDaliImageCulling_WithinBoundary03(void) +{ + tet_infoline("Test that 40x120 image positioned outside the stage but with bounding box intersecting the stage is drawn\n"); + + TestApplication application; + OBBTestImageAtBoundary( application, 40, 120); + END_TEST; +} + +int UtcDaliImageCulling_WithinBoundary04(void) +{ + tet_infoline("Test that 500x2 images positioned outside the stage but with bounding box intersecting the stage is drawn\n"); + + TestApplication application; + OBBTestImageAtBoundary( application, 500, 2 ); + END_TEST; +} + +int UtcDaliImageCulling_WithinBoundary05(void) +{ + tet_infoline("Test that 2x500 images positioned outside the stage but with bounding box intersecting the stage is drawn\n"); + + TestApplication application; + OBBTestImageAtBoundary( application, 2, 500 ); + END_TEST; +} + +int UtcDaliImageCulling_OutsideBoundary01(void) +{ + tet_infoline("Test that 80x80 image positioned outside the stage by more than 2 times\n" + "the radius of the bounding circle is not drawn\n"); + + TestApplication application; + OBBTestImageOutsideBoundary( application, 80, 80 ); + END_TEST; +} + +int UtcDaliImageCulling_OutsideBoundary02(void) +{ + tet_infoline("Test that 120x40 image positioned outside the stage by more than 2 times\n" + "the radius of the bounding circle is not drawn\n"); + + TestApplication application; + OBBTestImageOutsideBoundary( application, 120, 40 ); + END_TEST; +} +int UtcDaliImageCulling_OutsideBoundary03(void) +{ + tet_infoline("Test that 40x120 image positioned outside the stage by more than 2 times\n" + "the radius of the bounding circle is not drawn\n"); + + TestApplication application; + OBBTestImageOutsideBoundary( application, 40, 120 ); + END_TEST; +} + +int UtcDaliImageCulling_OutsideBoundary04(void) +{ + tet_infoline("Test that 500x2 image positioned outside the stage by more than 2 times\n" + "the radius of the bounding circle is not drawn\n"); + + TestApplication application; + OBBTestImageOutsideBoundary( application, 500, 2 ); + END_TEST; +} + +int UtcDaliImageCulling_OutsideBoundary05(void) +{ + tet_infoline("Test that 2x500 image positioned outside the stage by more than 2 times\n" + "the radius of the bounding circle is not drawn\n"); + + TestApplication application; + OBBTestImageOutsideBoundary( application, 2, 500 ); + END_TEST; +} + +int UtcDaliImageCulling_OutsideIntersect01(void) +{ + TestApplication application; + + tet_infoline("Test that actors positioned outside the stage with bounding boxes also\n" + "outside the stage but intersecting it are still drawn"); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + textureTrace.Enable(true); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + Vector2 stageSize = Stage::GetCurrent().GetSize(); + + float width = stageSize.x*5.0f; + float height = stageSize.y*0.2f; + Image image = LoadImage( application, 23, width, height); + ImageActor imageActor = CreateOnStageActor(application, image, width, height, true); + + RepositionActor( application, imageActor, stageSize.x*1.2f, 0.0f, true); + RepositionActor( application, imageActor, stageSize.x*1.2f, -stageSize.y*0.55f, true); + RepositionActor( application, imageActor, stageSize.x*1.2f, stageSize.y*0.55f, true); + END_TEST; +} + +int UtcDaliImageCulling_OutsideIntersect02(void) +{ + TestApplication application; + + tet_infoline("Test that actors positioned outside the stage with bounding boxes also\n" + "outside the stage that cross planes are not drawn"); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + textureTrace.Enable(true); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + Vector2 stageSize = Stage::GetCurrent().GetSize(); + + float width = stageSize.x*5.0f; + float height = stageSize.y*0.2f; + Image image = LoadImage( application, 23, width, height); + ImageActor imageActor = CreateOnStageActor(application, image, width, height, true); + + RepositionActor( application, imageActor, stageSize.x*10.0f, stageSize.y*0.5f, false); + RepositionActor( application, imageActor, -stageSize.x*10.0f, stageSize.y*0.5f, false); + RepositionActor( application, imageActor, stageSize.x*10.0f, -stageSize.y*0.5f, false); + RepositionActor( application, imageActor, -stageSize.x*10.0f, -stageSize.y*0.5f, false); + END_TEST; +} + +int UtcDaliImageCulling_OutsideIntersect03(void) +{ + TestApplication application; + + tet_infoline("Test that image actor larger than the stage, positioned outside the stage \n" + "with bounding boxes also outside the stage but intersecting it is still drawn\n"); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + textureTrace.Enable(true); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + Vector2 stageSize = Stage::GetCurrent().GetSize(); + + // Try an actor bigger than the stage, with center outside stage + float width = stageSize.x*5.0f; + float height = stageSize.y*5.0f; + Image image = LoadImage( application, 23, width, height); + ImageActor imageActor = CreateOnStageActor(application, image, width, height, true); + + RepositionActor( application, imageActor, stageSize.x*1.2f, 0.0f, true); + RepositionActor( application, imageActor, stageSize.x*1.2f, -stageSize.y*1.1f, true); + RepositionActor( application, imageActor, stageSize.x*1.2f, stageSize.y*1.1f, true); + + END_TEST; +} + +int UtcDaliImageCulling_OutsideIntersect04(void) +{ + TestApplication application; + + tet_infoline("Test that image actors positioned outside the stage, with bounding boxes\n" + "also outside the stage but intersecting it, and angled at 45 degrees to\n" + "the corners are still drawn\n"); + + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + textureTrace.Enable(true); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + Vector2 stageSize = Stage::GetCurrent().GetSize(); + + // Test image at 45 degrees outside corners of stage + float width = 400.0f; + float height = 200.0f; + Image image = LoadImage( application, 23, width, height); + ImageActor imageActor = CreateOnStageActor(application, image, width, height, true); + + RepositionActorWithAngle( application, imageActor, -stageSize.x*0.55f, -stageSize.y*0.55, 135.0f, true); + RepositionActorWithAngle( application, imageActor, -stageSize.x*0.55f, stageSize.y*0.55, 225.0f, true); + RepositionActorWithAngle( application, imageActor, stageSize.x*0.55f, -stageSize.y*0.55, 45.0f, true); + RepositionActorWithAngle( application, imageActor, stageSize.x*0.55f, stageSize.y*0.55, 315.0f, true); + + END_TEST; +} + +int UtcDaliImageCulling_Plane01(void) +{ + tet_infoline("Test that a set of image actors with different images are drawn appropriately"); + + TestApplication application; + + TestPlaneOfImages(application, 0.0f); + END_TEST; +} + +int UtcDaliImageCulling_Plane02(void) +{ + tet_infoline("Test that a set of image actors with different images are drawn appropriately"); + + TestApplication application; + + TestPlaneOfImages(application, 100.0f); + END_TEST; +} + +int UtcDaliImageCulling_Plane03(void) +{ + tet_infoline("Test that a set of image actors with different images are drawn appropriately"); + + TestApplication application; + + TestPlaneOfImages(application, -100.0f); + END_TEST; +} + +int UtcDaliImageCulling_Plane04(void) +{ + tet_infoline("Test that a set of image actors with different images are drawn appropriately"); + + TestApplication application; + + TestPlaneOfImages(application, -200.0f); + END_TEST; +} + +int UtcDaliImageCulling_Disable(void) +{ + tet_infoline("Test that culling can be disabled"); + + TestApplication application; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + textureTrace.Enable(true); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + drawTrace.Enable(true); + + Vector2 stageSize = Stage::GetCurrent().GetSize(); + float width=80; + float height=80; + Image image = LoadImage( application, 23, width, height ); + + ImageActor imageActor = CreateOnStageActor(application, image, width, height, true); + Vector3 imageSize = imageActor.GetCurrentSize(); + DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION); + + imageSize.z = 0.0f; + + tet_infoline("Setting cull mode to false\n"); + Stage::GetCurrent().GetRenderTaskList().GetTask(0).SetCullMode(false); + + float x1 = -stageSize.x - imageSize.x; + float x2 = stageSize.x + imageSize.x; + float y1 = -stageSize.y - imageSize.y; + float y2 = stageSize.y + imageSize.y; + + // Positioning actors outside stage, with no culling, they should still be drawn. + RepositionActorOutside( application, imageActor, x1, y1, true ); + RepositionActorOutside( application, imageActor, x2, y1, true ); + RepositionActorOutside( application, imageActor, x1, y2, true ); + RepositionActorOutside( application, imageActor, x2, y2, true ); + + tet_infoline("Setting cull mode to true\n"); + Stage::GetCurrent().GetRenderTaskList().GetTask(0).SetCullMode(true); + + RepositionActorOutside( application, imageActor, x1, y1, false ); + RepositionActorOutside( application, imageActor, x2, y1, false ); + RepositionActorOutside( application, imageActor, x1, y2, false ); + RepositionActorOutside( application, imageActor, x2, y2, false ); + + END_TEST; +} diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-ImageFactory.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-ImageFactory.cpp new file mode 100644 index 0000000..d0e63ad --- /dev/null +++ b/automated-tests/src/dali-internal/utc-Dali-Internal-ImageFactory.cpp @@ -0,0 +1,621 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +// Internal headers are allowed here +#include +#include +#include +#include + +using namespace Dali; + +using Internal::ResourceTicketPtr; +using Internal::ImageFactory; +using Internal::ImageFactoryCache::RequestPtr; +using Internal::ImageAttributes; + +namespace +{ + +static const char* gTestImageFilename = "icon_wrt.png"; + +static void EmulateImageLoaded( TestApplication& application, unsigned int width, unsigned int height ) +{ + // emulate load success + Integration::ResourceRequest* request = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD ); + Integration::ResourcePointer resource( bitmap ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, width, height, width, height ); + if( request ) + { + application.GetPlatform().SetResourceLoaded( request->GetId(), request->GetType()->id, resource ); + } + + application.SendNotification(); + application.Render(); + + application.SendNotification(); + application.Render(); +} + +} //anonymous namespace + + +// High-level test for image factory request cache +int UtcDaliImageFactoryUseCachedRequest01(void) +{ + TestApplication application; + + tet_infoline( "UtcDaliImageFactoryCachedRequest01 - Request same image more than once" ); + + Image image = ResourceImage::New( gTestImageFilename ); + + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + application.GetPlatform().ResetTrace(); + + Image image2 = ResourceImage::New( gTestImageFilename ); + + application.SendNotification(); + application.Render(); + + // check resource is not loaded twice + DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + application.GetPlatform().ResetTrace(); + + Image image3 = ResourceImage::New( gTestImageFilename ); + + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + END_TEST; +} + +// High-level test for image factory request cache +int UtcDaliImageFactoryUseCachedRequest02(void) +{ + TestApplication application; + + // testing resource deletion when taken off stage + tet_infoline( "UtcDaliImageFactoryCachedRequest02 - Discard previously requested resource" ); + + Image image = ResourceImage::New( gTestImageFilename, ResourceImage::IMMEDIATE, Image::UNUSED ); + ImageActor actor = ImageActor::New( image ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + application.GetPlatform().ResetTrace(); + + // Add actor to stage + Stage::GetCurrent().Add( actor ); + + application.Render(); + application.SendNotification(); + application.Render(); + application.SendNotification(); + + // Release the resource, request is still cached + Stage::GetCurrent().Remove( actor ); + application.Render(); + application.SendNotification(); + application.Render(); + application.SendNotification(); + + // Should find stale request in cache, so load image from filesystem + Image image2 = ResourceImage::New( gTestImageFilename ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + application.GetPlatform().ResetTrace(); + + // Resource is reloaded + Image image3 = ResourceImage::New( gTestImageFilename ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + END_TEST; +} + +// Low-level test for image factory request cache +int UtcDaliImageFactoryUseCachedRequest03(void) +{ + TestApplication application; + tet_infoline( "UtcDaliImageFactoryCachedRequest03 - Request same image more than once - Request Ids" ); + + ImageFactory& imageFactory = Internal::ThreadLocalStorage::Get().GetImageFactory(); + + RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL ); + ResourceTicketPtr ticket = imageFactory.Load( *req.Get() ); + + RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, NULL ); + ResourceTicketPtr ticket2 = imageFactory.Load( *req2.Get() ); + DALI_TEST_EQUALS( req, req2, TEST_LOCATION ); + DALI_TEST_EQUALS( ticket, ticket2, TEST_LOCATION ); + + req2 = imageFactory.RegisterRequest( gTestImageFilename, NULL ); + ResourceTicketPtr ticket3 = imageFactory.Load( *req2.Get() ); + DALI_TEST_EQUALS( req, req2, TEST_LOCATION ); + DALI_TEST_EQUALS( ticket, ticket3, TEST_LOCATION ); + + // request differs in scaled size - not default size + ImageAttributes attr = ImageAttributes::New( 80, 160); + req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr ); + ResourceTicketPtr ticket4 = imageFactory.Load( *req2.Get() ); + DALI_TEST_CHECK( req != req2 ); + END_TEST; +} + +// Low-level test for image factory request cache +int UtcDaliImageFactoryUseCachedRequest04(void) +{ + TestApplication application; + tet_infoline( "UtcDaliImageFactoryCachedRequest04 - Request same image with different Image objects - Request Ids" ); + + ImageFactory& imageFactory = Internal::ThreadLocalStorage::Get().GetImageFactory(); + + ImageAttributes attr = ImageAttributes::New( 80, 160 ); + RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, &attr ); + + ImageAttributes attr2 = ImageAttributes::New( 80, 160 ); + RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr2 ); + DALI_TEST_EQUALS( req, req2, TEST_LOCATION ); + END_TEST; +} + +// Different requests, compatible resource +int UtcDaliImageFactoryCompatibleResource01(void) +{ + TestApplication application; + tet_infoline( "UtcDaliImageFactoryCompatibleResource01 - Two requests mapping to same resource" ); + + ImageFactory& imageFactory = Internal::ThreadLocalStorage::Get().GetImageFactory(); + + Vector2 testSize(80.0f, 80.0f); + application.GetPlatform().SetClosestImageSize(testSize); + + // request with default attributes ( size is 0,0 ) + RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL ); + ResourceTicketPtr ticket = imageFactory.Load( *req.Get() ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + // emulate load success + EmulateImageLoaded( application, 80, 80 ); + + // Request a second load using exact-match image size: + ImageAttributes attr = ImageAttributes::New(); + attr.SetSize( 80, 80 ); + RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr ); + ResourceTicketPtr ticket2 = imageFactory.Load( *req2.Get() ); + + DALI_TEST_CHECK( req != req2 ); // different requests + DALI_TEST_EQUALS( ticket->GetId(), ticket2->GetId(), TEST_LOCATION ); // same resource + END_TEST; +} + +// Different requests, compatible resource +int UtcDaliImageFactoryCompatibleResource02(void) +{ + TestApplication application; + tet_infoline( "UtcDaliImageFactoryCompatibleResource02 - Two requests mapping to same resource." ); + + ImageFactory& imageFactory = Internal::ThreadLocalStorage::Get().GetImageFactory(); + + Vector2 testSize( 2048.0f, 2048.0f ); + application.GetPlatform().SetClosestImageSize( testSize ); + + // request with default attributes ( size is 0,0 ) + RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL ); + ResourceTicketPtr ticket = imageFactory.Load( *req.Get() ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + // emulate load success + EmulateImageLoaded( application, testSize.x, testSize.y ); + + // Request slightly bigger size than actual image. + // This will load the same resource as the ImageFactory cache uses a small fudge factor in matching. + // See UtcDaliImageFactoryReload06 + ImageAttributes attr = ImageAttributes::New(); + attr.SetSize( testSize.x + 1, testSize.y + 1 ); + RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr ); + ResourceTicketPtr ticket2 = imageFactory.Load( *req2.Get() ); + + DALI_TEST_CHECK( req != req2 ); // different requests + DALI_TEST_EQUALS( ticket->GetId(), ticket2->GetId(), TEST_LOCATION ); // same resource + END_TEST; +} + +// Different requests, incompatible resource, so two loads result: +int UtcDaliImageFactoryInCompatibleResource(void) +{ + TestApplication application; + tet_infoline( "UtcDaliImageFactoryCompatibleResource02 - Two requests mapping to same resource." ); + + ImageFactory& imageFactory = Internal::ThreadLocalStorage::Get().GetImageFactory(); + + Vector2 testSize(2048.0f, 2048.0f); + application.GetPlatform().SetClosestImageSize(testSize); + + // request with default attributes ( size is 0,0 ) + RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL ); + ResourceTicketPtr ticket = imageFactory.Load( *req.Get() ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + // emulate load success + EmulateImageLoaded( application, testSize.x, testSize.y ); + + // Request substantially different size than actual image. + // This will issue a second resource load as difference in sizes is greater than + // the small fudge factor used in the ImageFactory cache. + ImageAttributes attr = ImageAttributes::New(); + attr.SetSize( testSize.x - 16, testSize.y - 16 ); + RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr ); + ResourceTicketPtr ticket2 = imageFactory.Load( *req2.Get() ); + + DALI_TEST_CHECK( req != req2 ); // different requests + DALI_TEST_CHECK( ticket->GetId() != ticket2->GetId() ); // differnet resources + END_TEST; +} + +// Different requests, compatible resource +int UtcDaliImageFactoryCompatibleResource03(void) +{ + TestApplication application; + tet_infoline( "UtcDaliImageFactoryCompatibleResource03 - Two requests mapping to same resource" ); + + ImageFactory& imageFactory = Internal::ThreadLocalStorage::Get().GetImageFactory(); + + Vector2 testSize(80.0f, 80.0f); + application.GetPlatform().SetClosestImageSize(testSize); + + // this time use defined attributes, nut just NULL + ImageAttributes attr = ImageAttributes::New(); + attr.SetSize( 120, 120 ); + + // request with default attributes ( size is 0,0 ) + RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, &attr ); + ResourceTicketPtr ticket = imageFactory.Load( *req.Get() ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + // emulate load success + EmulateImageLoaded( application, 80, 80 ); + + ImageAttributes attr2 = ImageAttributes::New(); + attr2.SetSize( 80, 80 ); + RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr2 ); + ResourceTicketPtr ticket2 = imageFactory.Load( *req2.Get() ); + + DALI_TEST_CHECK( req != req2 ); // different requests + DALI_TEST_EQUALS( ticket->GetId(), ticket2->GetId(), TEST_LOCATION ); // same resource + END_TEST; +} + +// Test for reloading image +int UtcDaliImageFactoryReload01(void) +{ + TestApplication application; + tet_infoline( "UtcDaliImageFactoryReload01 - Reload unchanged image" ); + + Vector2 testSize(80.0f, 80.0f); + application.GetPlatform().SetClosestImageSize(testSize); + + ImageFactory& imageFactory = Internal::ThreadLocalStorage::Get().GetImageFactory(); + + RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL ); + ResourceTicketPtr ticket = imageFactory.Load( *req.Get() ); + + ResourceTicketPtr ticket2 = imageFactory.Reload( *req.Get() ); + DALI_TEST_EQUALS( ticket, ticket2, TEST_LOCATION ); + + ResourceTicketPtr ticket3 = imageFactory.Reload( *req.Get() ); + DALI_TEST_EQUALS( ticket, ticket3, TEST_LOCATION ); + END_TEST; +} + +// Testing file system access when reloading image +int UtcDaliImageFactoryReload02(void) +{ + TestApplication application; + tet_infoline( "UtcDaliImageFactoryReload02 - Reload unchanged image" ); + + ImageFactory& imageFactory = Internal::ThreadLocalStorage::Get().GetImageFactory(); + + Vector2 testSize(80.0f, 80.0f); + application.GetPlatform().SetClosestImageSize(testSize); + + RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL ); + ResourceTicketPtr ticket = imageFactory.Load( *req.Get() ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + application.GetPlatform().ResetTrace(); + + ResourceTicketPtr ticket2 = imageFactory.Reload( *req.Get() ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( ticket, ticket2, TEST_LOCATION ); + // resource is still loading, do not issue another request + DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + + // emulate load success + EmulateImageLoaded( application, 80, 80 ); + + ResourceTicketPtr ticket3 = imageFactory.Reload( *req.Get() ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( ticket, ticket3, TEST_LOCATION ); + DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + application.GetPlatform().ResetTrace(); + + ticket3 = imageFactory.Reload( *req.Get() ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + END_TEST; +} + +// Test for reloading changed image +int UtcDaliImageFactoryReload03(void) +{ + TestApplication application; + tet_infoline( "UtcDaliImageFactoryReload03 - Reload changed image" ); + + ImageFactory& imageFactory = Internal::ThreadLocalStorage::Get().GetImageFactory(); + + Vector2 testSize( 80.0f, 80.0f ); + application.GetPlatform().SetClosestImageSize( testSize ); + + RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL ); + ResourceTicketPtr ticket = imageFactory.Load( *req.Get() ); + + application.SendNotification(); + application.Render(); + + // emulate load success + EmulateImageLoaded( application, 80, 80 ); + + Vector2 newSize( 192.0f, 192.0f ); + application.GetPlatform().SetClosestImageSize( newSize ); + + // Image file changed size, new resource request should be issued + ResourceTicketPtr ticket2 = imageFactory.Reload( *req.Get() ); + DALI_TEST_CHECK( ticket != ticket2 ); + + ResourceTicketPtr ticket3 = imageFactory.Reload( *req.Get() ); + DALI_TEST_EQUALS( ticket2, ticket3, TEST_LOCATION ); + END_TEST; +} + +// Testing file system access when reloading image +int UtcDaliImageFactoryReload04(void) +{ + TestApplication application; + tet_infoline( "UtcDaliImageFactoryReload04 - Reload unchanged image" ); + + ImageFactory& imageFactory = Internal::ThreadLocalStorage::Get().GetImageFactory(); + + Vector2 testSize(80.0f, 80.0f); + application.GetPlatform().SetClosestImageSize(testSize); + + RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL ); + ResourceTicketPtr ticket = imageFactory.Load( *req.Get() ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + application.GetPlatform().ResetTrace(); + + ResourceTicketPtr ticket2 = imageFactory.Reload( *req.Get() ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( ticket, ticket2, TEST_LOCATION ); + // resource is still loading, do not issue another request + DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + + // emulate load success + EmulateImageLoaded( application, 80, 80 ); + + ResourceTicketPtr ticket3 = imageFactory.Reload( *req.Get() ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + // size didn't change, using same ticket + DALI_TEST_EQUALS( ticket, ticket3, TEST_LOCATION ); + DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + application.GetPlatform().ResetTrace(); + + // still loading + ticket3 = imageFactory.Reload( *req.Get() ); + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + END_TEST; +} + +// Testing OnDemand + Reload +// Reload should have no effect if OnDemand Image is not loaded yet, as stated in the API documentation +int UtcDaliImageFactoryReload05(void) +{ + TestApplication application; + + tet_infoline( "UtcDaliImageFactoryReload05 - Reload OnDemand image" ); + + ImageFactory& imageFactory = Internal::ThreadLocalStorage::Get().GetImageFactory(); + + Vector2 testSize(80.0f, 80.0f); + application.GetPlatform().SetClosestImageSize(testSize); + + RequestPtr req; + ImageAttributes attr = ImageAttributes::New(); + attr.SetSize( 80, 80 ); + + // this happens first when loading Image OnDemand + req = imageFactory.RegisterRequest( gTestImageFilename, &attr ); + + application.SendNotification(); + application.Render(); + + ResourceTicketPtr ticket = imageFactory.Reload( *req.Get() ); + + DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + DALI_TEST_CHECK( !ticket ); + + // this happens when Image is put on stage + ticket = imageFactory.Load( *req.Get() ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + DALI_TEST_CHECK( ticket ); + application.GetPlatform().ResetTrace(); + + ticket = imageFactory.Reload( *req.Get() ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + // still loading, no new request + DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + + // emulate load success + EmulateImageLoaded( application, 80, 80 ); + + ticket = imageFactory.Reload( *req.Get() ); + + application.SendNotification(); + application.Render(); + + application.SendNotification(); + application.Render(); + + + DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) ); + END_TEST; +} + +// Initally two different requests map to same resource. +// After overwriting the file, they load different image resources. +int UtcDaliImageFactoryReload06(void) +{ + TestApplication application; + tet_infoline( "UtcDaliImageFactoryReload06 - Two requests first mapping to same resource, then different resources." ); + + ImageFactory& imageFactory = Internal::ThreadLocalStorage::Get().GetImageFactory(); + + Vector2 testSize(2048.0f, 2048.0f); + application.GetPlatform().SetClosestImageSize( testSize ); + + // request with default attributes ( size is 0,0 ) + RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL ); + ResourceTicketPtr ticket = imageFactory.Load( *req.Get() ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + // emulate load success + EmulateImageLoaded( application, testSize.x, testSize.y ); + + // Request bigger size than actual image. + // This will load the same resource. + // However if image size changes later on to eg. 512*512 (file is overwritten), + // reissuing these two requests will load different resources. + ImageAttributes attr = ImageAttributes::New(); + attr.SetSize( testSize.x + 1, testSize.y + 1 ); + RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr ); + ResourceTicketPtr ticket2 = imageFactory.Load( *req2.Get() ); + + DALI_TEST_CHECK( req != req2 ); // different requests + DALI_TEST_EQUALS( ticket->GetId(), ticket2->GetId(), TEST_LOCATION ); // same resource + + Vector2 newSize(512.0f, 512.0f); + application.GetPlatform().SetClosestImageSize(newSize); + + // reload fixed size (192,192) request + ticket2 = imageFactory.Reload( *req2.Get() ); + + // emulate load success + // note: this is the only way to emulate what size is loaded by platform abstraction + EmulateImageLoaded( application, testSize.x + 1, testSize.y + 1 ); + + // reload default size request + ticket = imageFactory.Reload( *req.Get() ); + + DALI_TEST_CHECK( ticket->GetId() != ticket2->GetId() ); // different resources + END_TEST; +} diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-MemoryPoolObjectAllocator.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-MemoryPoolObjectAllocator.cpp new file mode 100644 index 0000000..e254b68 --- /dev/null +++ b/automated-tests/src/dali-internal/utc-Dali-Internal-MemoryPoolObjectAllocator.cpp @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +// Internal headers are allowed here + +#include + +using namespace Dali; + +void utc_dali_internal_memorypoolobjectallocator_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_internal_memorypoolobjectallocator_cleanup(void) +{ + test_return_value = TET_PASS; +} + +struct MemoryPoolObjectAllocatorTestObjectTracking +{ + int testObjectDestructed; + int testObjectMethod; + int testObjectDataAccess; + + MemoryPoolObjectAllocatorTestObjectTracking() + : testObjectDestructed( 0 ), + testObjectMethod( 0 ), + testObjectDataAccess( 0 ) + { + } +}; + +class MemoryPoolObjectAllocatorTestObject +{ +public: + + MemoryPoolObjectAllocatorTestObject() + : mData1( 0 ), + mData2( false ), + mTracking( NULL ) + { + } + + ~MemoryPoolObjectAllocatorTestObject() + { + if( mTracking ) + { + mTracking->testObjectDestructed++; + } + } + + void Method() + { + if( mTracking ) + { + mTracking->testObjectMethod++; + } + } + + void DataAccess() + { + mData1++; + mData2 = true; + + if( mTracking ) + { + mTracking->testObjectDataAccess++; + } + } + + void SetTracking( MemoryPoolObjectAllocatorTestObjectTracking* tracking ) + { + mTracking = tracking; + } + +private: + + int mData1; + bool mData2; + + MemoryPoolObjectAllocatorTestObjectTracking* mTracking; +}; + +int UtcDaliMemoryPoolObjectAllocatorObjectAllocation(void) +{ + + Internal::MemoryPoolObjectAllocator< MemoryPoolObjectAllocatorTestObject > allocator; + + // Allocate an object + MemoryPoolObjectAllocatorTestObject* testObject1 = allocator.Allocate(); + DALI_TEST_CHECK( testObject1 ); + + MemoryPoolObjectAllocatorTestObjectTracking tracking1; + testObject1->SetTracking( &tracking1 ); + + testObject1->Method(); + DALI_TEST_EQUALS( tracking1.testObjectMethod, 1, TEST_LOCATION ); + + testObject1->DataAccess(); + DALI_TEST_EQUALS( tracking1.testObjectDataAccess, 1, TEST_LOCATION ); + + allocator.Free( testObject1 ); + DALI_TEST_EQUALS( tracking1.testObjectDestructed, 1, TEST_LOCATION ); + + // Reset and allocate another object + allocator.ResetMemoryPool(); + + MemoryPoolObjectAllocatorTestObject* testObject2 = allocator.Allocate(); + DALI_TEST_CHECK( testObject2 ); + + MemoryPoolObjectAllocatorTestObjectTracking tracking2; + testObject2->SetTracking( &tracking2 ); + + testObject2->Method(); + DALI_TEST_EQUALS( tracking2.testObjectMethod, 1, TEST_LOCATION ); + + testObject2->DataAccess(); + DALI_TEST_EQUALS( tracking2.testObjectDataAccess, 1, TEST_LOCATION ); + + allocator.Free( testObject2 ); + DALI_TEST_EQUALS( tracking2.testObjectDestructed, 1, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMemoryPoolObjectAllocatorObjectRawAllocation(void) +{ + Internal::MemoryPoolObjectAllocator< MemoryPoolObjectAllocatorTestObject > allocator; + + MemoryPoolObjectAllocatorTestObject* testObject = new ( allocator.AllocateRaw() ) MemoryPoolObjectAllocatorTestObject(); + DALI_TEST_CHECK( testObject ); + + MemoryPoolObjectAllocatorTestObjectTracking tracking; + testObject->SetTracking( &tracking ); + + testObject->Method(); + DALI_TEST_EQUALS( tracking.testObjectMethod, 1, TEST_LOCATION ); + + testObject->DataAccess(); + DALI_TEST_EQUALS( tracking.testObjectDataAccess, 1, TEST_LOCATION ); + + allocator.Free( testObject ); + DALI_TEST_EQUALS( tracking.testObjectDestructed, 1, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliMemoryPoolObjectAllocatorObjectAllocationPOD(void) +{ + Internal::MemoryPoolObjectAllocator< bool > allocator; + + bool* testObject1 = allocator.Allocate(); + DALI_TEST_CHECK( testObject1 ); + + allocator.Free( testObject1 ); + + allocator.ResetMemoryPool(); + + bool* testObject2 = allocator.Allocate(); + DALI_TEST_CHECK( testObject2 ); + + allocator.Free( testObject2 ); + + END_TEST; +} diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-ResourceClient.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-ResourceClient.cpp new file mode 100644 index 0000000..71855fc --- /dev/null +++ b/automated-tests/src/dali-internal/utc-Dali-Internal-ResourceClient.cpp @@ -0,0 +1,1022 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include + +// Internal headers are allowed here +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; + +#include + +namespace +{ + +class TestTicketObserver : public Internal::ResourceTicketObserver +{ +public: + TestTicketObserver() + : mLoadingFailedCalled(0), mLoadingSucceededCalled(0), + mUploadedCount(0) + {} + + int LoadFailedCalled() { + tet_printf("TicketObserver: LoadingFailed() called %d times", mLoadingFailedCalled); + return mLoadingFailedCalled; + } + int LoadSucceededCalled() { + tet_printf("TicketObserver: LoadingSucceeded() called %d times", mLoadingSucceededCalled); + return mLoadingSucceededCalled; + } + int UploadCalled() { + tet_printf("TicketObserver: Uploaded() called %d times", mUploadedCount); + return mUploadedCount; + } + void Reset() { + mLoadingFailedCalled = 0; + mLoadingSucceededCalled = 0; + mUploadedCount = 0; + } + +public: // From ResourceTicketObserver + virtual void ResourceLoadingFailed(const Internal::ResourceTicket& ticket) {mLoadingFailedCalled++;} + virtual void ResourceLoadingSucceeded(const Internal::ResourceTicket& ticket) {mLoadingSucceededCalled++;} + virtual void ResourceUploaded(const Internal::ResourceTicket& ticket) {mUploadedCount++;} + +private: + int mLoadingFailedCalled; + int mLoadingSucceededCalled; + int mUploadedCount; +}; + +class TestTicketLifetimeObserver : public Internal::ResourceTicketLifetimeObserver +{ +public: + TestTicketLifetimeObserver() : resourceTicketDiscarded(false) {} + + virtual void ResourceTicketDiscarded( const Internal::ResourceTicket& ticket ) + { resourceTicketDiscarded = true; } + + void Reset() { resourceTicketDiscarded = false; } + bool resourceTicketDiscarded; +}; + +static TestTicketObserver testTicketObserver; +static TestTicketLifetimeObserver testTicketLifetimeObserver; + + +Internal::ImagePtr LoadImage(TestApplication& application, char* name) +{ + Internal::ResourceImagePtr image = Internal::ResourceImage::New( name, Internal::ImageAttributes::DEFAULT_ATTRIBUTES ); + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80,80,80,80 ); + Integration::ResourcePointer resourcePtr(bitmap); // reference it + application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr); + application.Render(); // Process LoadComplete + application.SendNotification(); // Process event messages + application.GetPlatform().DiscardRequest(); // Ensure load request is discarded + req=NULL; + application.GetPlatform().ResetTrace(); + return image; +} + + +Internal::ResourceTicketPtr CheckLoadBitmap(TestApplication& application, const char* name, int w, int h) +{ + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + Integration::BitmapResourceType bitmapRequest; + Internal::ResourceTicketPtr ticket = resourceClient.RequestResource( bitmapRequest, name ); + ticket->AddObserver(testTicketObserver); + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, w, h, w, h ); + Integration::ResourcePointer resourcePtr(bitmap); // reference it + application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr); + application.Render(); // Process LoadComplete + application.SendNotification(); // Process event messages + DALI_TEST_CHECK( ticket->GetLoadingState() == ResourceLoadingSucceeded ); + application.GetPlatform().DiscardRequest(); // Ensure load request is discarded + req=NULL; + application.GetPlatform().ResetTrace(); + + return ticket; +} + +} //anonymous namespace + + +void utc_dali_internal_resource_client_startup() +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_internal_resource_client_cleanup() +{ + test_return_value = TET_PASS; +} + +// Load a bitmap resource successfully, then discard it's ticket +int UtcDaliInternalRequestResourceBitmapRequests01(void) +{ + TestApplication application; // Reset all test adapter return codes + + tet_infoline("Testing bitmap requests"); + + Internal::ResourceManager& resourceManager = Internal::ThreadLocalStorage::Get().GetResourceManager(); + Integration::BitmapResourceType bitmapRequest; + Internal::ResourceId id(0); + + testTicketObserver.Reset(); + + { + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + /************************************************************ + * FUNCTION UNDER TEST + ***********************************************************/ + Internal::ResourceTicketPtr ticket = resourceClient.RequestResource( bitmapRequest, "image.png" ); + ticket->AddObserver(testTicketObserver); + + // Update thread will request the bitmap resource: + // Sets application.GetPlatform().mRequest + application.SendNotification(); // Run flush update queue + application.Render(1); // Process update messages + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) ); + + application.SendNotification(); // Send any event messages + DALI_TEST_CHECK( testTicketObserver.LoadFailedCalled() == 0 ); + DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 ); + DALI_TEST_CHECK( ticket->GetLoadingState() == ResourceLoading ); + + Internal::ImageTicketPtr imageTicket(dynamic_cast(ticket.Get())); + DALI_TEST_CHECK( imageTicket ); + DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION ); + + // Create a resource + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80, 80, 80, 80 ); + Integration::ResourcePointer resourcePtr(bitmap); // reference it + + // Set up platform abstraction to load it + id=req->GetId(); + application.GetPlatform().SetResourceLoaded( id, Integration::ResourceBitmap, resourcePtr ); + + DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(req->GetId()) ); + + // load the cache, which will immediately have the loaded resource + application.Render(0); + + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) ); + + DALI_TEST_CHECK( resourceManager.IsResourceLoaded(req->GetId()) ); + Internal::BitmapMetadata bitmapData = resourceManager.GetBitmapMetadata(req->GetId()); + DALI_TEST_CHECK( bitmapData.GetWidth() == 80 ); + DALI_TEST_CHECK( bitmapData.GetHeight() == 80 ); + + DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION ); + + // Trigger the event thread to process notify messages. Should then trigger the signals + // in the ticket observer + application.SendNotification(); + + DALI_TEST_CHECK( ticket->GetLoadingState() == ResourceLoadingSucceeded ); + DALI_TEST_EQUALS(testTicketObserver.LoadSucceededCalled(), 1, TEST_LOCATION ); + + // Check that the image ticket was updated with the image attributes + DALI_TEST_EQUALS( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 80, TEST_LOCATION ); + } // Discard ticket + + application.SendNotification(); // Flush update queue (with ticket discarded message + application.Render(1); // Process update messages + application.SendNotification(); // Send event notifications + application.Render(1); // Process update messages + + // Resource should have been discarded. + DALI_TEST_CHECK( ! application.GetPlatform().WasCalled(TestPlatformAbstraction::CancelLoadFunc ) ); + DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id)); + + DALI_TEST_EQUALS(testTicketObserver.LoadSucceededCalled(), 1, TEST_LOCATION ); + DALI_TEST_EQUALS(testTicketObserver.LoadFailedCalled(), 0, TEST_LOCATION ); + END_TEST; +} + +// Starting Loading a bitmap resource, then discard it's ticket before loading complete. +int UtcDaliInternalRequestResourceBitmapRequests02(void) +{ + TestApplication application; // Reset all test adapter return codes + + tet_infoline("Testing bitmap request ticket discard before load complete"); + + Internal::ResourceManager& resourceManager = Internal::ThreadLocalStorage::Get().GetResourceManager(); + Integration::BitmapResourceType bitmapRequest; + Internal::ResourceId id(0); + + testTicketObserver.Reset(); + + { + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + /************************************************************ + * FUNCTION UNDER TEST + ***********************************************************/ + Internal::ResourceTicketPtr ticket = resourceClient.RequestResource( bitmapRequest, "image.png" ); + ticket->AddObserver(testTicketObserver); + Internal::ImageTicketPtr imageTicket(dynamic_cast(ticket.Get())); + DALI_TEST_CHECK( imageTicket ); + DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION ); + + // Update thread will request the bitmap resource: + // Sets application.GetPlatform().mRequest + application.SendNotification(); // Run flush update queue + application.Render(1); + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) ); + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + id=req->GetId(); + + application.SendNotification(); // Should produce no messages + DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( testTicketObserver.LoadFailedCalled(), 0, TEST_LOCATION ); + + DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id)); + + DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION ); + DALI_TEST_CHECK( ticket->GetLoadingState() == ResourceLoading ); + + } // Discard ticket + + // Ensure ticket discarded message is sent to update thread + application.SendNotification(); // Flush update queue + application.Render(0); // Process update messages + + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::CancelLoadFunc ) ); + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) ); + + DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id)); + + // Trigger the event thread to process notify messages. Should then trigger the signals + // in the ticket observer + application.SendNotification(); + + DALI_TEST_EQUALS(testTicketObserver.LoadSucceededCalled(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS(testTicketObserver.LoadFailedCalled(), 0, TEST_LOCATION ); + END_TEST; +} + +// start loading a bitmap resource that doesn't exist, then discard it's ticket after failure +int UtcDaliInternalRequestResourceBitmapRequests03(void) +{ + TestApplication application; // Reset all test adapter return codes + + tet_infoline("Load bitmap that doesn't exist, followed by ticket discard. Expect LoadingFailed"); + + Internal::ResourceManager& resourceManager = Internal::ThreadLocalStorage::Get().GetResourceManager(); + Integration::BitmapResourceType bitmapRequest; + Internal::ResourceId id(0); + + testTicketObserver.Reset(); + { // Scope lifetime of ticket + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + + /************************************************************ + * FUNCTION UNDER TEST + ***********************************************************/ + Internal::ResourceTicketPtr ticket = resourceClient.RequestResource( bitmapRequest, "image.png" ); + ticket->AddObserver(testTicketObserver); + Internal::ImageTicketPtr imageTicket(dynamic_cast(ticket.Get())); + DALI_TEST_CHECK( imageTicket ); + DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION ); + + // Update thread will request the bitmap resource: + // Sets application.GetPlatform().mRequest + application.SendNotification(); // Run flush update queue + application.Render(1); // process update messages + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) ); + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + id=req->GetId(); + application.SendNotification(); // Should produce no messages + DALI_TEST_CHECK( testTicketObserver.LoadFailedCalled() == 0 ); + DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 ); + + DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id)); + + application.GetPlatform().SetResourceLoadFailed(id, Integration::FailureFileNotFound ); + + application.Render(0); // Get failed result + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) ); + application.SendNotification(); // send failed + DALI_TEST_CHECK( testTicketObserver.LoadFailedCalled() != 0 ); + DALI_TEST_CHECK( ticket->GetLoadingState() == ResourceLoadingFailed ); + + DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 ); + DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION ); + + DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id)); + } // Discard ticket + + application.Render(0); // Send DiscardTicket + application.SendNotification(); + + DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id)); + END_TEST; +} + + + +// Load a bitmap resource successfully, then reload it +int UtcDaliInternalRequestReloadBitmapRequests01(void) +{ + TestApplication application; // Reset all test adapter return codes + + tet_infoline("Testing bitmap reload after successful load"); + + Internal::ResourceManager& resourceManager = Internal::ThreadLocalStorage::Get().GetResourceManager(); + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + + Internal::ResourceId id(0); + testTicketObserver.Reset(); + + { + Internal::ResourceTicketPtr ticket = CheckLoadBitmap( application, "image.png", 80, 80 ); + Internal::ImageTicketPtr imageTicket(dynamic_cast(ticket.Get())); + id = ticket->GetId(); + + // Reset call statistics - test that resource is reloaded + application.GetPlatform().ResetTrace(); + + /************************************************************ + * FUNCTION UNDER TEST + ***********************************************************/ + resourceClient.ReloadResource( ticket->GetId() ); + + DALI_TEST_CHECK( ! application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) ); + application.SendNotification(); // Flush update messages + application.Render(0); // Process update messages + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) ); + application.SendNotification(); // Process event messages + + DALI_TEST_EQUALS( ticket->GetLoadingState(), ResourceLoading, TEST_LOCATION ); + DALI_TEST_EQUALS( testTicketObserver.LoadFailedCalled(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 1, TEST_LOCATION ); + DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION ); + + // Create a new resource - the image size could have changed in the meantime + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap2->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 120, 120, 120, 120 ); + Integration::ResourcePointer resourcePtr2(bitmap2); // reference it + DALI_TEST_CHECK( req->GetId() == ticket->GetId() ); + application.GetPlatform().SetResourceLoaded(id, Integration::ResourceBitmap, resourcePtr2); + + application.Render(0); // Process update messages / UpdateCache + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) ); + + DALI_TEST_CHECK( resourceManager.IsResourceLoaded(id)); + Internal::BitmapMetadata bitmapData = resourceManager.GetBitmapMetadata(id); + DALI_TEST_CHECK( bitmapData.GetWidth() == 120 ); + DALI_TEST_CHECK( bitmapData.GetHeight() == 120 ); + + // Ticket can't have been updated yet - it should still have old values + DALI_TEST_EQUALS( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 80, TEST_LOCATION ); + + application.SendNotification(); // Process event messages + application.Render(0); // Process update messages / UpdateCache + application.SendNotification(); // Process event messages + + DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 2, TEST_LOCATION ); + DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( ticket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetWidth(), 120, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 120, TEST_LOCATION ); + + } // Discard ticket + + application.SendNotification(); // Flush update queue (with ticket discarded message + application.Render(1); // Process update messages + application.SendNotification(); // Send event notifications + application.Render(1); // Process update messages + + // Resource should have been discarded. + DALI_TEST_CHECK( ! application.GetPlatform().WasCalled(TestPlatformAbstraction::CancelLoadFunc ) ); + DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id)); + + DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 2, TEST_LOCATION ); + DALI_TEST_EQUALS( testTicketObserver.LoadFailedCalled(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliInternalRequestReloadBitmapRequests02(void) +{ + TestApplication application; // Reset all test adapter return codes + + tet_infoline("Testing bitmap reload during first load"); + + Internal::ResourceManager& resourceManager = Internal::ThreadLocalStorage::Get().GetResourceManager(); + Integration::BitmapResourceType bitmapRequest; + Internal::ResourceId id(0); + + testTicketObserver.Reset(); + + { + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + Internal::ResourceTicketPtr ticket = resourceClient.RequestResource( bitmapRequest, "image.png" ); + ticket->AddObserver(testTicketObserver); + + // Update thread will request the bitmap resource: + // Sets application.GetPlatform().mRequest + application.SendNotification(); // Run flush update queue + application.Render(1); // Process update messages + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) ); + + application.SendNotification(); // Send any event messages + DALI_TEST_CHECK( testTicketObserver.LoadFailedCalled() == 0 ); + DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 ); + + Internal::ImageTicketPtr imageTicket(dynamic_cast(ticket.Get())); + DALI_TEST_CHECK( imageTicket ); + DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION ); + + + /************************************************************ + * FUNCTION UNDER TEST + ***********************************************************/ + resourceClient.ReloadResource( ticket->GetId() ); + /************************************************************ + * Expected result - current load completes as usual, no reload requested + ************************************************************/ + + application.SendNotification(); // Flush update methods + + // Reset call statistics - test that resource is not reloaded + application.GetPlatform().ResetTrace(); + + application.Render(0); // Process reload message (nothing for UpdateCache yet) + + DALI_TEST_CHECK( ! application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) ); + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) ); + // Create a resource + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80, 80, 80, 80 ); + Integration::ResourcePointer resourcePtr(bitmap); // reference it + + // Set up platform abstraction to load it + id=req->GetId(); + + application.GetPlatform().SetResourceLoaded(id, Integration::ResourceBitmap, resourcePtr); + + DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id)); + + application.GetPlatform().ResetTrace(); + // load the cache, which will immediately have the loaded resource + application.Render(0); + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) ); + DALI_TEST_CHECK( resourceManager.IsResourceLoaded(id)); + Internal::BitmapMetadata bitmapData = resourceManager.GetBitmapMetadata(id); + DALI_TEST_CHECK( bitmapData.GetWidth() == 80 ); + DALI_TEST_CHECK( bitmapData.GetHeight() == 80 ); + + DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION ); + + // Trigger the event thread to process notify messages. Should then trigger the signals + // in the ticket observer + application.SendNotification(); + + DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 1, TEST_LOCATION ); + DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( ticket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + + // Check that the image ticket was updated with the image attributes + DALI_TEST_EQUALS( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 80, TEST_LOCATION ); + + DALI_TEST_CHECK( ! application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) ); + + application.SendNotification(); // Flush update messages + application.Render(0); // Process update messages + + // There should be no reload + DALI_TEST_CHECK( ! application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) ); + application.SendNotification(); // Process event messages + + DALI_TEST_EQUALS( ticket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_EQUALS( testTicketObserver.LoadFailedCalled(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 1, TEST_LOCATION ); + DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION ); + + DALI_TEST_CHECK( resourceManager.IsResourceLoaded(id)); + bitmapData = resourceManager.GetBitmapMetadata(id); + DALI_TEST_CHECK( bitmapData.GetWidth() == 80 ); + DALI_TEST_CHECK( bitmapData.GetHeight() == 80 ); + DALI_TEST_EQUALS( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 80, TEST_LOCATION ); + + } // Discard ticket + END_TEST; +} + + +int UtcDaliInternalRequestReloadBitmapRequests03(void) +{ + TestApplication application; // Reset all test adapter return codes + + tet_infoline("Testing bitmap reload at end of first load"); + + Internal::ResourceManager& resourceManager = Internal::ThreadLocalStorage::Get().GetResourceManager(); + Integration::BitmapResourceType bitmapRequest; + Internal::ResourceId id(0); + + testTicketObserver.Reset(); + + { + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + Internal::ResourceTicketPtr ticket = resourceClient.RequestResource( bitmapRequest, "image.png" ); + ticket->AddObserver(testTicketObserver); + + // Update thread will request the bitmap resource: + // Sets application.GetPlatform().mRequest + application.SendNotification(); // Run flush update queue + application.Render(1); // Process update messages + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) ); + + application.SendNotification(); // Send any event messages + DALI_TEST_CHECK( testTicketObserver.LoadFailedCalled() == 0 ); + DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 ); + + Internal::ImageTicketPtr imageTicket(dynamic_cast(ticket.Get())); + DALI_TEST_CHECK( imageTicket ); + DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION ); + + + /************************************************************ + * FUNCTION UNDER TEST + ***********************************************************/ + resourceClient.ReloadResource( ticket->GetId() ); + /************************************************************ + * Expected result - current load completes as usual, no reload requested + ************************************************************/ + + application.SendNotification(); // Flush update methods + + // Reset call statistics - test that resource is not reloaded + application.GetPlatform().ResetTrace(); + + // Create a resource + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80, 80, 80, 80 ); + Integration::ResourcePointer resourcePtr(bitmap); // reference it + + // Set up platform abstraction to load it + id=req->GetId(); + + application.GetPlatform().SetResourceLoaded(id, Integration::ResourceBitmap, resourcePtr); + + DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id)); + + application.GetPlatform().ResetTrace(); + // load the cache, which will immediately have the loaded resource + application.Render(0); + + // UpdateCache runs before ProcessMessages, so the loading resource completes before + // the reload request is handled. + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) ); + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) ); + + DALI_TEST_CHECK( resourceManager.IsResourceLoaded(id)); + Internal::BitmapMetadata bitmapData = resourceManager.GetBitmapMetadata(id); + DALI_TEST_CHECK( bitmapData.GetWidth() == 80 ); + DALI_TEST_CHECK( bitmapData.GetHeight() == 80 ); + + DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION ); + + // Trigger the event thread to process notify messages. Should then trigger the signals + // in the ticket observer + application.SendNotification(); + + DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 1, TEST_LOCATION ); + DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS( ticket->GetLoadingState(), ResourceLoading, TEST_LOCATION ); + + // Check that the image ticket was updated with the image attributes + DALI_TEST_EQUALS( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 80, TEST_LOCATION ); + + DALI_TEST_EQUALS( resourceManager.ResourcesToProcess(), true, TEST_LOCATION ); + + // Create a new resource - the image size could have changed in the meantime + req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap2->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 120, 120, 120, 120 ); + Integration::ResourcePointer resourcePtr2(bitmap2); // reference it + DALI_TEST_CHECK( req->GetId() == id ); + application.GetPlatform().SetResourceLoaded(id, Integration::ResourceBitmap, resourcePtr2); + + application.Render(0); // Process update messages / UpdateCache + + DALI_TEST_CHECK( resourceManager.IsResourceLoaded(id)); + bitmapData = resourceManager.GetBitmapMetadata(id); + DALI_TEST_CHECK( bitmapData.GetWidth() == 120 ); + DALI_TEST_CHECK( bitmapData.GetHeight() == 120 ); + DALI_TEST_EQUALS( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 80, TEST_LOCATION ); + + application.SendNotification(); // Process event messages + + DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 2, TEST_LOCATION ); + + // Not staged - no GL upload + DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION ); + + DALI_TEST_EQUALS( ticket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetWidth(), 120, TEST_LOCATION ); + DALI_TEST_EQUALS( imageTicket->GetHeight(), 120, TEST_LOCATION ); + DALI_TEST_EQUALS( resourceManager.ResourcesToProcess(), false, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliInternalRequestResourceTicket01(void) +{ + TestApplication application; + tet_infoline("Testing RequestResourceTicket() with valid id"); + + testTicketObserver.Reset(); + + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + + // First, load a bitmap resource + Internal::ResourceTicketPtr ticket = CheckLoadBitmap(application, "bitmap.jpg", 80, 80); + + Internal::ResourceTicketPtr newTicket = resourceClient.RequestResourceTicket( ticket->GetId() ); + DALI_TEST_CHECK( newTicket ); + DALI_TEST_CHECK( newTicket->GetId() == ticket->GetId() ); + DALI_TEST_CHECK( newTicket->GetTypePath().type->id == ticket->GetTypePath().type->id ); + END_TEST; +} + +int UtcDaliInternalRequestResourceTicket02(void) +{ + TestApplication application; + tet_infoline("Testing RequestResourceTicket() with invalid id"); + + testTicketObserver.Reset(); + + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + + // First, load a bitmap resource + Internal::ResourceTicketPtr ticket = CheckLoadBitmap(application, "bitmap.jpg", 80, 80); + + Internal::ResourceTicketPtr newTicket = resourceClient.RequestResourceTicket( ticket->GetId() + 2000 ); + DALI_TEST_CHECK( ! newTicket ); + END_TEST; +} + +int UtcDaliInternalAllocateBitmapImage01(void) +{ + TestApplication application; + tet_infoline("Testing AllocateBitmapImage()"); + testTicketObserver.Reset(); + + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + Internal::ImageTicketPtr imageTicket = resourceClient.AllocateBitmapImage(80, 80, 80, 80, Pixel::RGB565); + imageTicket->AddObserver( testTicketObserver ); + + DALI_TEST_CHECK( imageTicket ); + DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION ); + + application.SendNotification(); // Flush update queue + application.Render(0); // Process message + application.SendNotification(); // Send message to tickets + + DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent + DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION ); + + Integration::Bitmap* bitmap = resourceClient.GetBitmap(imageTicket); + DALI_TEST_CHECK ( bitmap != NULL ); + DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 80u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 80u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 80u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 80u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGB565, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliInternalAddBitmapImage01(void) +{ + TestApplication application; + tet_infoline("Testing AddBitmap with reserved buffer()"); + testTicketObserver.Reset(); + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGB565, 80, 80, 80, 80 ); + + Internal::ImageTicketPtr imageTicket = resourceClient.AddBitmapImage( bitmap ); + DALI_TEST_CHECK( imageTicket ); + imageTicket->AddObserver( testTicketObserver ); + + DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION ); + + application.SendNotification(); // Flush update queue + application.Render(0); // Process message + application.SendNotification(); // Send message to tickets + + DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent + DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION ); + + Integration::Bitmap* theBitmap = resourceClient.GetBitmap(imageTicket); + DALI_TEST_CHECK ( theBitmap != NULL ); + DALI_TEST_CHECK ( bitmap == theBitmap ); + DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 80u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 80u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 80u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 80u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGB565, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliInternalAddBitmapImage02(void) +{ + TestApplication application; + tet_infoline("Testing AddBitmap without reserved buffer()"); + testTicketObserver.Reset(); + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + + Internal::ImageTicketPtr imageTicket = resourceClient.AddBitmapImage( bitmap ); + DALI_TEST_CHECK( imageTicket ); + imageTicket->AddObserver( testTicketObserver ); + + DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetHeight(), 0, TEST_LOCATION ); + DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent + + application.SendNotification(); // Flush update queue + application.Render(0); // Process message + application.SendNotification(); // Send message to tickets + + DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetWidth(), 0, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetHeight(), 0, TEST_LOCATION ); + DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent + + Integration::Bitmap* theBitmap = resourceClient.GetBitmap(imageTicket); + DALI_TEST_CHECK ( theBitmap != NULL ); + DALI_TEST_CHECK ( bitmap == theBitmap ); + DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION ); + + // There is no way for the ticket's image attributes to be updated if the bitmap + // reserves a buffer after ticket generation. + // Probably not an issue - there is no public API in BufferImage to change the image size. + END_TEST; +} + + +int UtcDaliInternalAddBitmapImage03(void) +{ + TestApplication application; + tet_infoline("Testing AddBitmap() with invalid bitmap"); + testTicketObserver.Reset(); + + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + Internal::ImageTicketPtr imageTicket; + bool exceptionRaised=false; + try + { + imageTicket = resourceClient.AddBitmapImage( NULL ); + } + catch( DaliException& e ) + { + exceptionRaised = true; + } + DALI_TEST_CHECK( exceptionRaised ); + DALI_TEST_CHECK( ! imageTicket ); + END_TEST; +} + +int UtcDaliInternalGetBitmapImage01(void) +{ + TestApplication application; + tet_infoline("Testing GetBitmap() with valid ticket"); + testTicketObserver.Reset(); + + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 20, 20, 80, 80 ); + Internal::ImageTicketPtr imageTicket = resourceClient.AddBitmapImage( bitmap ); + + Integration::Bitmap* theBitmap = resourceClient.GetBitmap(imageTicket); + DALI_TEST_CHECK ( theBitmap != NULL ); + DALI_TEST_CHECK ( bitmap == theBitmap ); + DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 20u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 20u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 80u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 80u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION ); + + imageTicket->AddObserver( testTicketObserver ); + application.SendNotification(); // Flush update queue + application.Render(0); // Process message + application.SendNotification(); // Send message to tickets + + theBitmap = resourceClient.GetBitmap(imageTicket); + DALI_TEST_CHECK ( theBitmap != NULL ); + DALI_TEST_CHECK ( bitmap == theBitmap ); + DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 20u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 20u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 80u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 80u, TEST_LOCATION ); + DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliInternalGetBitmapImage02(void) +{ + TestApplication application; + tet_infoline("Testing GetBitmap() with invalid ticket"); + + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + Internal::ImageTicketPtr imageTicket; + Integration::Bitmap* theBitmap = NULL; + bool exceptionRaised = false; + try + { + theBitmap = resourceClient.GetBitmap(imageTicket); + } catch (DaliException& e) + { + exceptionRaised = true; + } + DALI_TEST_CHECK( exceptionRaised ); + DALI_TEST_CHECK( ! theBitmap ); + END_TEST; +} + +int UtcDaliInternalGetBitmapImage03(void) +{ + TestApplication application; + tet_infoline("Testing GetBitmap() with valid ticket for incorrect type"); + + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); Internal::ResourceTicketPtr imageTicket = CheckLoadBitmap( application, "Stuff.png", 100, 100 ); + + Integration::Bitmap* theBitmap = NULL; + theBitmap = resourceClient.GetBitmap(imageTicket); + DALI_TEST_CHECK( ! theBitmap ); + + END_TEST; +} + +int UtcDaliInternalAllocateTexture01(void) +{ + TestApplication application; + tet_infoline("Testing AllocateTexture()"); + testTicketObserver.Reset(); + + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + Internal::ResourceTicketPtr resourceTicket = resourceClient.AllocateTexture(80, 80, Pixel::L8 ); + resourceTicket->AddObserver( testTicketObserver ); + + DALI_TEST_CHECK( resourceTicket ); + DALI_TEST_EQUALS ( resourceTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 ); + + application.SendNotification(); // Flush update queue + application.Render(0); // Process message + application.SendNotification(); // Send message to tickets + + DALI_TEST_EQUALS ( resourceTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 ); + END_TEST; +} + +int UtcDaliInternalAddNativeImage(void) +{ + TestApplication application; + tet_infoline("Testing AddNativeImage()"); + + testTicketObserver.Reset(); + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + Internal::ResourceTicketPtr ticket; + Internal::ImageTicketPtr imageTicket; + { // Test image going out of scope after ticket creation (message to Update thread holds a ref) + TestNativeImagePointer nativeImage = TestNativeImage::New( 80, 80 ); + ticket = resourceClient.AddNativeImage( *nativeImage ); + imageTicket = dynamic_cast(ticket.Get()); + DALI_TEST_CHECK( imageTicket ); + imageTicket->AddObserver( testTicketObserver ); + } + + DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION ); + DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent + + application.SendNotification(); // Flush update queue + application.Render(0); // Process message + application.SendNotification(); // Send message to tickets + + DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION ); + DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent + + Integration::Bitmap* theBitmap = NULL; + theBitmap = resourceClient.GetBitmap(imageTicket); + + DALI_TEST_CHECK ( theBitmap == NULL ); + END_TEST; +} + +int UtcDaliInternalAddFrameBufferImage(void) +{ + TestApplication application; + tet_infoline("Testing AddFrameBufferImage()"); + + testTicketObserver.Reset(); + Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient(); + Internal::ImageTicketPtr imageTicket = resourceClient.AddFrameBufferImage(80, 80, Pixel::A8, RenderBuffer::COLOR ); + DALI_TEST_CHECK( imageTicket ); + imageTicket->AddObserver( testTicketObserver ); + + DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent + + application.SendNotification(); // Flush update queue + application.Render(0); // Process message + application.SendNotification(); // Send message to tickets + + DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION ); + DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION ); + DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent + + Integration::Bitmap* theBitmap = NULL; + theBitmap = resourceClient.GetBitmap(imageTicket); + DALI_TEST_CHECK ( theBitmap == NULL ); + END_TEST; +} diff --git a/automated-tests/src/dali/CMakeLists.txt b/automated-tests/src/dali/CMakeLists.txt new file mode 100644 index 0000000..d474038 --- /dev/null +++ b/automated-tests/src/dali/CMakeLists.txt @@ -0,0 +1,118 @@ +SET(PKG_NAME "dali") + +SET(EXEC_NAME "tct-${PKG_NAME}-core") +SET(RPM_NAME "core-${PKG_NAME}-tests") + +SET(CAPI_LIB "dali") + +SET(TC_SOURCES + utc-Dali-Actor.cpp + utc-Dali-AlphaFunction.cpp + utc-Dali-AngleAxis.cpp + utc-Dali-Animation.cpp + utc-Dali-Any.cpp + utc-Dali-BaseHandle.cpp + utc-Dali-BufferImage.cpp + utc-Dali-CameraActor.cpp + utc-Dali-Constraint.cpp + utc-Dali-ConstraintFunction.cpp + utc-Dali-Constraints.cpp + utc-Dali-ConstraintSource.cpp + utc-Dali-ConnectionTracker.cpp + utc-Dali-CustomActor.cpp + utc-Dali-Degree.cpp + utc-Dali-EncodedBufferImage.cpp + utc-Dali-FrameBufferImage.cpp + utc-Dali-Gesture.cpp + utc-Dali-GestureDetector.cpp + utc-Dali-Handle.cpp + utc-Dali-HoverProcessing.cpp + utc-Dali-Image.cpp + utc-Dali-ImageActor.cpp + utc-Dali-IntrusivePtr.cpp + utc-Dali-KeyEvent.cpp + utc-Dali-Layer.cpp + utc-Dali-LocklessBuffer.cpp + utc-Dali-LongPressGesture.cpp + utc-Dali-LongPressGestureDetector.cpp + utc-Dali-MathUtils.cpp + utc-Dali-Matrix.cpp + utc-Dali-Matrix3.cpp + utc-Dali-MeshMaterial.cpp + utc-Dali-NativeImage.cpp + utc-Dali-NinePatchImages.cpp + utc-Dali-ObjectRegistry.cpp + utc-Dali-PanGesture.cpp + utc-Dali-PanGestureDetector.cpp + utc-Dali-Path.cpp + utc-Dali-PinchGesture.cpp + utc-Dali-PinchGestureDetector.cpp + utc-Dali-Pixel.cpp + utc-Dali-PropertyMap.cpp + utc-Dali-PropertyArray.cpp + utc-Dali-PropertyNotification.cpp + utc-Dali-PropertyTypes.cpp + utc-Dali-PropertyValue.cpp + utc-Dali-Quaternion.cpp + utc-Dali-Radian.cpp + utc-Dali-Random.cpp + utc-Dali-Rect.cpp + utc-Dali-RenderTask.cpp + utc-Dali-RenderTaskList.cpp + utc-Dali-ResourceImage.cpp + utc-Dali-ShaderEffect.cpp + utc-Dali-SignalTemplatesFunctors.cpp + utc-Dali-SignalTemplates.cpp + utc-Dali-Stage.cpp + utc-Dali-TapGesture.cpp + utc-Dali-TapGestureDetector.cpp + utc-Dali-TouchEventCombiner.cpp + utc-Dali-TouchProcessing.cpp + utc-Dali-TypeRegistry.cpp + utc-Dali-Uint16Pair.cpp + utc-Dali-Vector.cpp + utc-Dali-Vector2.cpp + utc-Dali-Vector3.cpp + utc-Dali-Vector4.cpp + utc-Dali-WheelEvent.cpp + utc-Dali-Constrainer.cpp +) + +LIST(APPEND TC_SOURCES + dali-test-suite-utils/mesh-builder.cpp + dali-test-suite-utils/dali-test-suite-utils.cpp + dali-test-suite-utils/test-harness.cpp + dali-test-suite-utils/test-application.cpp + dali-test-suite-utils/test-gesture-manager.cpp + dali-test-suite-utils/test-gl-abstraction.cpp + dali-test-suite-utils/test-gl-sync-abstraction.cpp + dali-test-suite-utils/test-native-image.cpp + dali-test-suite-utils/test-platform-abstraction.cpp + dali-test-suite-utils/test-render-controller.cpp + dali-test-suite-utils/test-trace-call-stack.cpp +) + +PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED + dali-core +) + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${${CAPI_LIB}_CFLAGS_OTHER} -O0 -ggdb --coverage -Wall -Werror=return-type") + +FOREACH(directory ${${CAPI_LIB}_LIBRARY_DIRS}) + SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -L${directory}") +ENDFOREACH(directory ${CAPI_LIB_LIBRARY_DIRS}) + +INCLUDE_DIRECTORIES( + ../../../ + ${${CAPI_LIB}_INCLUDE_DIRS} + dali-test-suite-utils +) + +ADD_EXECUTABLE(${EXEC_NAME} ${EXEC_NAME}.cpp ${TC_SOURCES}) +TARGET_LINK_LIBRARIES(${EXEC_NAME} + ${${CAPI_LIB}_LIBRARIES} +) + +INSTALL(PROGRAMS ${EXEC_NAME} + DESTINATION ${BIN_DIR}/${EXEC_NAME} +) diff --git a/automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.cpp b/automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.cpp new file mode 100644 index 0000000..d053cf5 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include "dali-test-suite-utils.h" + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +using namespace Dali; + +int test_return_value = TET_UNDEF; + +void tet_result(int value) +{ + // First TET_PASS should set to zero + // first TET_FAIL should prevent any further TET_PASS from setting back to zero + // Any TET_FAIL should set to fail or leave as fail + if( test_return_value != 1 ) + test_return_value = value; +} + +#define END_TEST \ + return ((test_return_value>0)?1:0) + + +void tet_infoline(const char* str) +{ + fprintf(stderr, "%s\n", str); +} + +void tet_printf(const char *format, ...) +{ + va_list arg; + va_start(arg, format); + vfprintf(stderr, format, arg); + va_end(arg); +} + +bool operator==(TimePeriod a, TimePeriod b) +{ + return Equals(a.durationSeconds, b.durationSeconds) && Equals(a.delaySeconds, b.delaySeconds) ; +} + +std::ostream& operator<<( std::ostream& ostream, TimePeriod value ) +{ + return ostream << "( Duration:" << value.durationSeconds << " Delay:" << value.delaySeconds << ")"; +} + +std::ostream& operator<<( std::ostream& ostream, Radian angle ) +{ + ostream << angle.radian; + return ostream; +} + +std::ostream& operator<<( std::ostream& ostream, Degree angle ) +{ + ostream << angle.degree; + return ostream; +} + +void DALI_TEST_EQUALS( const Matrix3& matrix1, const Matrix3& matrix2, const char* location) +{ + const float* m1 = matrix1.AsFloat(); + const float* m2 = matrix2.AsFloat(); + bool equivalent = true; + + for (int i=0;i<9;++i) + { + if( ! (fabsf(m1[i] - m2[i])< GetRangedEpsilon(m1[i], m2[i])) ) + { + equivalent = false; + } + } + + if( !equivalent ) + { + fprintf(stderr, "%s, checking\n" + "(%f, %f, %f) (%f, %f, %f)\n" + "(%f, %f, %f) == (%f, %f, %f)\n" + "(%f, %f, %f) (%f, %f, %f)\n", + location, + m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], + m1[3], m1[4], m1[5], m2[3], m2[4], m2[5], + m1[6], m1[7], m1[8], m2[6], m2[7], m2[8]); + + tet_result(TET_FAIL); + } + else + { + tet_result(TET_PASS); + } +} + +void DALI_TEST_EQUALS( const Matrix3& matrix1, const Matrix3& matrix2, float epsilon, const char* location) +{ + const float* m1 = matrix1.AsFloat(); + const float* m2 = matrix2.AsFloat(); + bool equivalent = true; + + for (int i=0;i<9;++i) + { + equivalent &= (fabsf(m1[i] - m2[i]) +#include + +// INTERNAL INCLUDES +#include + +void tet_infoline(const char*str); +void tet_printf(const char *format, ...); + +#include "test-application.h" + +using namespace Dali; + +#define STRINGIZE_I(text) #text +#define STRINGIZE(text) STRINGIZE_I(text) + +// the following is the other compilers way of token pasting, gcc seems to just concatenate strings automatically +//#define TOKENPASTE(x,y) x ## y +#define TOKENPASTE(x,y) x y +#define TOKENPASTE2(x,y) TOKENPASTE( x, y ) +#define TEST_LOCATION TOKENPASTE2( "Test failed in ", TOKENPASTE2( __FILE__, TOKENPASTE2( ", line ", STRINGIZE(__LINE__) ) ) ) + +#define TET_UNDEF 2 +#define TET_FAIL 1 +#define TET_PASS 0 + +extern int test_return_value; + +void tet_result(int value); + +#define END_TEST \ + return ((test_return_value>0)?1:0) + +void tet_infoline(const char* str); +void tet_printf(const char *format, ...); + +/** + * DALI_TEST_CHECK is a wrapper for tet_result. + * If the condition evaluates to false, the test is stopped. + * @param[in] The boolean expression to check + */ +#define DALI_TEST_CHECK(condition) \ +if ( (condition) ) \ +{ \ + tet_result(TET_PASS); \ +} \ +else \ +{ \ + fprintf(stderr, "%s Failed in %s at line %d\n", __PRETTY_FUNCTION__, __FILE__, __LINE__); \ + tet_result(TET_FAIL); \ + throw("TET_FAIL"); \ +} + +template +inline bool CompareType(Type value1, Type value2, float epsilon); + +/** + * A helper for fuzzy-comparing Vector2 objects + * @param[in] vector1 the first object + * @param[in] vector2 the second object + * @param[in] epsilon difference threshold + * @returns true if difference is smaller than epsilon threshold, false otherwise + */ +template <> +inline bool CompareType(float value1, float value2, float epsilon) +{ + return fabsf(value1 - value2) < epsilon; +} + +/** + * A helper for fuzzy-comparing Vector2 objects + * @param[in] vector1 the first object + * @param[in] vector2 the second object + * @param[in] epsilon difference threshold + * @returns true if difference is smaller than epsilon threshold, false otherwise + */ +template <> +inline bool CompareType(Vector2 vector1, Vector2 vector2, float epsilon) +{ + return fabsf(vector1.x - vector2.x) +inline bool CompareType(Vector3 vector1, Vector3 vector2, float epsilon) +{ + return fabsf(vector1.x - vector2.x) +inline bool CompareType(Vector4 vector1, Vector4 vector2, float epsilon) +{ + return fabsf(vector1.x - vector2.x) +inline bool CompareType(Quaternion q1, Quaternion q2, float epsilon) +{ + Quaternion q2N = -q2; // These quaternions represent the same rotation + return CompareType(q1.mVector, q2.mVector, epsilon) || CompareType(q1.mVector, q2N.mVector, epsilon); +} + +template <> +inline bool CompareType(Radian q1, Radian q2, float epsilon) +{ + return CompareType(q1.radian, q2.radian, epsilon); +} + +template <> +inline bool CompareType(Degree q1, Degree q2, float epsilon) +{ + return CompareType(q1.degree, q2.degree, epsilon); +} + +bool operator==(TimePeriod a, TimePeriod b); +std::ostream& operator<<( std::ostream& ostream, TimePeriod value ); +std::ostream& operator<<( std::ostream& ostream, Radian angle ); +std::ostream& operator<<( std::ostream& ostream, Degree angle ); + +/** + * Test whether two values are equal. + * @param[in] value1 The first value + * @param[in] value2 The second value + * @param[in] location The TEST_LOCATION macro should be used here + */ +template +inline void DALI_TEST_EQUALS(TypeA value1, TypeB value2, const char* location) +{ + if (!(value1 == value2)) + { + std::ostringstream o; + o << value1 << " == " << value2 << std::endl; + fprintf(stderr, "%s, checking %s", location, o.str().c_str()); + tet_result(TET_FAIL); + } + else + { + tet_result(TET_PASS); + } +} + +template +inline void DALI_TEST_EQUALS(Type value1, Type value2, float epsilon, const char* location) +{ + if( !CompareType(value1, value2, epsilon) ) + { + std::ostringstream o; + o << value1 << " == " << value2 << std::endl; + fprintf(stderr, "%s, checking %s", location, o.str().c_str()); + tet_result(TET_FAIL); + } + else + { + tet_result(TET_PASS); + } +} + +/** + * Test whether two TimePeriods are within a certain distance of each other. + * @param[in] value1 The first value + * @param[in] value2 The second value + * @param[in] epsilon The values must be within this distance of each other + * @param[in] location The TEST_LOCATION macro should be used here + */ +template<> +inline void DALI_TEST_EQUALS( TimePeriod value1, TimePeriod value2, float epsilon, const char* location) +{ + if ((fabs(value1.durationSeconds - value2.durationSeconds) > epsilon)) + { + fprintf(stderr, "%s, checking durations %f == %f, epsilon %f\n", location, value1.durationSeconds, value2.durationSeconds, epsilon); + tet_result(TET_FAIL); + } + else if ((fabs(value1.delaySeconds - value2.delaySeconds) > epsilon)) + { + fprintf(stderr, "%s, checking delays %f == %f, epsilon %f\n", location, value1.delaySeconds, value2.delaySeconds, epsilon); + tet_result(TET_FAIL); + } + else + { + tet_result(TET_PASS); + } +} + +/** + * Test whether two Matrix3 objects are equal. + * @param[in] matrix1 The first object + * @param[in] matrix2 The second object + * @param[in] location The TEST_LOCATION macro should be used here + */ +void DALI_TEST_EQUALS( const Matrix3& matrix1, const Matrix3& matrix2, const char* location); + +/** Test whether two Matrix3 objects are equal (fuzzy compare). + * @param[in] matrix1 The first object + * @param[in] matrix2 The second object + * @param[in] epsilon The epsilon to use for comparison + * @param[in] location The TEST_LOCATION macro should be used here + */ +void DALI_TEST_EQUALS( const Matrix3& matrix1, const Matrix3& matrix2, float epsilon, const char* location); + +/** + * Test whether two Matrix objects are equal. + * @param[in] matrix1 The first object + * @param[in] matrix2 The second object + * @param[in] location The TEST_LOCATION macro should be used here + */ +void DALI_TEST_EQUALS( const Matrix& matrix1, const Matrix& matrix2, const char* location); + +/** + * Test whether two Matrix objects are equal (fuzzy-compare). + * @param[in] matrix1 The first object + * @param[in] matrix2 The second object + * @param[in] location The TEST_LOCATION macro should be used here + */ +void DALI_TEST_EQUALS( const Matrix& matrix1, const Matrix& matrix2, float epsilon, const char* location); + +/** + * Test whether two strings are equal. + * @param[in] str1 The first string + * @param[in] str2 The second string + * @param[in] location The TEST_LOCATION macro should be used here + */ +template<> +inline void DALI_TEST_EQUALS( const char* str1, const char* str2, const char* location) +{ + if (strcmp(str1, str2)) + { + fprintf(stderr, "%s, checking '%s' == '%s'\n", location, str1, str2); + tet_result(TET_FAIL); + } + else + { + tet_result(TET_PASS); + } +} + +/** + * Test whether two strings are equal. + * @param[in] str1 The first string + * @param[in] str2 The second string + * @param[in] location The TEST_LOCATION macro should be used here + */ +template<> +inline void DALI_TEST_EQUALS( const std::string &str1, const std::string &str2, const char* location) +{ + DALI_TEST_EQUALS(str1.c_str(), str2.c_str(), location); +} + +/** + * Test whether two strings are equal. + * @param[in] str1 The first string + * @param[in] str2 The second string + * @param[in] location The TEST_LOCATION macro should be used here + */ +void DALI_TEST_EQUALS( const std::string &str1, const char* str2, const char* location); + +/** + * Test whether two strings are equal. + * @param[in] str1 The first string + * @param[in] str2 The second string + * @param[in] location The TEST_LOCATION macro should be used here + */ +void DALI_TEST_EQUALS( const char* str1, const std::string &str2, const char* location); + +/** + * Test whether one unsigned integer value is greater than another. + * Test succeeds if value1 > value2 + * @param[in] value1 The first value + * @param[in] value2 The second value + * @param[in] location The TEST_LOCATION macro should be used here + */ +template< typename T > +void DALI_TEST_GREATER( T value1, T value2, const char* location) +{ + if (!(value1 > value2)) + { + std::cerr << location << ", checking " << value1 <<" > " << value2 << "\n"; + tet_result(TET_FAIL); + } + else + { + tet_result(TET_PASS); + } +} + +/** + * Test whether the assertion condition that failed and thus triggered the + * exception \b e contained a given substring. + * @param[in] e The exception that we expect was fired by a runtime assertion failure. + * @param[in] conditionSubString The text that we expect to be present in an + * assertion which triggered the exception. + * @param[in] location The TEST_LOCATION macro should be used here. + */ +void DALI_TEST_ASSERT( DaliException& e, std::string conditionSubString, const char* location ); + +/** + * Print the assert + * @param[in] e The exception that we expect was fired by a runtime assertion failure. + */ +inline void DALI_TEST_PRINT_ASSERT( DaliException& e ) +{ + tet_printf("Assertion %s failed at %s\n", e.condition, e.location ); +} + +// Functor to test whether an Applied signal is emitted +struct ConstraintAppliedCheck +{ + ConstraintAppliedCheck( bool& signalReceived ); + void operator()( Constraint& constraint ); + void Reset(); + void CheckSignalReceived(); + void CheckSignalNotReceived(); + bool& mSignalReceived; // owned by individual tests +}; + +/** + * A Helper to test default functions + */ +template +struct DefaultFunctionCoverage +{ + DefaultFunctionCoverage() + { + T a; + T *b = new T(a); + DALI_TEST_CHECK(b); + a = *b; + delete b; + } +}; + + +// Helper to Create buffer image +BufferImage CreateBufferImage(); + +#endif // __DALI_TEST_SUITE_UTILS_H__ diff --git a/automated-tests/src/dali/dali-test-suite-utils/mesh-builder.cpp b/automated-tests/src/dali/dali-test-suite-utils/mesh-builder.cpp new file mode 100644 index 0000000..3fdae8a --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/mesh-builder.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include "mesh-builder.h" + +namespace Dali +{ + +Material CreateMaterial(float opacity) +{ + Shader shader = Shader::New( "vertexSrc", "fragmentSrc" ); + Material material = Material::New(shader); + + Vector4 color = Color::WHITE; + color.a = opacity; + material.SetProperty(Material::Property::COLOR, color); + return material; +} + +Material CreateMaterial(float opacity, Image image) +{ + Shader shader = Shader::New( "vertexSrc", "fragmentSrc" ); + Material material = Material::New(shader); + + Vector4 color = Color::WHITE; + color.a = opacity; + material.SetProperty(Material::Property::COLOR, color); + + Sampler sampler = Sampler::New( image, "sTexture" ); + material.AddSampler( sampler ); + + return material; +} + +PropertyBuffer CreatePropertyBuffer() +{ + Property::Map texturedQuadVertexFormat; + texturedQuadVertexFormat["aPosition"] = Property::VECTOR2; + texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2; + + PropertyBuffer vertexData = PropertyBuffer::New( texturedQuadVertexFormat, 4 ); + return vertexData; +} + +Geometry CreateQuadGeometry(void) +{ + PropertyBuffer vertexData = CreatePropertyBuffer(); + return CreateQuadGeometryFromBuffer( vertexData ); +} + +Geometry CreateQuadGeometryFromBuffer( PropertyBuffer vertexData ) +{ + const float halfQuadSize = .5f; + struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; }; + TexturedQuadVertex texturedQuadVertexData[4] = { + { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) }, + { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) }, + { Vector2(-halfQuadSize, halfQuadSize), Vector2(0.f, 1.f) }, + { Vector2( halfQuadSize, halfQuadSize), Vector2(1.f, 1.f) } }; + vertexData.SetData(texturedQuadVertexData); + + unsigned int indexData[6] = { 0, 3, 1, 0, 2, 3 }; + Property::Map indexFormat; + indexFormat["indices"] = Property::INTEGER; + PropertyBuffer indices = PropertyBuffer::New( indexFormat, sizeof(indexData)/sizeof(indexData[0]) ); + indices.SetData(indexData); + + Geometry geometry = Geometry::New(); + geometry.AddVertexBuffer( vertexData ); + geometry.SetIndexBuffer( indices ); + + return geometry; +} + + + +} // namespace Dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/mesh-builder.h b/automated-tests/src/dali/dali-test-suite-utils/mesh-builder.h new file mode 100644 index 0000000..a123808 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/mesh-builder.h @@ -0,0 +1,38 @@ +#ifndef MESH_BUILDER_H +#define MESH_BUILDER_H +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +Material CreateMaterial(float opacity); +Material CreateMaterial(float opacity, Image image); +Geometry CreateQuadGeometry(); +Geometry CreateQuadGeometryFromBuffer( PropertyBuffer vertexData ); +PropertyBuffer CreatePropertyBuffer(); + +} + +#endif // MESH_BUILDER_H diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp new file mode 100644 index 0000000..5d17a1d --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test-application.h" + +namespace Dali +{ + + +TestApplication::TestApplication( size_t surfaceWidth, + size_t surfaceHeight, + float horizontalDpi, + float verticalDpi, + ResourcePolicy::DataRetention policy) +: mCore( NULL ), + mSurfaceWidth( surfaceWidth ), + mSurfaceHeight( surfaceHeight ), + mFrame( 0u ), + mDpi( horizontalDpi, verticalDpi ), + mLastVSyncTime(0u), + mDataRetentionPolicy(policy) +{ + Initialize(); +} + +TestApplication::TestApplication( bool initialize, + size_t surfaceWidth, + size_t surfaceHeight, + float horizontalDpi, + float verticalDpi, + ResourcePolicy::DataRetention policy) +: mCore( NULL ), + mSurfaceWidth( surfaceWidth ), + mSurfaceHeight( surfaceHeight ), + mFrame( 0u ), + mDpi( horizontalDpi, verticalDpi ), + mLastVSyncTime(0u), + mDataRetentionPolicy( policy ) +{ + if ( initialize ) + { + Initialize(); + } +} + +void TestApplication::Initialize() +{ + mCore = Dali::Integration::Core::New( + mRenderController, + mPlatformAbstraction, + mGlAbstraction, + mGlSyncAbstraction, + mGestureManager, + mDataRetentionPolicy); + + mCore->ContextCreated(); + mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight ); + mCore->SetDpi( mDpi.x, mDpi.y ); + + Dali::Integration::Log::LogFunction logFunction(&TestApplication::LogMessage); + Dali::Integration::Log::InstallLogFunction(logFunction); + + mCore->SceneCreated(); +} + +TestApplication::~TestApplication() +{ + Dali::Integration::Log::UninstallLogFunction(); + delete mCore; +} + +void TestApplication::LogMessage(Dali::Integration::Log::DebugPriority level, std::string& message) +{ + switch(level) + { + case Dali::Integration::Log::DebugInfo: + fprintf(stderr, "INFO: %s", message.c_str()); + break; + case Dali::Integration::Log::DebugWarning: + fprintf(stderr, "WARN: %s", message.c_str()); + break; + case Dali::Integration::Log::DebugError: + fprintf(stderr, "ERROR: %s", message.c_str()); + break; + default: + fprintf(stderr, "DEFAULT: %s", message.c_str()); + break; + } +} + +Dali::Integration::Core& TestApplication::GetCore() +{ + return *mCore; +} + +TestPlatformAbstraction& TestApplication::GetPlatform() +{ + return mPlatformAbstraction; +} + +TestRenderController& TestApplication::GetRenderController() +{ + return mRenderController; +} + +TestGlAbstraction& TestApplication::GetGlAbstraction() +{ + return mGlAbstraction; +} + +TestGlSyncAbstraction& TestApplication::GetGlSyncAbstraction() +{ + return mGlSyncAbstraction; +} + +TestGestureManager& TestApplication::GetGestureManager() +{ + return mGestureManager; +} + +void TestApplication::ProcessEvent(const Integration::Event& event) +{ + mCore->QueueEvent(event); + mCore->ProcessEvents(); +} + +void TestApplication::SendNotification() +{ + mCore->ProcessEvents(); +} + +void TestApplication::SetSurfaceWidth( unsigned int width, unsigned height ) +{ + mSurfaceWidth = width; + mSurfaceHeight = height; + + mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight ); +} + +void TestApplication::DoUpdate( unsigned int intervalMilliseconds ) +{ + unsigned int seconds(0u), microseconds(0u); + mPlatformAbstraction.GetTimeMicroseconds( seconds, microseconds ); + mLastVSyncTime = ( seconds * 1e3 ) + ( microseconds / 1e3 ); + unsigned int nextVSyncTime = mLastVSyncTime + 16; + + // Update Time values + mPlatformAbstraction.IncrementGetTimeResult( intervalMilliseconds ); + + float elapsedSeconds = intervalMilliseconds / 1e3f; + mCore->Update( elapsedSeconds, mLastVSyncTime, nextVSyncTime, mStatus ); +} + +bool TestApplication::Render( unsigned int intervalMilliseconds ) +{ + DoUpdate( intervalMilliseconds ); + mCore->Render( mRenderStatus ); + + mFrame++; + + return mStatus.KeepUpdating() || mRenderStatus.NeedsUpdate(); +} + +unsigned int TestApplication::GetUpdateStatus() +{ + return mStatus.KeepUpdating(); +} + +bool TestApplication::UpdateOnly( unsigned int intervalMilliseconds ) +{ + DoUpdate( intervalMilliseconds ); + return mStatus.KeepUpdating(); +} + +bool TestApplication::RenderOnly( ) +{ + // Update Time values + mCore->Render( mRenderStatus ); + + mFrame++; + + return mRenderStatus.NeedsUpdate(); +} + +void TestApplication::ResetContext() +{ + mCore->ContextDestroyed(); + mCore->ContextCreated(); +} + + +} // Namespace dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-application.h b/automated-tests/src/dali/dali-test-suite-utils/test-application.h new file mode 100644 index 0000000..ed33f52 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-application.h @@ -0,0 +1,109 @@ +#ifndef __DALI_TEST_APPLICATION_H__ +#define __DALI_TEST_APPLICATION_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include "test-gesture-manager.h" +#include "test-gl-sync-abstraction.h" +#include "test-gl-abstraction.h" +#include "test-render-controller.h" +#include +#include +#include + +namespace Dali +{ + +class DALI_IMPORT_API TestApplication : public ConnectionTracker +{ +public: + + // Default values derived from H2 device. + static const unsigned int DEFAULT_SURFACE_WIDTH = 480; + static const unsigned int DEFAULT_SURFACE_HEIGHT = 800; + +#ifdef _CPP11 + static constexpr float DEFAULT_HORIZONTAL_DPI = 220.0f; + static constexpr float DEFAULT_VERTICAL_DPI = 217.0f; +#else + static const float DEFAULT_HORIZONTAL_DPI = 220.0f; + static const float DEFAULT_VERTICAL_DPI = 217.0f; +#endif + + static const unsigned int DEFAULT_RENDER_INTERVAL = 1; + + TestApplication( size_t surfaceWidth = DEFAULT_SURFACE_WIDTH, + size_t surfaceHeight = DEFAULT_SURFACE_HEIGHT, + float horizontalDpi = DEFAULT_HORIZONTAL_DPI, + float verticalDpi = DEFAULT_VERTICAL_DPI, + ResourcePolicy::DataRetention policy = ResourcePolicy::DALI_DISCARDS_ALL_DATA); + + TestApplication( bool initialize, + size_t surfaceWidth = DEFAULT_SURFACE_WIDTH, + size_t surfaceHeight = DEFAULT_SURFACE_HEIGHT, + float horizontalDpi = DEFAULT_HORIZONTAL_DPI, + float verticalDpi = DEFAULT_VERTICAL_DPI, + ResourcePolicy::DataRetention policy = ResourcePolicy::DALI_DISCARDS_ALL_DATA); + + void Initialize(); + virtual ~TestApplication(); + static void LogMessage( Dali::Integration::Log::DebugPriority level, std::string& message ); + Dali::Integration::Core& GetCore(); + TestPlatformAbstraction& GetPlatform(); + TestRenderController& GetRenderController(); + TestGlAbstraction& GetGlAbstraction(); + TestGlSyncAbstraction& GetGlSyncAbstraction(); + TestGestureManager& GetGestureManager(); + void ProcessEvent(const Integration::Event& event); + void SendNotification(); + void SetSurfaceWidth( unsigned int width, unsigned height ); + bool Render( unsigned int intervalMilliseconds = DEFAULT_RENDER_INTERVAL ); + unsigned int GetUpdateStatus(); + bool UpdateOnly( unsigned int intervalMilliseconds = DEFAULT_RENDER_INTERVAL ); + bool RenderOnly( ); + void ResetContext(); + +private: + void DoUpdate( unsigned int intervalMilliseconds ); + +protected: + TestPlatformAbstraction mPlatformAbstraction; + TestRenderController mRenderController; + TestGlAbstraction mGlAbstraction; + TestGlSyncAbstraction mGlSyncAbstraction; + TestGestureManager mGestureManager; + + Integration::UpdateStatus mStatus; + Integration::RenderStatus mRenderStatus; + + Integration::Core* mCore; + + unsigned int mSurfaceWidth; + unsigned int mSurfaceHeight; + unsigned int mFrame; + + Vector2 mDpi; + unsigned int mLastVSyncTime; + ResourcePolicy::DataRetention mDataRetentionPolicy; +}; + +} // Dali + +#endif diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.cpp new file mode 100644 index 0000000..2844ff1 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.cpp @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test-gesture-manager.h" + +namespace Dali +{ + +TestGestureManager::TestGestureManager() +{ + Initialize(); +} + +/** + * Destructor + */ +TestGestureManager::~TestGestureManager() +{ +} + +/** + * @copydoc Dali::Integration::GestureManager::Register(Gesture::Type) + */ +void TestGestureManager::Register(const Integration::GestureRequest& request) +{ + mFunctionsCalled.Register = true; +} + +/** + * @copydoc Dali::Integration::GestureManager::Unregister(Gesture::Type) + */ +void TestGestureManager::Unregister(const Integration::GestureRequest& request) +{ + mFunctionsCalled.Unregister = true; +} + +/** + * @copydoc Dali::Integration::GestureManager::Update(Gesture::Type) + */ +void TestGestureManager::Update(const Integration::GestureRequest& request) +{ + mFunctionsCalled.Update = true; +} + + +/** Call this every test */ +void TestGestureManager::Initialize() +{ + mFunctionsCalled.Reset(); +} + +bool TestGestureManager::WasCalled(TestFuncEnum func) +{ + switch(func) + { + case RegisterType: return mFunctionsCalled.Register; + case UnregisterType: return mFunctionsCalled.Unregister; + case UpdateType: return mFunctionsCalled.Update; + } + return false; +} + +void TestGestureManager::ResetCallStatistics(TestFuncEnum func) +{ + switch(func) + { + case RegisterType: mFunctionsCalled.Register = false; break; + case UnregisterType: mFunctionsCalled.Unregister = false; break; + case UpdateType: mFunctionsCalled.Update = false; break; + } +} + +TestGestureManager::TestFunctions::TestFunctions() +: Register(false), + Unregister(false), + Update(false) +{ +} + +void TestGestureManager::TestFunctions::Reset() +{ + Register = false; + Unregister = false; + Update = false; +} + + + +} // namespace Dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.h b/automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.h new file mode 100644 index 0000000..4c0b766 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.h @@ -0,0 +1,93 @@ +#ifndef __DALI_TEST_GESTURE_MANAGER_H__ +#define __DALI_TEST_GESTURE_MANAGER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +/** + * Concrete implementation of the gesture manager class. + */ +class DALI_IMPORT_API TestGestureManager : public Dali::Integration::GestureManager +{ + +public: + + /** + * Constructor + */ + TestGestureManager(); + + /** + * Destructor + */ + virtual ~TestGestureManager(); + + /** + * @copydoc Dali::Integration::GestureManager::Register(Gesture::Type) + */ + virtual void Register(const Integration::GestureRequest& request); + + /** + * @copydoc Dali::Integration::GestureManager::Unregister(Gesture::Type) + */ + virtual void Unregister(const Integration::GestureRequest& request); + + /** + * @copydoc Dali::Integration::GestureManager::Update(Gesture::Type) + */ + virtual void Update(const Integration::GestureRequest& request); + +public: // TEST FUNCTIONS + + // Enumeration of Gesture Manager methods + enum TestFuncEnum + { + RegisterType, + UnregisterType, + UpdateType, + }; + + /** Call this every test */ + void Initialize(); + bool WasCalled(TestFuncEnum func); + void ResetCallStatistics(TestFuncEnum func); + +private: + + struct TestFunctions + { + TestFunctions(); + void Reset(); + + bool Register; + bool Unregister; + bool Update; + }; + + TestFunctions mFunctionsCalled; +}; + +} // Dali + +#endif // __DALI_TEST_GESTURE_MANAGER_H__ diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.cpp new file mode 100644 index 0000000..d8af042 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test-gl-abstraction.h" + +namespace Dali +{ + +TestGlAbstraction::TestGlAbstraction() +{ + Initialize(); +} + +TestGlAbstraction::~TestGlAbstraction() {} + +void TestGlAbstraction::Initialize() +{ + mCurrentProgram = 0; + mCompileStatus = GL_TRUE; + mLinkStatus = GL_TRUE; + + mGetAttribLocationResult = 0; + mGetErrorResult = 0; + mGetStringResult = NULL; + mIsBufferResult = 0; + mIsEnabledResult = 0; + mIsFramebufferResult = 0; + mIsProgramResult = 0; + mIsRenderbufferResult = 0; + mIsShaderResult = 0; + mIsTextureResult = 0; + mVertexAttribArrayChanged = false; + + mCheckFramebufferStatusResult = 0; + mFramebufferStatus = 0; + mFramebufferColorAttached = 0; + mFramebufferDepthAttached = 0; + mFramebufferStencilAttached = 0; + + mNumBinaryFormats = 0; + mBinaryFormats = 0; + mProgramBinaryLength = 0; + mGetProgramBinaryCalled = false; + + mLastAutoTextureIdUsed = 0; + + mLastShaderIdUsed = 0; + mLastProgramIdUsed = 0; + mLastUniformIdUsed = 0; + mLastShaderCompiled = 0; + mLastClearBitMask = 0; + mClearCount = 0; + + mLastBlendEquationRgb = 0; + mLastBlendEquationAlpha = 0; + mLastBlendFuncSrcRgb = 0; + mLastBlendFuncDstRgb = 0; + mLastBlendFuncSrcAlpha = 0; + mLastBlendFuncDstAlpha = 0; + + mUniforms.clear(); + mProgramUniforms1i.clear(); + mProgramUniforms1f.clear(); + mProgramUniforms2f.clear(); + mProgramUniforms3f.clear(); + mProgramUniforms4f.clear(); +} + +void TestGlAbstraction::PreRender() +{ +} + +void TestGlAbstraction::PostRender() +{ +} + +} // Namespace dali + +bool BlendEnabled(const Dali::TraceCallStack& callStack) +{ + std::stringstream out; + out << GL_BLEND; + bool blendEnabled = callStack.FindMethodAndParams("Enable", out.str()); + return blendEnabled; +} + +bool BlendDisabled(const Dali::TraceCallStack& callStack) +{ + std::stringstream out; + out << GL_BLEND; + bool blendEnabled = callStack.FindMethodAndParams("Disable", out.str()); + return blendEnabled; +} diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h b/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h new file mode 100644 index 0000000..51df9ce --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h @@ -0,0 +1,1999 @@ +#ifndef __TEST_GL_ABSTRACTION_H__ +#define __TEST_GL_ABSTRACTION_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include // for strcmp + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include "test-trace-call-stack.h" + +namespace Dali +{ + +static const unsigned int MAX_ATTRIBUTE_CACHE_SIZE = 64; +static const char *mStdAttribs[MAX_ATTRIBUTE_CACHE_SIZE] = +{ + "aPosition", // ATTRIB_POSITION + "aNormal", // ATTRIB_NORMAL + "aTexCoord", // ATTRIB_TEXCOORD + "aColor", // ATTRIB_COLOR + "aBoneWeights", // ATTRIB_BONE_WEIGHTS + "aBoneIndices" // ATTRIB_BONE_INDICES +}; + +class DALI_IMPORT_API TestGlAbstraction: public Dali::Integration::GlAbstraction +{ +public: + TestGlAbstraction(); + ~TestGlAbstraction(); + void Initialize(); + + void PreRender(); + void PostRender(); + + /* OpenGL ES 2.0 */ + + inline void ActiveTexture( GLenum textureUnit ) + { + mActiveTextureUnit = textureUnit - GL_TEXTURE0; + } + + inline GLenum GetActiveTextureUnit() const + { + return mActiveTextureUnit + GL_TEXTURE0; + } + + inline void AttachShader( GLuint program, GLuint shader ) + { + std::stringstream out; + out << program << ", " << shader; + mShaderTrace.PushCall("AttachShader", out.str()); + } + + inline void BindAttribLocation( GLuint program, GLuint index, const char* name ) + { + } + + inline void BindBuffer( GLenum target, GLuint buffer ) + { + } + + inline void BindFramebuffer( GLenum target, GLuint framebuffer ) + { + //Add 010 bit; + mFramebufferStatus |= 2; + } + + inline void BindRenderbuffer( GLenum target, GLuint renderbuffer ) + { + } + + /** + * This method can be used by test cases, to query the texture IDs that have been bound by BindTexture. + * @return A vector containing the IDs that were bound. + */ + inline const std::vector& GetBoundTextures() const + { + return mBoundTextures; + } + + /** + * Query the texture IDs that have been bound with BindTexture, with a specific active texture unit. + * @param[in] activeTextureUnit The specific active texture unit. + * @return A vector containing the IDs that were bound. + */ + inline const std::vector& GetBoundTextures( GLuint activeTextureUnit ) const + { + return mActiveTextures[ activeTextureUnit - GL_TEXTURE0 ].mBoundTextures; + } + + /** + * This method can be used by test cases, to clear the record of texture IDs that have been bound by BindTexture. + */ + inline void ClearBoundTextures() + { + mBoundTextures.clear(); + + for( unsigned int i=0; i::iterator iter=mDeletedTextureIds.begin(); iter != mDeletedTextureIds.end(); ++iter) + { + if(*iter == textureId) + { + found = true; + break; + } + } + return found; + } + + inline void ClearDeletedTextures() + { + mDeletedTextureIds.clear(); + } + + inline void DepthFunc(GLenum func) + { + } + + inline void DepthMask(GLboolean flag) + { + } + + inline void DepthRangef(GLclampf zNear, GLclampf zFar) + { + } + + inline void DetachShader(GLuint program, GLuint shader) + { + std::stringstream out; + out << program << ", " << shader; + mShaderTrace.PushCall("DetachShader", out.str()); + } + + inline void Disable(GLenum cap) + { + std::stringstream out; + out << cap; + mCullFaceTrace.PushCall("Disable", out.str()); + } + + inline void DisableVertexAttribArray(GLuint index) + { + SetVertexAttribArray( index, false ); + } + + inline void DrawArrays(GLenum mode, GLint first, GLsizei count) + { + std::stringstream out; + out << mode << ", " << first << ", " << count; + mDrawTrace.PushCall("DrawArrays", out.str()); + } + + inline void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) + { + std::stringstream out; + out << mode << ", " << count << ", " << type << ", indices"; + mDrawTrace.PushCall("DrawElements", out.str()); + } + + inline void Enable(GLenum cap) + { + std::stringstream out; + out << cap; + mCullFaceTrace.PushCall("Enable", out.str()); + } + + inline void EnableVertexAttribArray(GLuint index) + { + SetVertexAttribArray( index, true); + } + + inline void Finish(void) + { + } + + inline void Flush(void) + { + } + + inline void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) + { + if (attachment == GL_DEPTH_ATTACHMENT) + { + mFramebufferDepthAttached = true; + } + else if (attachment == GL_STENCIL_ATTACHMENT) + { + mFramebufferStencilAttached = true; + } + } + + inline void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) + { + //Add 100 bit; + mFramebufferStatus |= 4; + + //We check 4 attachment colors + if ((attachment == GL_COLOR_ATTACHMENT0) || (attachment == GL_COLOR_ATTACHMENT1) || (attachment == GL_COLOR_ATTACHMENT2) || (attachment == GL_COLOR_ATTACHMENT4)) + { + mFramebufferColorAttached = true; + } + } + + inline void FrontFace(GLenum mode) + { + } + + inline void GenBuffers(GLsizei n, GLuint* buffers) + { + // avoids an assert in GpuBuffers + *buffers = 1u; + } + + inline void GenerateMipmap(GLenum target) + { + } + + inline void GenFramebuffers(GLsizei n, GLuint* framebuffers) + { + for( int i = 0; i < n; i++ ) + { + framebuffers[i] = i + 1; + } + + //Add 001 bit, this function needs to be called the first one in the chain + mFramebufferStatus = 1; + } + + inline void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) + { + for( int i = 0; i < n; i++ ) + { + renderbuffers[i] = i + 1; + } + } + + /** + * This method can be used by test cases, to manipulate the texture IDs generated by GenTextures. + * @param[in] ids A vector containing the next IDs to be generated + */ + inline void SetNextTextureIds( const std::vector& ids ) + { + mNextTextureIds = ids; + } + + inline const std::vector& GetNextTextureIds() + { + return mNextTextureIds; + } + + inline void GenTextures(GLsizei n, GLuint* textures) + { + for( int i=0; isecond; + UniformIDMap::iterator it2 = uniformIDs.find( name ); + if( it2 == uniformIDs.end() ) + { + // Uniform not found, so add it... + uniformIDs[name] = ++mLastUniformIdUsed; + return mLastUniformIdUsed; + } + + return it2->second; + } + + inline void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) + { + } + + inline void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) + { + } + + inline void GetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) + { + } + + inline void Hint(GLenum target, GLenum mode) + { + } + + inline GLboolean IsBuffer(GLuint buffer) + { + return mIsBufferResult; + } + + inline GLboolean IsEnabled(GLenum cap) + { + return mIsEnabledResult; + } + + inline GLboolean IsFramebuffer(GLuint framebuffer) + { + return mIsFramebufferResult; + } + + inline GLboolean IsProgram(GLuint program) + { + return mIsProgramResult; + } + + inline GLboolean IsRenderbuffer(GLuint renderbuffer) + { + return mIsRenderbufferResult; + } + + inline GLboolean IsShader(GLuint shader) + { + return mIsShaderResult; + } + + inline GLboolean IsTexture(GLuint texture) + { + return mIsTextureResult; + } + + inline void LineWidth(GLfloat width) + { + } + + inline void LinkProgram(GLuint program) + { + std::stringstream out; + out << program; + mShaderTrace.PushCall("LinkProgram", out.str()); + } + + inline void PixelStorei(GLenum pname, GLint param) + { + } + + inline void PolygonOffset(GLfloat factor, GLfloat units) + { + } + + inline void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) + { + } + + inline void ReleaseShaderCompiler(void) + { + } + + inline void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) + { + } + + inline void SampleCoverage(GLclampf value, GLboolean invert) + { + } + + inline void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) + { + mScissorParams.x = x; + mScissorParams.y = y; + mScissorParams.width = width; + mScissorParams.height = height; + } + + inline void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length) + { + } + + inline void ShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length) + { + std::string stringBuilder; + for(int i = 0; i < count; ++i) + { + stringBuilder += string[i]; + } + mShaderSources[shader] = stringBuilder; + mLastShaderCompiled = shader; + } + + inline void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) + { + const std::string shaderSource = mShaderSources[shader]; + if( static_cast(shaderSource.length()) < bufsize ) + { + strcpy(source, shaderSource.c_str()); + *length = shaderSource.length(); + } + else + { + *length = bufsize -1; + strncpy(source, shaderSource.c_str(), *length); + source[*length] = 0x0; + } + } + + inline std::string GetShaderSource(GLuint shader) + { + return mShaderSources[shader]; + } + + inline void StencilFunc(GLenum func, GLint ref, GLuint mask) + { + } + + inline void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) + { + } + + inline void StencilMask(GLuint mask) + { + } + + inline void StencilMaskSeparate(GLenum face, GLuint mask) + { + } + + inline void StencilOp(GLenum fail, GLenum zfail, GLenum zpass) + { + } + + inline void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) + { + } + + inline void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) + { + std::stringstream out; + out << width << ", " << height; + mTextureTrace.PushCall("TexImage2D", out.str()); + } + + inline void TexParameterf(GLenum target, GLenum pname, GLfloat param) + { + std::stringstream out; + out << target << ", " << pname << ", " << param; + mTexParamaterTrace.PushCall("TexParameterf", out.str()); + } + + inline void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params) + { + std::stringstream out; + out << target << ", " << pname << ", " << params[0]; + mTexParamaterTrace.PushCall("TexParameterfv", out.str()); + } + + inline void TexParameteri(GLenum target, GLenum pname, GLint param) + { + std::stringstream out; + out << target << ", " << pname << ", " << param; + mTexParamaterTrace.PushCall("TexParameteri", out.str()); + } + + inline void TexParameteriv(GLenum target, GLenum pname, const GLint* params) + { + std::stringstream out; + out << target << ", " << pname << ", " << params[0]; + mTexParamaterTrace.PushCall("TexParameteriv", out.str()); + } + + inline void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) + { + std::stringstream out; + out << xoffset << ", " << yoffset << ", " << width << ", " << height; + mTextureTrace.PushCall("TexSubImage2D", out.str()); + } + + inline void Uniform1f(GLint location, GLfloat x) + { + if( ! mProgramUniforms1f.SetUniformValue( mCurrentProgram, location, x ) ) + { + mGetErrorResult = GL_INVALID_OPERATION; + } + } + + inline void Uniform1fv(GLint location, GLsizei count, const GLfloat* v) + { + for( int i = 0; i < count; ++i ) + { + if( ! mProgramUniforms1f.SetUniformValue( mCurrentProgram, location, v[i] ) ) + { + mGetErrorResult = GL_INVALID_OPERATION; + break; + } + } + } + + inline void Uniform1i(GLint location, GLint x) + { + if( ! mProgramUniforms1i.SetUniformValue( mCurrentProgram, location, x ) ) + { + mGetErrorResult = GL_INVALID_OPERATION; + } + } + + inline void Uniform1iv(GLint location, GLsizei count, const GLint* v) + { + for( int i = 0; i < count; ++i ) + { + if( ! mProgramUniforms1i.SetUniformValue( mCurrentProgram, + location, + v[i] ) ) + { + mGetErrorResult = GL_INVALID_OPERATION; + break; + } + } + } + + inline void Uniform2f(GLint location, GLfloat x, GLfloat y) + { + if( ! mProgramUniforms2f.SetUniformValue( mCurrentProgram, + location, + Vector2( x, y ) ) ) + { + mGetErrorResult = GL_INVALID_OPERATION; + } + } + + inline void Uniform2fv(GLint location, GLsizei count, const GLfloat* v) + { + for( int i = 0; i < count; ++i ) + { + if( ! mProgramUniforms2f.SetUniformValue( mCurrentProgram, + location, + Vector2( v[2*i], v[2*i+1] ) ) ) + { + mGetErrorResult = GL_INVALID_OPERATION; + break; + } + } + } + + inline void Uniform2i(GLint location, GLint x, GLint y) + { + } + + inline void Uniform2iv(GLint location, GLsizei count, const GLint* v) + { + } + + inline void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) + { + if( ! mProgramUniforms3f.SetUniformValue( mCurrentProgram, + location, + Vector3( x, y, z ) ) ) + { + mGetErrorResult = GL_INVALID_OPERATION; + } + } + + inline void Uniform3fv(GLint location, GLsizei count, const GLfloat* v) + { + for( int i = 0; i < count; ++i ) + { + if( ! mProgramUniforms3f.SetUniformValue( + mCurrentProgram, + location, + Vector3( v[3*i], v[3*i+1], v[3*i+2] ) ) ) + { + mGetErrorResult = GL_INVALID_OPERATION; + break; + } + } + } + + inline void Uniform3i(GLint location, GLint x, GLint y, GLint z) + { + } + + inline void Uniform3iv(GLint location, GLsizei count, const GLint* v) + { + } + + inline void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) + { + if( ! mProgramUniforms4f.SetUniformValue( mCurrentProgram, + location, + Vector4( x, y, z, w ) ) ) + { + mGetErrorResult = GL_INVALID_OPERATION; + } + } + + inline void Uniform4fv(GLint location, GLsizei count, const GLfloat* v) + { + for( int i = 0; i < count; ++i ) + { + if( ! mProgramUniforms4f.SetUniformValue( + mCurrentProgram, + location, + Vector4( v[4*i], v[4*i+1], v[4*i+2], v[4*i+3] ) ) ) + { + mGetErrorResult = GL_INVALID_OPERATION; + break; + } + } + } + + inline void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) + { + } + + inline void Uniform4iv(GLint location, GLsizei count, const GLint* v) + { + } + + inline void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + { + } + + inline void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + { + for( int i = 0; i < count; ++i ) + { + if( ! mProgramUniformsMat3.SetUniformValue( + mCurrentProgram, + location, + Matrix3( value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7], value[8] ) ) ) + { + mGetErrorResult = GL_INVALID_OPERATION; + break; + } + } + } + + inline void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + { + for( int i = 0; i < count; ++i ) + { + if( ! mProgramUniformsMat4.SetUniformValue( + mCurrentProgram, + location, + Matrix( value ) ) ) + { + mGetErrorResult = GL_INVALID_OPERATION; + break; + } + } + } + + inline void UseProgram(GLuint program) + { + mCurrentProgram = program; + } + + inline void ValidateProgram(GLuint program) + { + } + + inline void VertexAttrib1f(GLuint indx, GLfloat x) + { + } + + inline void VertexAttrib1fv(GLuint indx, const GLfloat* values) + { + } + + inline void VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) + { + } + + inline void VertexAttrib2fv(GLuint indx, const GLfloat* values) + { + } + + inline void VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) + { + } + + inline void VertexAttrib3fv(GLuint indx, const GLfloat* values) + { + } + + inline void VertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) + { + } + + inline void VertexAttrib4fv(GLuint indx, const GLfloat* values) + { + } + + inline void VertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) + { + } + + inline void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) + { + } + + /* OpenGL ES 3.0 */ + + inline void ReadBuffer(GLenum mode) + { + } + + inline void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices) + { + } + + inline void TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) + { + } + + inline void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) + { + } + + inline void CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) + { + } + + inline void CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) + { + } + + inline void CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) + { + } + + inline void GenQueries(GLsizei n, GLuint* ids) + { + } + + inline void DeleteQueries(GLsizei n, const GLuint* ids) + { + } + + inline GLboolean IsQuery(GLuint id) + { + return false; + } + + inline void BeginQuery(GLenum target, GLuint id) + { + } + + inline void EndQuery(GLenum target) + { + } + + inline void GetQueryiv(GLenum target, GLenum pname, GLint* params) + { + } + + inline void GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) + { + } + + inline GLboolean UnmapBuffer(GLenum target) + { + return false; + } + + inline void GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) + { + } + + inline void DrawBuffers(GLsizei n, const GLenum* bufs) + { + } + + inline void UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + { + } + + inline void UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + { + } + + inline void UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + { + } + + inline void UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + { + } + + inline void UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + { + } + + inline void UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) + { + } + + inline void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) + { + } + + inline void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) + { + } + + inline void FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) + { + } + + inline GLvoid* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) + { + return NULL; + } + + inline void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) + { + } + + inline void BindVertexArray(GLuint array) + { + } + + inline void DeleteVertexArrays(GLsizei n, const GLuint* arrays) + { + } + + inline void GenVertexArrays(GLsizei n, GLuint* arrays) + { + } + + inline GLboolean IsVertexArray(GLuint array) + { + return false; + } + + inline void GetIntegeri_v(GLenum target, GLuint index, GLint* data) + { + } + + inline void BeginTransformFeedback(GLenum primitiveMode) + { + } + + inline void EndTransformFeedback(void) + { + } + + inline void BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) + { + } + + inline void BindBufferBase(GLenum target, GLuint index, GLuint buffer) + { + } + + inline void TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) + { + } + + inline void GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) + { + } + + inline void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) + { + } + + inline void GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) + { + } + + inline void GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) + { + } + + inline void VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) + { + } + + inline void VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) + { + } + + inline void VertexAttribI4iv(GLuint index, const GLint* v) + { + } + + inline void VertexAttribI4uiv(GLuint index, const GLuint* v) + { + } + + inline void GetUniformuiv(GLuint program, GLint location, GLuint* params) + { + } + + inline GLint GetFragDataLocation(GLuint program, const GLchar *name) + { + return -1; + } + + inline void Uniform1ui(GLint location, GLuint v0) + { + } + + inline void Uniform2ui(GLint location, GLuint v0, GLuint v1) + { + } + + inline void Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) + { + } + + inline void Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) + { + } + + inline void Uniform1uiv(GLint location, GLsizei count, const GLuint* value) + { + } + + inline void Uniform2uiv(GLint location, GLsizei count, const GLuint* value) + { + } + + inline void Uniform3uiv(GLint location, GLsizei count, const GLuint* value) + { + } + + inline void Uniform4uiv(GLint location, GLsizei count, const GLuint* value) + { + } + + inline void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) + { + } + + inline void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) + { + } + + inline void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) + { + } + + inline void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) + { + } + + inline const GLubyte* GetStringi(GLenum name, GLuint index) + { + return NULL; + } + + inline void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) + { + } + + inline void GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) + { + } + + inline void GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) + { + } + + inline GLuint GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) + { + return GL_INVALID_INDEX; + } + + inline void GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) + { + } + + inline void GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) + { + } + + inline void UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) + { + } + + inline void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) + { + } + + inline void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) + { + } + + inline GLsync FenceSync(GLenum condition, GLbitfield flags) + { + return NULL; + } + + inline GLboolean IsSync(GLsync sync) + { + return false; + } + + inline void DeleteSync(GLsync sync) + { + } + + inline GLenum ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) + { + return 0; + } + + inline void WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) + { + } + + inline void GetInteger64v(GLenum pname, GLint64* params) + { + } + + inline void GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) + { + } + + inline void GetInteger64i_v(GLenum target, GLuint index, GLint64* data) + { + } + + inline void GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) + { + } + + inline void GenSamplers(GLsizei count, GLuint* samplers) + { + } + + inline void DeleteSamplers(GLsizei count, const GLuint* samplers) + { + } + + inline GLboolean IsSampler(GLuint sampler) + { + return false; + } + + inline void BindSampler(GLuint unit, GLuint sampler) + { + } + + inline void SamplerParameteri(GLuint sampler, GLenum pname, GLint param) + { + } + + inline void SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) + { + } + + inline void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) + { + } + + inline void SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) + { + } + + inline void GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) + { + } + + inline void GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) + { + } + + inline void VertexAttribDivisor(GLuint index, GLuint divisor) + { + } + + inline void BindTransformFeedback(GLenum target, GLuint id) + { + } + + inline void DeleteTransformFeedbacks(GLsizei n, const GLuint* ids) + { + } + + inline void GenTransformFeedbacks(GLsizei n, GLuint* ids) + { + } + + inline GLboolean IsTransformFeedback(GLuint id) + { + return false; + } + + inline void PauseTransformFeedback(void) + { + } + + inline void ResumeTransformFeedback(void) + { + } + + inline void GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) + { + mGetProgramBinaryCalled = true; + } + + inline void ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) + { + } + + inline void ProgramParameteri(GLuint program, GLenum pname, GLint value) + { + } + + inline void InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) + { + } + + inline void InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) + { + } + + inline void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) + { + } + + inline void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) + { + } + + inline void GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) + { + } + +public: // TEST FUNCTIONS + inline void SetCompileStatus( GLuint value ) { mCompileStatus = value; } + inline void SetLinkStatus( GLuint value ) { mLinkStatus = value; } + inline void SetGetAttribLocationResult( int result) { mGetAttribLocationResult = result; } + inline void SetGetErrorResult( GLenum result) { mGetErrorResult = result; } + inline void SetGetStringResult( GLubyte* result) { mGetStringResult = result; } + inline void SetIsBufferResult( GLboolean result) { mIsBufferResult = result; } + inline void SetIsEnabledResult( GLboolean result) { mIsEnabledResult = result; } + inline void SetIsFramebufferResult( GLboolean result) { mIsFramebufferResult = result; } + inline void SetIsProgramResult( GLboolean result) { mIsProgramResult = result; } + inline void SetIsRenderbufferResult( GLboolean result) { mIsRenderbufferResult = result; } + inline void SetIsShaderResult( GLboolean result) { mIsShaderResult = result; } + inline void SetIsTextureResult( GLboolean result) { mIsTextureResult = result; } + inline void SetCheckFramebufferStatusResult( GLenum result) { mCheckFramebufferStatusResult = result; } + inline void SetNumBinaryFormats( GLint numFormats ) { mNumBinaryFormats = numFormats; } + inline void SetBinaryFormats( GLint binaryFormats ) { mBinaryFormats = binaryFormats; } + inline void SetProgramBinaryLength( GLint length ) { mProgramBinaryLength = length; } + + inline bool GetVertexAttribArrayState(GLuint index) + { + if( index >= MAX_ATTRIBUTE_CACHE_SIZE ) + { + // out of range + return false; + } + return mVertexAttribArrayState[ index ]; + } + inline void ClearVertexAttribArrayChanged() { mVertexAttribArrayChanged = false; } + inline bool GetVertexAttribArrayChanged() { return mVertexAttribArrayChanged; } + + //Methods for CullFace verification + inline void EnableCullFaceCallTrace(bool enable) { mCullFaceTrace.Enable(enable); } + inline void ResetCullFaceCallStack() { mCullFaceTrace.Reset(); } + inline TraceCallStack& GetCullFaceTrace() { return mCullFaceTrace; } + + //Methods for Shader verification + inline void EnableShaderCallTrace(bool enable) { mShaderTrace.Enable(enable); } + inline void ResetShaderCallStack() { mShaderTrace.Reset(); } + inline TraceCallStack& GetShaderTrace() { return mShaderTrace; } + + //Methods for Texture verification + inline void EnableTextureCallTrace(bool enable) { mTextureTrace.Enable(enable); } + inline void ResetTextureCallStack() { mTextureTrace.Reset(); } + inline TraceCallStack& GetTextureTrace() { return mTextureTrace; } + + //Methods for Texture verification + inline void EnableTexParameterCallTrace(bool enable) { mTexParamaterTrace.Enable(enable); } + inline void ResetTexParameterCallStack() { mTexParamaterTrace.Reset(); } + inline TraceCallStack& GetTexParameterTrace() { return mTexParamaterTrace; } + + //Methods for Draw verification + inline void EnableDrawCallTrace(bool enable) { mDrawTrace.Enable(enable); } + inline void ResetDrawCallStack() { mDrawTrace.Reset(); } + inline TraceCallStack& GetDrawTrace() { return mDrawTrace; } + + template + inline bool GetUniformValue( const char* name, T& value ) const + { + for( ProgramUniformMap::const_iterator program_it = mUniforms.begin(); + program_it != mUniforms.end(); + ++program_it ) + { + const UniformIDMap &uniformIDs = program_it->second; + + UniformIDMap::const_iterator uniform_it = uniformIDs.find( name ); + if( uniform_it != uniformIDs.end() ) + { + // found one matching uniform name, lets check the value... + GLuint programId = program_it->first; + GLint uniformId = uniform_it->second; + + const ProgramUniformValue &mProgramUniforms = GetProgramUniformsForType( value ); + return mProgramUniforms.GetUniformValue( programId, uniformId, value ); + } + } + return false; + } + + + template + inline bool CheckUniformValue( const char* name, const T& value ) const + { + for( ProgramUniformMap::const_iterator program_it = mUniforms.begin(); + program_it != mUniforms.end(); + ++program_it ) + { + const UniformIDMap &uniformIDs = program_it->second; + + UniformIDMap::const_iterator uniform_it = uniformIDs.find( name ); + if( uniform_it != uniformIDs.end() ) + { + // found one matching uniform name, lets check the value... + GLuint programId = program_it->first; + GLint uniformId = uniform_it->second; + + const ProgramUniformValue &mProgramUniforms = GetProgramUniformsForType( value ); + if( mProgramUniforms.CheckUniformValue( programId, uniformId, value ) ) + { + // the value matches + return true; + } + } + } + + fprintf(stderr, "Not found, printing possible values:\n" ); + for( ProgramUniformMap::const_iterator program_it = mUniforms.begin(); + program_it != mUniforms.end(); + ++program_it ) + { + const UniformIDMap &uniformIDs = program_it->second; + + UniformIDMap::const_iterator uniform_it = uniformIDs.find( name ); + if( uniform_it != uniformIDs.end() ) + { + // found one matching uniform name, lets check the value... + GLuint programId = program_it->first; + GLint uniformId = uniform_it->second; + + const ProgramUniformValue &mProgramUniforms = GetProgramUniformsForType( value ); + T origValue; + if ( mProgramUniforms.GetUniformValue(programId, uniformId, origValue) ) + { + std::stringstream out; + out << uniform_it->first << ": " << origValue; + fprintf(stderr, "%s\n", out.str().c_str() ); + } + } + } + return false; + } + + template + inline bool GetUniformValue( GLuint programId, GLuint uniformId, T& outValue) const + { + const ProgramUniformValue &mProgramUniforms = GetProgramUniformsForType( outValue ); + return mProgramUniforms.GetUniformValue( programId, uniformId, outValue ); + } + + inline bool GetUniformIds( const char* name, GLuint& programId, GLuint& uniformId ) const + { + for( ProgramUniformMap::const_iterator program_it = mUniforms.begin(); + program_it != mUniforms.end(); + ++program_it ) + { + const UniformIDMap &uniformIDs = program_it->second; + + UniformIDMap::const_iterator uniform_it = uniformIDs.find( name ); + if( uniform_it != uniformIDs.end() ) + { + programId = program_it->first; + uniformId = uniform_it->second; + return true; + } + } + return false; + } + + inline GLuint GetLastShaderCompiled() const + { + return mLastShaderCompiled; + } + + inline GLuint GetLastProgramCreated() const + { + return mLastProgramIdUsed; + } + + inline GLbitfield GetLastClearMask() const + { + return mLastClearBitMask; + } + + enum AttribType + { + ATTRIB_UNKNOWN = -1, + ATTRIB_POSITION, + ATTRIB_NORMAL, + ATTRIB_TEXCOORD, + ATTRIB_COLOR, + ATTRIB_BONE_WEIGHTS, + ATTRIB_BONE_INDICES, + ATTRIB_TYPE_LAST + }; + + struct ScissorParams + { + GLint x; + GLint y; + GLsizei width; + GLsizei height; + + ScissorParams() : x( 0 ), y( 0 ), width( 0 ), height( 0 ) { } + }; + + // Methods to check scissor tests + inline const ScissorParams& GetScissorParams() const { return mScissorParams; } + + inline bool GetProgramBinaryCalled() const { return mGetProgramBinaryCalled; } + + inline unsigned int GetClearCountCalled() const { return mClearCount; } + + typedef std::vector BufferDataCalls; + inline const BufferDataCalls& GetBufferDataCalls() const { return mBufferDataCalls; } + inline void ResetBufferDataCalls() { mBufferDataCalls.clear(); } + + typedef std::vector BufferSubDataCalls; + inline const BufferSubDataCalls& GetBufferSubDataCalls() const { return mBufferSubDataCalls; } + inline void ResetBufferSubDataCalls() { mBufferSubDataCalls.clear(); } + +private: + GLuint mCurrentProgram; + GLuint mCompileStatus; + BufferDataCalls mBufferDataCalls; + BufferSubDataCalls mBufferSubDataCalls; + GLuint mLinkStatus; + GLint mGetAttribLocationResult; + GLenum mGetErrorResult; + GLubyte* mGetStringResult; + GLboolean mIsBufferResult; + GLboolean mIsEnabledResult; + GLboolean mIsFramebufferResult; + GLboolean mIsProgramResult; + GLboolean mIsRenderbufferResult; + GLboolean mIsShaderResult; + GLboolean mIsTextureResult; + GLenum mActiveTextureUnit; + GLenum mCheckFramebufferStatusResult; + GLint mFramebufferStatus; + GLenum mFramebufferColorAttached; + GLenum mFramebufferDepthAttached; + GLenum mFramebufferStencilAttached; + GLint mNumBinaryFormats; + GLint mBinaryFormats; + GLint mProgramBinaryLength; + bool mVertexAttribArrayState[MAX_ATTRIBUTE_CACHE_SIZE]; + bool mVertexAttribArrayChanged; // whether the vertex attrib array has been changed + bool mGetProgramBinaryCalled; + typedef std::map< GLuint, std::string> ShaderSourceMap; + ShaderSourceMap mShaderSources; + GLuint mLastShaderCompiled; + GLbitfield mLastClearBitMask; + unsigned int mClearCount; + + Vector4 mLastBlendColor; + GLenum mLastBlendEquationRgb; + GLenum mLastBlendEquationAlpha; + GLenum mLastBlendFuncSrcRgb; + GLenum mLastBlendFuncDstRgb; + GLenum mLastBlendFuncSrcAlpha; + GLenum mLastBlendFuncDstAlpha; + + // Data for manipulating the IDs returned by GenTextures + GLuint mLastAutoTextureIdUsed; + std::vector mNextTextureIds; + std::vector mDeletedTextureIds; + std::vector mBoundTextures; + + struct ActiveTextureType + { + std::vector mBoundTextures; + }; + + ActiveTextureType mActiveTextures[ MIN_TEXTURE_UNIT_LIMIT ]; + + TraceCallStack mCullFaceTrace; + TraceCallStack mShaderTrace; + TraceCallStack mTextureTrace; + TraceCallStack mTexParamaterTrace; + TraceCallStack mDrawTrace; + + // Shaders & Uniforms + GLuint mLastShaderIdUsed; + GLuint mLastProgramIdUsed; + GLuint mLastUniformIdUsed; + typedef std::map< std::string, GLint > UniformIDMap; + typedef std::map< GLuint, UniformIDMap > ProgramUniformMap; + ProgramUniformMap mUniforms; + + template + struct ProgramUniformValue : public std::map< GLuint, std::map< GLint, T > > + { + public: + typedef std::map< GLint, T > UniformValueMap; + typedef std::map< GLuint, UniformValueMap > Map; + + bool SetUniformValue( GLuint program, GLuint uniform, const T& value ) + { + if( program == 0 ) + { + return false; + } + + typename Map::iterator it = Map::find( program ); + if( it == Map::end() ) + { + // if its the first uniform for this program add it + std::pair< typename Map::iterator, bool > result = + Map::insert( typename Map::value_type( program, UniformValueMap() ) ); + it = result.first; + } + + UniformValueMap& uniforms = it->second; + uniforms[uniform] = value; + + return true; + } + + bool CheckUniformValue( GLuint program, GLuint uniform, const T& value ) const + { + T uniformValue; + if ( GetUniformValue( program, uniform, uniformValue ) ) + { + return value == uniformValue; + } + + return false; + } + + bool GetUniformValue( GLuint program, GLuint uniform, T& value ) const + { + if( program == 0 ) + { + return false; + } + + typename Map::const_iterator it = Map::find( program ); + if( it == Map::end() ) + { + // Uniform values always initialised as 0 + value = GetZero(); + return true; + } + + const UniformValueMap& uniforms = it->second; + typename UniformValueMap::const_iterator it2 = uniforms.find( uniform ); + if( it2 == uniforms.end() ) + { + // Uniform values always initialised as 0 + value = GetZero(); + return true; + } + value = it2->second; + + return true; + } + + T GetZero() const; + }; + ProgramUniformValue mProgramUniforms1i; + ProgramUniformValue mProgramUniforms1f; + ProgramUniformValue mProgramUniforms2f; + ProgramUniformValue mProgramUniforms3f; + ProgramUniformValue mProgramUniforms4f; + ProgramUniformValue mProgramUniformsMat4; + ProgramUniformValue mProgramUniformsMat3; + + inline const ProgramUniformValue& GetProgramUniformsForType( const int ) const + { + return mProgramUniforms1i; + } + inline const ProgramUniformValue& GetProgramUniformsForType( const float ) const + { + return mProgramUniforms1f; + } + inline const ProgramUniformValue& GetProgramUniformsForType( const Vector2& ) const + { + return mProgramUniforms2f; + } + inline const ProgramUniformValue& GetProgramUniformsForType( const Vector3& ) const + { + return mProgramUniforms3f; + } + inline const ProgramUniformValue& GetProgramUniformsForType( const Vector4& ) const + { + return mProgramUniforms4f; + } + inline const ProgramUniformValue& GetProgramUniformsForType( const Matrix& ) const + { + return mProgramUniformsMat4; + } + inline const ProgramUniformValue& GetProgramUniformsForType( const Matrix3& ) const + { + return mProgramUniformsMat3; + } + inline void SetVertexAttribArray(GLuint index, bool state) + { + if( index >= MAX_ATTRIBUTE_CACHE_SIZE ) + { + // out of range + return; + } + mVertexAttribArrayState[ index ] = state; + mVertexAttribArrayChanged = true; + } + + ScissorParams mScissorParams; +}; + +template <> +inline int TestGlAbstraction::ProgramUniformValue::GetZero() const +{ + return 0; +} + +template <> +inline float TestGlAbstraction::ProgramUniformValue::GetZero() const +{ + return 0.0f; +} + +template <> +inline Vector2 TestGlAbstraction::ProgramUniformValue::GetZero() const +{ + return Vector2::ZERO; +} + +template <> +inline Vector3 TestGlAbstraction::ProgramUniformValue::GetZero() const +{ + return Vector3::ZERO; +} + +template <> +inline Vector4 TestGlAbstraction::ProgramUniformValue::GetZero() const +{ + return Vector4::ZERO; +} + +template <> +inline Matrix TestGlAbstraction::ProgramUniformValue::GetZero() const +{ + return Matrix(); +} + +template <> +inline Matrix3 TestGlAbstraction::ProgramUniformValue::GetZero() const +{ + return Matrix3( Matrix() ); +} + +} // namespace Dali + +bool BlendEnabled(const Dali::TraceCallStack& callStack); +bool BlendDisabled(const Dali::TraceCallStack& callStack); + + + + +#endif // __TEST_GL_ES_H__ diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp new file mode 100644 index 0000000..533355c --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test-gl-sync-abstraction.h" + +namespace Dali +{ + +TestSyncObject::TestSyncObject(TraceCallStack& trace) +: synced(false), + mTrace(trace) +{ +} + +TestSyncObject::~TestSyncObject() +{ +} + +bool TestSyncObject::IsSynced() +{ + mTrace.PushCall("SyncObject::IsSynced", ""); // Trace the method + return synced; +} + + + +TestGlSyncAbstraction::TestGlSyncAbstraction() +{ + Initialize(); +} + +/** + * Destructor + */ +TestGlSyncAbstraction::~TestGlSyncAbstraction() +{ + for( SyncIter iter=mSyncObjects.begin(), end=mSyncObjects.end(); iter != end; ++iter ) + { + delete *iter; + } +} + +/** + * Initialize the sync objects - clear down the map + */ +void TestGlSyncAbstraction::Initialize() +{ + mSyncObjects.clear(); +} + +/** + * Create a sync object + * @return the sync object + */ +Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::CreateSyncObject( ) +{ + mTrace.PushCall("CreateSyncObject", ""); // Trace the method + + TestSyncObject* syncObject = new TestSyncObject(mTrace); + mSyncObjects.push_back( syncObject ); + return syncObject; +} + +/** + * Destroy a sync object + * @param[in] syncObject The object to destroy + */ +void TestGlSyncAbstraction::DestroySyncObject( Integration::GlSyncAbstraction::SyncObject* syncObject ) +{ + std::stringstream out; + out << syncObject; + mTrace.PushCall("DestroySyncObject", out.str()); // Trace the method + + for( SyncIter iter=mSyncObjects.begin(), end=mSyncObjects.end(); iter != end; ++iter ) + { + if( *iter == syncObject ) + { + delete *iter; + mSyncObjects.erase(iter); + break; + } + } +} + + +Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::GetLastSyncObject( ) +{ + if( !mSyncObjects.empty() ) + { + return mSyncObjects.back(); + } + return NULL; +} + +/** + * Test method to trigger the object sync behaviour. + * @param[in] + * @param[in] sync The sync value to set + */ +void TestGlSyncAbstraction::SetObjectSynced( Integration::GlSyncAbstraction::SyncObject* syncObject, bool sync ) +{ + TestSyncObject* testSyncObject = static_cast(syncObject); + testSyncObject->synced = sync; +} + +/** + * Turn trace on + */ +void TestGlSyncAbstraction::EnableTrace(bool enable) { mTrace.Enable(enable); } + +/** + * Reset the trace callstack + */ +void TestGlSyncAbstraction::ResetTrace() { mTrace.Reset(); } + +/** + * Get the trace object (allows test case to find methods on it) + */ +TraceCallStack& TestGlSyncAbstraction::GetTrace() { return mTrace; } + + +} // Dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.h b/automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.h new file mode 100644 index 0000000..e233176 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.h @@ -0,0 +1,112 @@ +#ifndef __TEST_GL_SYNC_ABSTRACTION_H__ +#define __TEST_GL_SYNC_ABSTRACTION_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include "test-trace-call-stack.h" + +namespace Dali +{ + +class DALI_IMPORT_API TestSyncObject : public Integration::GlSyncAbstraction::SyncObject +{ +public: + TestSyncObject(TraceCallStack& trace); + ~TestSyncObject(); + bool IsSynced(); + bool synced; + TraceCallStack& mTrace; +}; + +/** + * Class to emulate the GL sync functions with tracing + */ +class DALI_IMPORT_API TestGlSyncAbstraction: public Integration::GlSyncAbstraction +{ +public: + /** + * Constructor + */ + TestGlSyncAbstraction(); + + /** + * Destructor + */ + ~TestGlSyncAbstraction(); + + /** + * Initialize the sync objects - clear down the map + */ + void Initialize(); + + /** + * Create a sync object + * @return the sync object + */ + virtual Integration::GlSyncAbstraction::SyncObject* CreateSyncObject( ); + + /** + * Destroy a sync object + * @param[in] syncObject The object to destroy + */ + virtual void DestroySyncObject( Integration::GlSyncAbstraction::SyncObject* syncObject ); + + +public: // TEST FUNCTIONS + Integration::GlSyncAbstraction::SyncObject* GetLastSyncObject( ); + + /** + * Test method to trigger the object sync behaviour. + * @param[in] + * @param[in] sync The sync value to set + */ + void SetObjectSynced( Integration::GlSyncAbstraction::SyncObject* syncObject, bool sync ); + + /** + * Turn trace on + */ + void EnableTrace(bool enable); + + /** + * Reset the trace callstack + */ + void ResetTrace(); + + /** + * Get the trace object (allows test case to find methods on it) + */ + TraceCallStack& GetTrace(); + +private: + typedef std::vector SyncContainer; + typedef SyncContainer::iterator SyncIter; + SyncContainer mSyncObjects; ///< The sync objects + TraceCallStack mTrace; ///< the trace call stack for testing +}; + +} // Dali + +#endif // __TEST_GL_SYNC_ABSTRACTION_H__ diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-harness.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-harness.cpp new file mode 100644 index 0000000..55beebc --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-harness.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "test-harness.h" +#include +#include +#include +#include +#include +#include +#include +#include + +namespace TestHarness +{ + +typedef std::map RunningTestCases; + +namespace +{ +const char* RED_COLOR="\e[1;31m"; +const char* GREEN_COLOR="\e[1;32m"; +const char* ASCII_RESET="\e[0m"; +const char* ASCII_BOLD="\e[1m"; +} + + +int RunTestCase( struct ::testcase_s& testCase ) +{ + int result = EXIT_STATUS_TESTCASE_FAILED; + +// dont want to catch exception as we want to be able to get +// gdb stack trace from the first error +// by default tests should all always pass with no exceptions + if( testCase.startup ) + { + testCase.startup(); + } + result = testCase.function(); + if( testCase.cleanup ) + { + testCase.cleanup(); + } + + return result; +} + + +int RunTestCaseInChildProcess( struct ::testcase_s& testCase, bool suppressOutput ) +{ + int testResult = EXIT_STATUS_TESTCASE_FAILED; + + int pid = fork(); + if( pid == 0 ) // Child process + { + if( suppressOutput ) + { + close(STDOUT_FILENO); + close(STDERR_FILENO); + } + exit( RunTestCase( testCase ) ); + } + else if(pid == -1) + { + perror("fork"); + exit(EXIT_STATUS_FORK_FAILED); + } + else // Parent process + { + int status = 0; + int childPid = waitpid(-1, &status, 0); + if( childPid == -1 ) + { + perror("waitpid"); + exit(EXIT_STATUS_WAITPID_FAILED); + } + if( WIFEXITED(status) ) + { + if( childPid > 0 ) + { + testResult = WEXITSTATUS(status); + if( testResult ) + { + printf("Test case %s failed: %d\n", testCase.name, testResult); + } + } + } + else if(WIFSIGNALED(status) ) + { + testResult = EXIT_STATUS_TESTCASE_ABORTED; + +#ifdef WCOREDUMP + if(WCOREDUMP(status)) + { + printf("Test case %s failed: due to a crash\n", testCase.name); + } +#endif + printf("Test case %s failed: exit with signal %s\n", testCase.name, strsignal(WTERMSIG(status))); + } + else if(WIFSTOPPED(status)) + { + printf("Test case %s failed: stopped with signal %s\n", testCase.name, strsignal(WSTOPSIG(status))); + } + } + return testResult; +} + +void OutputStatistics( int numPasses, int numFailures ) +{ + const char* failureColor = GREEN_COLOR; + if( numFailures > 0 ) + { + failureColor = RED_COLOR; + } + printf("\rNumber of test passes: %s%4d (%5.2f%%)%s\n", ASCII_BOLD, numPasses, 100.0f * (float)numPasses / (numPasses+numFailures), ASCII_RESET); + printf("%sNumber of test failures:%s %s%4d%s\n", failureColor, ASCII_RESET, ASCII_BOLD, numFailures, ASCII_RESET); + +} + + +int RunAll(const char* processName, ::testcase tc_array[], bool reRunFailed) +{ + int numFailures = 0; + int numPasses = 0; + + // Run test cases in child process( to kill output/handle signals ), but run serially. + for( unsigned int i=0; tc_array[i].name; i++) + { + int result = RunTestCaseInChildProcess( tc_array[i], true ); + if( result == 0 ) + { + numPasses++; + } + else + { + numFailures++; + } + } + + OutputStatistics(numPasses, numFailures); + + return numFailures; +} + + + +// Constantly runs up to MAX_NUM_CHILDREN processes +int RunAllInParallel( const char* processName, ::testcase tc_array[], bool reRunFailed) +{ + int numFailures = 0; + int numPasses = 0; + + RunningTestCases children; + std::vector failedTestCases; + + // Fork up to MAX_NUM_CHILDREN processes, then + // wait. As soon as a proc completes, fork the next. + + int nextTestCase = 0; + int numRunningChildren = 0; + + while( tc_array[nextTestCase].name || numRunningChildren > 0) + { + // Create more children (up to the max number or til the end of the array) + while( numRunningChildren < MAX_NUM_CHILDREN && tc_array[nextTestCase].name ) + { + int pid = fork(); + if( pid == 0 ) // Child process + { + close(STDOUT_FILENO); + close(STDERR_FILENO); + exit( RunTestCase( tc_array[nextTestCase] ) ); + } + else if(pid == -1) + { + perror("fork"); + exit(EXIT_STATUS_FORK_FAILED); + } + else // Parent process + { + TestCase tc(nextTestCase, tc_array[nextTestCase].name); + children[pid] = tc; + nextTestCase++; + numRunningChildren++; + } + } + + // Wait for the next child to finish + + int status=0; + int childPid = waitpid(-1, &status, 0); + if( childPid == -1 ) + { + perror("waitpid"); + exit(EXIT_STATUS_WAITPID_FAILED); + } + + if( WIFEXITED(status) ) + { + if( childPid > 0 ) + { + int testResult = WEXITSTATUS(status); + if( testResult ) + { + printf("Test case %s failed: %d\n", children[childPid].testCaseName, testResult); + failedTestCases.push_back(children[childPid].testCase); + numFailures++; + } + else + { + numPasses++; + } + numRunningChildren--; + } + } + + else if( WIFSIGNALED(status) || WIFSTOPPED(status)) + { + status = WIFSIGNALED(status)?WTERMSIG(status):WSTOPSIG(status); + + if( childPid > 0 ) + { + RunningTestCases::iterator iter = children.find(childPid); + if( iter != children.end() ) + { + printf("Test case %s exited with signal %s\n", iter->second.testCaseName, strsignal(status)); + failedTestCases.push_back(iter->second.testCase); + } + else + { + printf("Unknown child process: %d signaled %s\n", childPid, strsignal(status)); + } + + numFailures++; + numRunningChildren--; + } + } + } + + OutputStatistics( numPasses, numFailures ); + + if( reRunFailed ) + { + for( unsigned int i=0; i\t\t Execute a test case\n" + " %s \t\t Execute all test cases in parallel\n" + " %s -r\t\t Execute all test cases in parallel, rerunning failed test cases\n", + program, program, program); +} + +} // namespace diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-harness.h b/automated-tests/src/dali/dali-test-suite-utils/test-harness.h new file mode 100644 index 0000000..e6dc517 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-harness.h @@ -0,0 +1,109 @@ +#ifndef TEST_HARNESS_H +#define TEST_HARNESS_H + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +namespace TestHarness +{ + +enum ExitStatus +{ + EXIT_STATUS_TESTCASE_SUCCEEDED, // 0 + EXIT_STATUS_TESTCASE_FAILED, // 1 + EXIT_STATUS_TESTCASE_ABORTED, // 2 + EXIT_STATUS_FORK_FAILED, // 3 + EXIT_STATUS_WAITPID_FAILED, // 4 + EXIT_STATUS_BAD_ARGUMENT, // 5 + EXIT_STATUS_TESTCASE_NOT_FOUND // 6 +}; + +const int MAX_NUM_CHILDREN(16); + +struct TestCase +{ + int testCase; + const char* testCaseName; + + TestCase() + : testCase(0), + testCaseName(NULL) + { + } + + TestCase(int tc, const char* name) + : testCase(tc), + testCaseName(name) + { + } + TestCase(const TestCase& rhs) + : testCase(rhs.testCase), + testCaseName(rhs.testCaseName) + { + } + TestCase& operator=(const TestCase& rhs) + { + testCase = rhs.testCase; + testCaseName = rhs.testCaseName; + return *this; + + } +}; + +/** + * Run a test case + * @param[in] testCase The Testkit-lite test case to run + */ +int RunTestCase( struct testcase_s& testCase ); + +/** + * Run all test cases in parallel + * @param[in] processName The name of this process + * @param[in] tc_array The array of auto-generated testkit-lite test cases + * @param[in] reRunFailed True if failed test cases should be re-run + * @return 0 on success + */ +int RunAllInParallel(const char* processName, testcase tc_array[], bool reRunFailed); + +/** + * Run all test cases in serial + * @param[in] processName The name of this process + * @param[in] tc_array The array of auto-generated testkit-lite test cases + * @param[in] reRunFailed True if failed test cases should be re-run + * @return 0 on success + */ +int RunAll(const char* processName, testcase tc_array[], bool reRunFailed); + +/** + * Find the named test case in the given array, and run it + * @param[in] tc_array The array of auto-generated testkit-lite test cases + * @param[in] testCaseName the name of the test case to run + * @return 0 on success + */ +int FindAndRunTestCase(::testcase tc_array[], const char* testCaseName); + +/** + * Display usage instructions for this program + * @param[in] program The name of this program + */ +void Usage(const char* program); + +} // namespace TestHarness + +#endif diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-intrusive-ptr.h b/automated-tests/src/dali/dali-test-suite-utils/test-intrusive-ptr.h new file mode 100644 index 0000000..03aafe3 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-intrusive-ptr.h @@ -0,0 +1,60 @@ +#ifndef __TEST_INTRUSIVE_PTR_H__ +#define __TEST_INTRUSIVE_PTR_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +template +struct UtcCoverageIntrusivePtr +{ + typedef IntrusivePtr (*Creator)(); + + void Check( Creator creator) + { + IntrusivePtr a = creator(); + IntrusivePtr b = creator(); + + DALI_TEST_CHECK( a.Get() ); + + a.Reset(); + + T* pB = b.Detach(); + + a.Reset(pB); + + DALI_TEST_CHECK(a); + + a.Reset(); + + }; + +}; + +} // Dali + +#endif + + diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-native-image.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-native-image.cpp new file mode 100644 index 0000000..d143d35 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-native-image.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#include "test-application.h" +#include "test-native-image.h" + + +namespace Dali +{ + +TestNativeImagePointer TestNativeImage::New(int width, int height) +{ + return new TestNativeImage(width, height); +} + +TestNativeImage::TestNativeImage(int width, int height) +: mWidth(width), mHeight(height), mExtensionCreateCalls(0), mExtensionDestroyCalls(0), mTargetTextureCalls(0) +{ +} + +TestNativeImage::~TestNativeImage() +{ +} + +} // namespace dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-native-image.h b/automated-tests/src/dali/dali-test-suite-utils/test-native-image.h new file mode 100644 index 0000000..4a39cb1 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-native-image.h @@ -0,0 +1,56 @@ +#ifndef __TEST_NATIVE_IMAGE_H__ +#define __TEST_NATIVE_IMAGE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ +class TestNativeImage; +typedef IntrusivePtr TestNativeImagePointer; + +class DALI_IMPORT_API TestNativeImage : public Dali::NativeImageInterface +{ +public: + static TestNativeImagePointer New(int width, int height); + + inline virtual bool GlExtensionCreate() { ++mExtensionCreateCalls; return true;}; + inline virtual void GlExtensionDestroy() { ++mExtensionDestroyCalls; }; + inline virtual GLenum TargetTexture() { ++mTargetTextureCalls; return 1;}; + inline virtual void PrepareTexture() {}; + inline virtual unsigned int GetWidth() const {return mWidth;}; + inline virtual unsigned int GetHeight() const {return mHeight;}; + inline virtual bool RequiresBlending() const {return true;}; + +private: + TestNativeImage(int width, int height); + virtual ~TestNativeImage(); + + int mWidth; + int mHeight; +public: + int mExtensionCreateCalls; + int mExtensionDestroyCalls; + int mTargetTextureCalls; +}; + +} // Dali + +#endif diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.cpp new file mode 100644 index 0000000..95082fd --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.cpp @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test-platform-abstraction.h" +#include "dali-test-suite-utils.h" +#include + +namespace Dali +{ + +/** + * Constructor + */ +TestPlatformAbstraction::TestPlatformAbstraction() +: mTrace(), + mSeconds( 0u ), + mMicroSeconds( 0u ), + mIsLoadingResult( false ), + mGetDefaultFontFamilyResult(), + mGetDefaultFontStyleResult(), + mGetDefaultFontSizeResult( 0 ), + mResources(), + mRequest( NULL ), + mSize(), + mClosestSize(), + mLoadFileResult(), + mSaveFileResult( false ) +{ + Initialize(); +} + +/** + * Destructor + */ +TestPlatformAbstraction::~TestPlatformAbstraction() +{ +} + +/** + * @copydoc PlatformAbstraction::GetTimeMicroseconds() + */ +void TestPlatformAbstraction::GetTimeMicroseconds(unsigned int &seconds, unsigned int µSeconds) +{ + seconds = mSeconds; + microSeconds = mMicroSeconds; + mTrace.PushCall("GetTimeMicroseconds", ""); +} + +/** + * @copydoc PlatformAbstraction::Suspend() + */ +void TestPlatformAbstraction::Suspend() +{ + mTrace.PushCall("Suspend", ""); +} + +/** + * @copydoc PlatformAbstraction::Resume() + */ +void TestPlatformAbstraction::Resume() +{ + mTrace.PushCall("Resume", ""); +} + +ImageDimensions TestPlatformAbstraction::GetClosestImageSize( const std::string& filename, + ImageDimensions size, + FittingMode::Type fittingMode, + SamplingMode::Type samplingMode, + bool orientationCorrection ) +{ + ImageDimensions closestSize = ImageDimensions( mClosestSize.x, mClosestSize.y ); + mTrace.PushCall("GetClosestImageSize", ""); + return closestSize; +} + +ImageDimensions TestPlatformAbstraction::GetClosestImageSize( Integration::ResourcePointer resourceBuffer, + ImageDimensions size, + FittingMode::Type fittingMode, + SamplingMode::Type samplingMode, + bool orientationCorrection ) +{ + ImageDimensions closestSize = ImageDimensions( mClosestSize.x, mClosestSize.y ); + mTrace.PushCall("GetClosestImageSize", ""); + return closestSize; +} + + +/** + * @copydoc PlatformAbstraction::LoadResource() + */ +void TestPlatformAbstraction::LoadResource(const Integration::ResourceRequest& request) +{ + std::ostringstream out; + out << "Type:" << request.GetType()->id << ", Path: " << request.GetPath() << std::endl ; + + mTrace.PushCall("LoadResource", out.str()); + if(mRequest != NULL) + { + delete mRequest; + tet_infoline ("Warning: multiple resource requests not handled by Test Suite. You may see unexpected errors"); + } + mRequest = new Integration::ResourceRequest(request); +} + +Integration::ResourcePointer TestPlatformAbstraction::LoadResourceSynchronously( const Integration::ResourceType& resourceType, const std::string& resourcePath ) +{ + mTrace.PushCall("LoadResourceSynchronously", ""); + return mResources.loadedResource; +} + +Integration::BitmapPtr TestPlatformAbstraction::DecodeBuffer( const Integration::ResourceType& resourceType, uint8_t * buffer, size_t size ) +{ + mTrace.PushCall("DecodeBuffer", ""); + return Integration::BitmapPtr(); +} + +/** + * @copydoc PlatformAbstraction::CancelLoad() + */ +void TestPlatformAbstraction::CancelLoad(Integration::ResourceId id, Integration::ResourceTypeId typeId) +{ + mTrace.PushCall("CancelLoad", ""); +} + +/** + * @copydoc PlatformAbstraction::GetResources() + */ +void TestPlatformAbstraction::GetResources(Integration::ResourceCache& cache) +{ + mTrace.PushCall("GetResources", ""); + + if(mResources.loaded) + { + cache.LoadResponse( mResources.loadedId, mResources.loadedType, mResources.loadedResource, Integration::RESOURCE_COMPLETELY_LOADED ); + } + if(mResources.loadFailed) + { + cache.LoadFailed( mResources.loadFailedId, mResources.loadFailure ); + } +} + +/** + * @copydoc PlatformAbstraction::IsLoading() + */ +bool TestPlatformAbstraction::IsLoading() +{ + mTrace.PushCall("IsLoading", ""); + return mIsLoadingResult; +} + +/** + * @copydoc PlatformAbstraction::GetDefaultFontSize() + */ +int TestPlatformAbstraction::GetDefaultFontSize() const +{ + mTrace.PushCall("GetDefaultFontSize", ""); + return mGetDefaultFontSizeResult; +} + +/** + * @copydoc PlatformAbstraction::SetDpi() + */ +void TestPlatformAbstraction::SetDpi (unsigned int dpiHorizontal, unsigned int dpiVertical) +{ + mTrace.PushCall("SetDpi", ""); +} + +/** + * @copydoc PlatformAbstraction::LoadFile() + */ +bool TestPlatformAbstraction::LoadFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const +{ + mTrace.PushCall("LoadFile", ""); + if( mLoadFileResult.loadResult ) + { + buffer = mLoadFileResult.buffer; + } + + return mLoadFileResult.loadResult; +} + +/** + * @copydoc PlatformAbstraction::LoadShaderBinaryFile() + */ +bool TestPlatformAbstraction::LoadShaderBinaryFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const +{ + mTrace.PushCall("LoadShaderBinaryFile", ""); + if( mLoadFileResult.loadResult ) + { + buffer = mLoadFileResult.buffer; + } + + return mLoadFileResult.loadResult; +} + +/** + * @copydoc PlatformAbstraction::SaveFile() + */ +bool TestPlatformAbstraction::SaveFile(const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const +{ + mTrace.PushCall("SaveFile", ""); + return false; +} + +void TestPlatformAbstraction::JoinLoaderThreads() +{ + mTrace.PushCall("JoinLoaderThreads", ""); +} + +/** Call this every test */ +void TestPlatformAbstraction::Initialize() +{ + mTrace.Reset(); + mTrace.Enable(true); + memset(&mResources, 0, sizeof(Resources)); + mSeconds=0; + mMicroSeconds=0; + mIsLoadingResult=false; + + if(mRequest) + { + delete mRequest; + mRequest = 0; + } +} + +bool TestPlatformAbstraction::WasCalled(TestFuncEnum func) +{ + switch(func) + { + case GetTimeMicrosecondsFunc: return mTrace.FindMethod("GetTimeMicroseconds"); + case SuspendFunc: return mTrace.FindMethod("Suspend"); + case ResumeFunc: return mTrace.FindMethod("Resume"); + case LoadResourceFunc: return mTrace.FindMethod("LoadResource"); + case LoadFileFunc: return mTrace.FindMethod("LoadFile"); + case SaveFileFunc: return mTrace.FindMethod("SaveFile"); + case CancelLoadFunc: return mTrace.FindMethod("CancelLoad"); + case GetResourcesFunc: return mTrace.FindMethod("GetResources"); + case IsLoadingFunc: return mTrace.FindMethod("IsLoading"); + case SetDpiFunc: return mTrace.FindMethod("SetDpi"); + case JoinLoaderThreadsFunc: return mTrace.FindMethod("JoinLoaderThreads"); + } + return false; +} + +void TestPlatformAbstraction::SetGetTimeMicrosecondsResult(size_t sec, size_t usec) +{ + mSeconds = sec; + mMicroSeconds = usec; +} + +void TestPlatformAbstraction::IncrementGetTimeResult(size_t milliseconds) +{ + mMicroSeconds += milliseconds * 1000u; + unsigned int additionalSeconds = mMicroSeconds / 1000000u; + + mSeconds += additionalSeconds; + mMicroSeconds -= additionalSeconds * 1000000u; +} + +void TestPlatformAbstraction::SetIsLoadingResult(bool result) +{ + mIsLoadingResult = result; +} + +void TestPlatformAbstraction::ClearReadyResources() +{ + memset(&mResources, 0, sizeof(Resources)); +} + +void TestPlatformAbstraction::SetResourceLoaded(Integration::ResourceId loadedId, + Integration::ResourceTypeId loadedType, + Integration::ResourcePointer loadedResource) +{ + mResources.loaded = true; + mResources.loadedId = loadedId; + mResources.loadedType = loadedType; + mResources.loadedResource = loadedResource; +} + +void TestPlatformAbstraction::SetResourceLoadFailed(Integration::ResourceId id, + Integration::ResourceFailure failure) +{ + mResources.loadFailed = true; + mResources.loadFailedId = id; + mResources.loadFailure = failure; +} + +Integration::ResourceRequest* TestPlatformAbstraction::GetRequest() +{ + return mRequest; +} + +void TestPlatformAbstraction::DiscardRequest() +{ + delete mRequest; + mRequest = NULL; +} + +void TestPlatformAbstraction::SetClosestImageSize(const Vector2& size) +{ + mClosestSize = size; +} + +void TestPlatformAbstraction::SetLoadFileResult( bool result, Dali::Vector< unsigned char >& buffer ) +{ + mLoadFileResult.loadResult = result; + if( result ) + { + mLoadFileResult.buffer = buffer; + } +} + +void TestPlatformAbstraction::SetSaveFileResult( bool result ) +{ + mSaveFileResult = result; +} + +} // namespace Dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.h b/automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.h new file mode 100644 index 0000000..9408801 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.h @@ -0,0 +1,236 @@ +#ifndef __DALI_TEST_PLATFORM_ABSTRACTION_H__ +#define __DALI_TEST_PLATFORM_ABSTRACTION_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include + +#include "test-trace-call-stack.h" + +namespace Dali +{ + +/** + * Concrete implementation of the platform abstraction class. + */ +class DALI_IMPORT_API TestPlatformAbstraction : public Dali::Integration::PlatformAbstraction +{ + +public: + + struct Resources + { + bool loaded; + Integration::ResourceId loadedId; + Integration::ResourceTypeId loadedType; + Integration::ResourcePointer loadedResource; + + bool loadFailed; + Integration::ResourceId loadFailedId; + Integration::ResourceFailure loadFailure; + }; + + struct LoadFileResult + { + inline LoadFileResult() + : loadResult(false) + { + + } + + bool loadResult; + Dali::Vector< unsigned char> buffer; + }; + + /** + * Constructor + */ + TestPlatformAbstraction(); + + /** + * Destructor + */ + virtual ~TestPlatformAbstraction(); + + /** + * @copydoc PlatformAbstraction::GetTimeMicroseconds() + */ + virtual void GetTimeMicroseconds(unsigned int &seconds, unsigned int µSeconds); + + /** + * @copydoc PlatformAbstraction::Suspend() + */ + virtual void Suspend(); + + /** + * @copydoc PlatformAbstraction::Resume() + */ + virtual void Resume(); + + virtual ImageDimensions GetClosestImageSize( const std::string& filename, + ImageDimensions size, + FittingMode::Type fittingMode, + SamplingMode::Type samplingMode, + bool orientationCorrection ); + + virtual ImageDimensions GetClosestImageSize( Integration::ResourcePointer resourceBuffer, + ImageDimensions size, + FittingMode::Type fittingMode, + SamplingMode::Type samplingMode, + bool orientationCorrection ); + + /** + * @copydoc PlatformAbstraction::LoadResource() + */ + virtual void LoadResource(const Integration::ResourceRequest& request); + + /** + * @copydoc PlatformAbstraction::LoadResourceSynchronously() + */ + virtual Integration::ResourcePointer LoadResourceSynchronously( const Integration::ResourceType& resourceType, const std::string& resourcePath ); + + /** + * @copydoc PlatformAbstraction::DecodeBuffer() + */ + virtual Integration::BitmapPtr DecodeBuffer( const Dali::Integration::ResourceType& resourceType, uint8_t * buffer, size_t size ); + + /** + * @copydoc PlatformAbstraction::CancelLoad() + */ + virtual void CancelLoad(Integration::ResourceId id, Integration::ResourceTypeId typeId); + + /** + * @copydoc PlatformAbstraction::GetResources() + */ + virtual void GetResources(Integration::ResourceCache& cache); + + /** + * @copydoc PlatformAbstraction::IsLoading() + */ + virtual bool IsLoading(); + + /** + * @copydoc PlatformAbstraction::GetDefaultFontSize() + */ + virtual int GetDefaultFontSize() const; + + /** + * @copydoc PlatformAbstraction::SetDpi() + */ + virtual void SetDpi (unsigned int dpiHorizontal, unsigned int dpiVertical); + + /** + * @copydoc PlatformAbstraction::LoadFile() + */ + virtual bool LoadFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const; + + /** + * @copydoc PlatformAbstraction::LoadShaderBinaryFile() + */ + virtual bool LoadShaderBinaryFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const; + + /** + * @copydoc PlatformAbstraction::SaveFile() + */ + virtual bool SaveFile(const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const; + + /** + * @copydoc PlatformAbstraction::SaveShaderBinaryFile() + */ + virtual bool SaveShaderBinaryFile( const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const { return false; } + + virtual void JoinLoaderThreads(); + +public: // TEST FUNCTIONS + + // Enumeration of Platform Abstraction methods + typedef enum + { + GetTimeMicrosecondsFunc, + SuspendFunc, + ResumeFunc, + LoadResourceFunc, + SaveFileFunc, + LoadFileFunc, + CancelLoadFunc, + GetResourcesFunc, + IsLoadingFunc, + SetDpiFunc, + JoinLoaderThreadsFunc, + } TestFuncEnum; + + /** Call this every test */ + void Initialize(); + + inline void EnableTrace(bool enable) { mTrace.Enable(enable); } + inline void ResetTrace() { mTrace.Reset(); } + inline TraceCallStack& GetTrace() { return mTrace; } + + bool WasCalled(TestFuncEnum func); + + void SetGetTimeMicrosecondsResult(size_t sec, size_t usec); + + void IncrementGetTimeResult(size_t milliseconds); + + void SetIsLoadingResult(bool result); + + void ClearReadyResources(); + + void SetResourceLoaded(Integration::ResourceId loadedId, + Integration::ResourceTypeId loadedType, + Integration::ResourcePointer loadedResource); + + void SetResourceLoadFailed(Integration::ResourceId id, + Integration::ResourceFailure failure); + + Integration::ResourceRequest* GetRequest(); + + void DiscardRequest(); + + void SetClosestImageSize(const Vector2& size); + + void SetLoadFileResult( bool result, Dali::Vector< unsigned char >& buffer ); + + void SetSaveFileResult( bool result ); + +private: + mutable TraceCallStack mTrace; + size_t mSeconds; + size_t mMicroSeconds; + bool mIsLoadingResult; + std::string mGetDefaultFontFamilyResult; + std::string mGetDefaultFontStyleResult; + int mGetDefaultFontSizeResult; + Resources mResources; + Integration::ResourceRequest* mRequest; + Vector2 mSize; + Vector2 mClosestSize; + + LoadFileResult mLoadFileResult; + bool mSaveFileResult; +}; + +} // Dali + +#endif /* __DALI_TET_PLATFORM_ABSTRACTION_H__ */ diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-render-controller.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-render-controller.cpp new file mode 100644 index 0000000..f3b04ad --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-render-controller.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test-render-controller.h" + +namespace Dali +{ + +TestRenderController::TestRenderController() +{ + Initialize(); +} + +TestRenderController::~TestRenderController() +{ +} + +void TestRenderController::RequestUpdate() +{ + mRequestUpdateCalled = true; +} + +void TestRenderController::RequestProcessEventsOnIdle() +{ + mRequestProcessEventsOnIdleCalled = true; +} + +bool TestRenderController::WasCalled(TestRenderControllerFuncEnum func) +{ + switch(func) + { + case RequestUpdateFunc: return mRequestUpdateCalled; + case RequestProcessEventsOnIdleFunc: return mRequestProcessEventsOnIdleCalled; + } + + return false; +} + +void TestRenderController::Initialize() +{ + mRequestUpdateCalled = false; + mRequestProcessEventsOnIdleCalled = false; +} + + +} // namespace dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-render-controller.h b/automated-tests/src/dali/dali-test-suite-utils/test-render-controller.h new file mode 100644 index 0000000..b00fbf0 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-render-controller.h @@ -0,0 +1,54 @@ +#ifndef __TEST_RENDER_CONTROLLER_H__ +#define __TEST_RENDER_CONTROLLER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +class DALI_IMPORT_API TestRenderController : public Dali::Integration::RenderController +{ +public: + TestRenderController(); + ~TestRenderController(); + + virtual void RequestUpdate(); + virtual void RequestProcessEventsOnIdle(); + + typedef enum + { + RequestUpdateFunc, + RequestProcessEventsOnIdleFunc, + } TestRenderControllerFuncEnum; + + bool WasCalled(TestRenderControllerFuncEnum func); + void Initialize(); + + +private: + bool mRequestUpdateCalled; + bool mRequestProcessEventsOnIdleCalled; +}; + +} // Dali + +#endif diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-touch-utils.h b/automated-tests/src/dali/dali-test-suite-utils/test-touch-utils.h new file mode 100644 index 0000000..ebae313 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-touch-utils.h @@ -0,0 +1,78 @@ +#ifndef _TEST_TOUCH_UTILS_H_ +#define _TEST_TOUCH_UTILS_H_ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +namespace Dali +{ + +// Data for touch events +struct TouchEventData +{ + TouchEventData() + : functorCalled(false), + receivedTouch(), + touchActor() + { + } + + void Reset() + { + functorCalled = false; + + receivedTouch.points.clear(); + receivedTouch.time = 0; + + touchActor.Reset(); + } + + bool functorCalled; + TouchEvent receivedTouch; + Actor touchActor; +}; + +// Functor that sets the data when called +struct TouchEventDataFunctor +{ + TouchEventDataFunctor(TouchEventData& data) : touchEventData(data) { } + + bool operator()(Actor actor, const TouchEvent& touch) + { + touchEventData.functorCalled = true; + touchEventData.touchActor = actor; + touchEventData.receivedTouch = touch; + return false; + } + + // Generate a touch-event + Integration::TouchEvent GenerateSingleTouch( TouchPoint::State state, Vector2 screenPosition ) const + { + Integration::TouchEvent touchEvent; + touchEvent.points.push_back( TouchPoint ( 0, state, screenPosition.x, screenPosition.y ) ); + return touchEvent; + } + + TouchEventData& touchEventData; +}; + + +} // namespace Dali + +#endif // _TEST_TOUCH_UTILS_H_ diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp new file mode 100644 index 0000000..921088b --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "test-trace-call-stack.h" + +namespace Dali +{ +/** + * Constructor + */ +TraceCallStack::TraceCallStack() : mTraceActive(false) { } + +/** + * Destructor + */ +TraceCallStack::~TraceCallStack() { } + +/** + * Turn on / off tracing + */ +void TraceCallStack::Enable(bool enable) { mTraceActive = enable; } + +bool TraceCallStack::IsEnabled() { return mTraceActive; } + +/** + * Push a call onto the stack if the trace is active + * @param[in] method The name of the method + * @param[in] params A comma separated list of parameter values + */ +void TraceCallStack::PushCall(std::string method, std::string params) +{ + if(mTraceActive) + { + std::vector< std::string > functionCall; + functionCall.push_back(method); + functionCall.push_back(params); + mCallStack.push_back( functionCall ); + } +} + +/** + * Search for a method in the stack + * @param[in] method The name of the method + * @return true if the method was in the stack + */ +bool TraceCallStack::FindMethod(std::string method) const +{ + bool found = false; + for( size_t i=0; i < mCallStack.size(); i++ ) + { + if( 0 == mCallStack[i][0].compare(method) ) + { + found = true; + break; + } + } + return found; +} + +int TraceCallStack::CountMethod(std::string method) const +{ + int numCalls = 0; + for( size_t i=0; i < mCallStack.size(); i++ ) + { + if( 0 == mCallStack[i][0].compare(method) ) + { + numCalls++; + } + } + return numCalls; +} + + +/** + * Search for a method in the stack with the given parameter list + * @param[in] method The name of the method + * @param[in] params A comma separated list of parameter values + * @return true if the method was in the stack + */ +bool TraceCallStack::FindMethodAndParams(std::string method, std::string params) const +{ + bool found = false; + for( size_t i=0; i < mCallStack.size(); i++ ) + { + if( 0 == mCallStack[i][0].compare(method) && 0 == mCallStack[i][1].compare(params) ) + { + found = true; + break; + } + } + return found; +} + +/** + * Test if the given method and parameters are at a given index in the stack + * @param[in] index Index in the call stack + * @param[in] method Name of method to test + * @param[in] params A comma separated list of parameter values to test + */ +bool TraceCallStack::TestMethodAndParams(int index, std::string method, std::string params) const +{ + return ( 0 == mCallStack[index][0].compare(method) && 0 == mCallStack[index][1].compare(params) ); +} + +/** + * Reset the call stack + */ +void TraceCallStack::Reset() +{ + mCallStack.clear(); +} + + +} // namespace Dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h b/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h new file mode 100644 index 0000000..25b77f8 --- /dev/null +++ b/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h @@ -0,0 +1,106 @@ +#ifndef __TEST_TRACE_CALL_STACK_H__ +#define __TEST_TRACE_CALL_STACK_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +namespace Dali +{ + +/** + * Helper class to track method calls in the abstraction and search for them in test cases + */ +class TraceCallStack +{ +public: + /** + * Constructor + */ + TraceCallStack(); + + /** + * Destructor + */ + ~TraceCallStack(); + + /** + * Turn on / off tracing + */ + void Enable(bool enable); + + bool IsEnabled(); + + /** + * Push a call onto the stack if the trace is active + * @param[in] method The name of the method + * @param[in] params A comma separated list of parameter values + */ + void PushCall(std::string method, std::string params); + + + /** + * Search for a method in the stack + * @param[in] method The name of the method + * @return true if the method was in the stack + */ + bool FindMethod(std::string method) const; + + /** + * Count how many times a method was called + * @param[in] method The name of the method + * @return The number of times it was called + */ + int CountMethod(std::string method) const; + + /** + * Search for a method in the stack with the given parameter list + * @param[in] method The name of the method + * @param[in] params A comma separated list of parameter values + * @return true if the method was in the stack + */ + bool FindMethodAndParams(std::string method, std::string params) const; + + /** + * Test if the given method and parameters are at a given index in the stack + * @param[in] index Index in the call stack + * @param[in] method Name of method to test + * @param[in] params A comma separated list of parameter values to test + */ + bool TestMethodAndParams(int index, std::string method, std::string params) const; + + /** + * Reset the call stack + */ + void Reset(); + + /** + * Get the call stack + * @return The call stack object (Vector of vector[2] of method/paramlist strings) + */ + inline const std::vector< std::vector< std::string > >& GetCallStack() { return mCallStack; } + +private: + bool mTraceActive; ///< True if the trace is active + std::vector< std::vector< std::string > > mCallStack; ///< The call stack +}; + +} // namespace dali + +#endif //__TEST_TRACE_CALL_STACK_H__ diff --git a/automated-tests/src/dali/tct-dali-core.cpp b/automated-tests/src/dali/tct-dali-core.cpp new file mode 100644 index 0000000..f8bd4de --- /dev/null +++ b/automated-tests/src/dali/tct-dali-core.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include "tct-dali-core.h" + +int main(int argc, char * const argv[]) +{ + int result = TestHarness::EXIT_STATUS_BAD_ARGUMENT; + + const char* optString = "r"; + bool optRerunFailed(false); + + int nextOpt = 0; + do + { + nextOpt = getopt( argc, argv, optString ); + switch(nextOpt) + { + case 'r': + optRerunFailed = true; + break; + case '?': + TestHarness::Usage(argv[0]); + exit(TestHarness::EXIT_STATUS_BAD_ARGUMENT); + break; + } + } while( nextOpt != -1 ); + + if( optind == argc ) // no testcase name in argument list + { + result = TestHarness::RunAllInParallel(argv[0], tc_array, optRerunFailed); + } + else + { + // optind is index of next argument - interpret as testcase name + result = TestHarness::FindAndRunTestCase(tc_array, argv[optind]); + } + return result; +} diff --git a/automated-tests/src/dali/utc-Dali-Actor.cpp b/automated-tests/src/dali/utc-Dali-Actor.cpp new file mode 100644 index 0000000..3ba9bd9 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Actor.cpp @@ -0,0 +1,2910 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "assert.h" +#include +#include +#include // For FLT_MAX +#include +#include +#include + +//& set: DaliActor + +using std::string; +using namespace Dali; + + +void utc_dali_actor_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_actor_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ +bool gTouchCallBackCalled=false; +bool gHoverCallBackCalled=false; + +/** + * Simulates a Down Touch at 25.0, 25.0. + * @param[in] app Test Application instance. + */ +int SimulateTouchForSetOverlayHitTest(TestApplication& app) +{ + app.SendNotification(); + app.Render(1); + app.SendNotification(); + app.Render(1); + + gTouchCallBackCalled = false; + + // simulate a touch event + Dali::TouchPoint point( 0, TouchPoint::Down, 25.0f, 25.0f ); + Dali::Integration::TouchEvent event; + event.AddPoint( point ); + app.ProcessEvent( event ); + + app.SendNotification(); + app.Render(1); + app.SendNotification(); + app.Render(1); + END_TEST; +} + + +static bool gTestConstraintCalled; + +struct TestConstraint +{ + void operator()( Vector4& color, const PropertyInputContainer& /* inputs */ ) + { + gTestConstraintCalled = true; + } +}; + +/** + * TestConstraint reference. + * When constraint is called, the resultRef is updated + * with the value supplied. + */ +template +struct TestConstraintRef +{ + TestConstraintRef(unsigned int& resultRef, unsigned int value) + : mResultRef(resultRef), + mValue(value) + { + } + + void operator()( T& current, const PropertyInputContainer& /* inputs */ ) + { + mResultRef = mValue; + } + + unsigned int& mResultRef; + unsigned int mValue; +}; + +static bool TestCallback(Actor actor, const TouchEvent& event) +{ + gTouchCallBackCalled = true; + return false; + END_TEST; +} + +static bool TestCallback3(Actor actor, const HoverEvent& event) +{ + gHoverCallBackCalled = true; + return false; + END_TEST; +} + +static Vector3 gSetSize; +static bool gSetSizeCallBackCalled; +void SetSizeCallback( Actor actor, const Vector3& size ) +{ + gSetSizeCallBackCalled = true; + gSetSize = size; +} +// validation stuff for onstage & offstage signals +static std::vector< std::string > gActorNamesOnOffStage; +static int gOnStageCallBackCalled; +void OnStageCallback( Actor actor ) +{ + ++gOnStageCallBackCalled; + gActorNamesOnOffStage.push_back( actor.GetName() ); + DALI_TEST_CHECK( actor.OnStage() == true ); +} +static int gOffStageCallBackCalled; +void OffStageCallback( Actor actor ) +{ + ++gOffStageCallBackCalled; + gActorNamesOnOffStage.push_back( actor.GetName() ); + DALI_TEST_CHECK( actor.OnStage() == false ); +} + +struct PositionComponentConstraint +{ + PositionComponentConstraint(){} + + void operator()( Vector3& pos, const PropertyInputContainer& inputs ) + { + const Matrix& m = inputs[0]->GetMatrix(); + Vector3 scale; + Quaternion rot; + m.GetTransformComponents(pos, rot, scale); + } +}; + +// OnRelayout + +static bool gOnRelayoutCallBackCalled = 0; +static std::vector< std::string > gActorNamesRelayout; + +void OnRelayoutCallback( Actor actor ) +{ + ++gOnRelayoutCallBackCalled; + gActorNamesRelayout.push_back( actor.GetName() ); +} + +} // anonymous namespace + + +//& purpose: Testing New API +int UtcDaliActorNew(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + DALI_TEST_CHECK(actor); + END_TEST; +} + +//& purpose: Testing Dali::Actor::DownCast() +int UtcDaliActorDownCastP(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Actor::DownCast()"); + + Actor actor = Actor::New(); + BaseHandle object(actor); + Actor actor2 = Actor::DownCast(object); + DALI_TEST_CHECK(actor2); + END_TEST; +} + +//& purpose: Testing Dali::Actor::DownCast() +int UtcDaliActorDownCastN(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Actor::DownCast()"); + + BaseHandle unInitializedObject; + Actor actor = Actor::DownCast(unInitializedObject); + DALI_TEST_CHECK(!actor); + END_TEST; +} + +//& purpose: Testing Dali::Actor::GetName() +int UtcDaliActorGetName(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + DALI_TEST_CHECK(actor.GetName().empty()); + END_TEST; +} + +//& purpose: Testing Dali::Actor::SetName() +int UtcDaliActorSetName(void) +{ + TestApplication application; + + string str("ActorName"); + Actor actor = Actor::New(); + + actor.SetName(str); + DALI_TEST_CHECK(actor.GetName() == str); + END_TEST; +} + +int UtcDaliActorGetId(void) +{ + tet_infoline("Testing Dali::Actor::UtcDaliActorGetId()"); + TestApplication application; + + Actor first = Actor::New(); + Actor second = Actor::New(); + Actor third = Actor::New(); + + DALI_TEST_CHECK(first.GetId() != second.GetId()); + DALI_TEST_CHECK(second.GetId() != third.GetId()); + END_TEST; +} + +int UtcDaliActorIsRoot(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_CHECK(!actor.IsRoot()); + + // get the root layer + actor = Stage::GetCurrent().GetLayer( 0 ); + DALI_TEST_CHECK( actor.IsRoot() ); + END_TEST; +} + +int UtcDaliActorOnStage(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_CHECK( !actor.OnStage() ); + + // get the root layer + actor = Stage::GetCurrent().GetLayer( 0 ); + DALI_TEST_CHECK( actor.OnStage() ); + END_TEST; +} + +int UtcDaliActorIsLayer(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_CHECK( !actor.IsLayer() ); + + // get the root layer + actor = Stage::GetCurrent().GetLayer( 0 ); + DALI_TEST_CHECK( actor.IsLayer() ); + END_TEST; +} + +int UtcDaliActorGetLayer(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + Layer layer = actor.GetLayer(); + + DALI_TEST_CHECK(layer); + + // get the root layers layer + actor = Stage::GetCurrent().GetLayer( 0 ); + DALI_TEST_CHECK( actor.GetLayer() ); + END_TEST; +} + +int UtcDaliActorAddP(void) +{ + tet_infoline("Testing Actor::Add"); + TestApplication application; + + Actor parent = Actor::New(); + Actor child = Actor::New(); + + DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION ); + + parent.Add(child); + + DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION ); + + Actor parent2 = Actor::New(); + parent2.Add( child ); + + DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( parent2.GetChildCount(), 1u, TEST_LOCATION ); + + // try Adding to same parent again, works + parent2.Add( child ); + DALI_TEST_EQUALS( parent2.GetChildCount(), 1u, TEST_LOCATION ); + + // try reparenting an orphaned child + { + Actor temporaryParent = Actor::New(); + temporaryParent.Add( child ); + DALI_TEST_EQUALS( parent2.GetChildCount(), 0u, TEST_LOCATION ); + } + // temporaryParent has now died, reparent the orphaned child + parent2.Add( child ); + DALI_TEST_EQUALS( parent2.GetChildCount(), 1u, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliActorAddN(void) +{ + tet_infoline("Testing Actor::Add"); + TestApplication application; + + Actor child = Actor::New(); + + Actor parent2 = Actor::New(); + parent2.Add( child ); + + // try illegal Add + try + { + parent2.Add( parent2 ); + tet_printf("Assertion test failed - no Exception\n" ); + tet_result(TET_FAIL); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "this != &child", TEST_LOCATION); + DALI_TEST_EQUALS( parent2.GetChildCount(), 1u, TEST_LOCATION ); + } + catch(...) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + // try reparenting root + try + { + parent2.Add( Stage::GetCurrent().GetLayer( 0 ) ); + tet_printf("Assertion test failed - no Exception\n" ); + tet_result(TET_FAIL); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "!child.IsRoot()", TEST_LOCATION); + DALI_TEST_EQUALS( parent2.GetChildCount(), 1u, TEST_LOCATION ); + } + catch(...) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + // try Add empty + try + { + Actor empty; + parent2.Add( empty ); + tet_printf("Assertion test failed - no Exception\n" ); + tet_result(TET_FAIL); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "actor", TEST_LOCATION); + DALI_TEST_EQUALS( parent2.GetChildCount(), 1u, TEST_LOCATION ); + } + catch(...) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + END_TEST; +} + +int UtcDaliActorRemoveN(void) +{ + tet_infoline("Testing Actor::Remove"); + TestApplication application; + + Actor parent = Actor::New(); + Actor child = Actor::New(); + DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION ); + + parent.Add(child); + DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION ); + + parent.Remove(child); + DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION ); + + // remove again, no problem + parent.Remove(child); + DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION ); + + // add child back + parent.Add(child); + DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION ); + // try Remove self, its a no-op + parent.Remove( parent ); + DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION ); + + // try Remove empty + try + { + Actor empty; + parent.Remove( empty ); + tet_printf("Assertion test failed - no Exception\n" ); + tet_result(TET_FAIL); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "actor", TEST_LOCATION); + DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION ); + } + catch(...) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + END_TEST; +} + +int UtcDaliActorRemoveP(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + Actor child = Actor::New(); + Actor random = Actor::New(); + + Stage::GetCurrent().Add( parent ); + + DALI_TEST_CHECK(parent.GetChildCount() == 0); + + parent.Add(child); + + DALI_TEST_CHECK(parent.GetChildCount() == 1); + + parent.Remove(random); + + DALI_TEST_CHECK(parent.GetChildCount() == 1); + + Stage::GetCurrent().Remove( parent ); + + DALI_TEST_CHECK(parent.GetChildCount() == 1); + END_TEST; +} + +int UtcDaliActorGetChildCount(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + Actor child = Actor::New(); + + DALI_TEST_CHECK(parent.GetChildCount() == 0); + + parent.Add(child); + + DALI_TEST_CHECK(parent.GetChildCount() == 1); + END_TEST; +} + +int UtcDaliActorGetChildren01(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + Actor first = Actor::New(); + Actor second = Actor::New(); + Actor third = Actor::New(); + + parent.Add(first); + parent.Add(second); + parent.Add(third); + + DALI_TEST_CHECK(parent.GetChildAt(0) == first); + DALI_TEST_CHECK(parent.GetChildAt(1) == second); + DALI_TEST_CHECK(parent.GetChildAt(2) == third); + END_TEST; +} + +int UtcDaliActorGetChildren02(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + Actor first = Actor::New(); + Actor second = Actor::New(); + Actor third = Actor::New(); + + parent.Add(first); + parent.Add(second); + parent.Add(third); + + const Actor& constParent = parent; + + DALI_TEST_CHECK(constParent.GetChildAt(0) == first); + DALI_TEST_CHECK(constParent.GetChildAt(1) == second); + DALI_TEST_CHECK(constParent.GetChildAt(2) == third); + END_TEST; +} + +int UtcDaliActorGetParent01(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + Actor child = Actor::New(); + + parent.Add(child); + + DALI_TEST_CHECK(child.GetParent() == parent); + END_TEST; +} + +int UtcDaliActorGetParent02(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + DALI_TEST_CHECK(!actor.GetParent()); + END_TEST; +} + +int UtcDaliActorSetParentOrigin(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + Vector3 vector(0.7f, 0.8f, 0.9f); + DALI_TEST_CHECK(vector != actor.GetCurrentParentOrigin()); + + actor.SetParentOrigin(vector); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentParentOrigin()); + + Stage::GetCurrent().Add( actor ); + + actor.SetParentOrigin( Vector3( 0.1f, 0.2f, 0.3f ) ); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( Vector3( 0.1f, 0.2f, 0.3f ), actor.GetCurrentParentOrigin(), TEST_LOCATION ); + + Stage::GetCurrent().Remove( actor ); + END_TEST; +} + +int UtcDaliActorGetCurrentParentOrigin(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + Vector3 vector(0.7f, 0.8f, 0.9f); + DALI_TEST_CHECK(vector != actor.GetCurrentParentOrigin()); + + actor.SetParentOrigin(vector); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentParentOrigin()); + END_TEST; +} + +int UtcDaliActorSetAnchorPoint(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + Vector3 vector(0.7f, 0.8f, 0.9f); + DALI_TEST_CHECK(vector != actor.GetCurrentAnchorPoint()); + + actor.SetAnchorPoint(vector); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentAnchorPoint()); + + Stage::GetCurrent().Add( actor ); + + actor.SetAnchorPoint( Vector3( 0.1f, 0.2f, 0.3f ) ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( Vector3( 0.1f, 0.2f, 0.3f ), actor.GetCurrentAnchorPoint(), TEST_LOCATION ); + + Stage::GetCurrent().Remove( actor ); + END_TEST; +} + +int UtcDaliActorGetCurrentAnchorPoint(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + Vector3 vector(0.7f, 0.8f, 0.9f); + DALI_TEST_CHECK(vector != actor.GetCurrentAnchorPoint()); + + actor.SetAnchorPoint(vector); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentAnchorPoint()); + END_TEST; +} + +// SetSize(float width, float height) +int UtcDaliActorSetSize01(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 vector(100.0f, 100.0f, 100.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentSize()); + + actor.SetSize(vector.x, vector.y); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentSize()); + END_TEST; +} + +// SetSize(float width, float height, float depth) +int UtcDaliActorSetSize02(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 vector(100.0f, 100.0f, 100.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentSize()); + + actor.SetSize(vector.x, vector.y, vector.z); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentSize()); + END_TEST; +} + +// SetSize(Vector2 size) +int UtcDaliActorSetSize03(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 vector(100.0f, 100.0f, 100.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentSize()); + + actor.SetSize(Vector2(vector.x, vector.y)); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentSize()); + END_TEST; +} + +// SetSize(Vector3 size) +int UtcDaliActorSetSize04(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 vector(100.0f, 100.0f, 100.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentSize()); + + actor.SetSize(vector); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentSize()); + + Stage::GetCurrent().Add( actor ); + actor.SetSize( Vector3( 0.1f, 0.2f, 0.3f ) ); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( Vector3( 0.1f, 0.2f, 0.3f ), actor.GetCurrentSize(), TEST_LOCATION ); + Stage::GetCurrent().Remove( actor ); + END_TEST; +} + +int UtcDaliActorGetCurrentSize(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 vector(100.0f, 100.0f, 20.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentSize()); + + actor.SetSize(vector); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentSize()); + END_TEST; +} + +int UtcDaliActorGetNaturalSize(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 vector( 0.0f, 0.0f, 0.0f ); + + DALI_TEST_CHECK( actor.GetNaturalSize() == vector ); + + END_TEST; +} + +int UtcDaliActorGetCurrentSizeImmediate(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 vector(100.0f, 100.0f, 20.0f); + + DALI_TEST_CHECK(vector != actor.GetTargetSize()); + DALI_TEST_CHECK(vector != actor.GetCurrentSize()); + + actor.SetSize(vector); + + DALI_TEST_CHECK(vector == actor.GetTargetSize()); + DALI_TEST_CHECK(vector != actor.GetCurrentSize()); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetTargetSize()); + DALI_TEST_CHECK(vector == actor.GetCurrentSize()); + + // Animation + // Build the animation + const float durationSeconds = 2.0f; + Animation animation = Animation::New( durationSeconds ); + const Vector3 targetValue( 10.0f, 20.0f, 30.0f ); + animation.AnimateTo( Property( actor, Actor::Property::SIZE ), targetValue ); + + DALI_TEST_CHECK( actor.GetTargetSize() == targetValue ); + + // Start the animation + animation.Play(); + + application.SendNotification(); + application.Render( static_cast( durationSeconds * 1000.0f ) ); + + DALI_TEST_CHECK( actor.GetTargetSize() == targetValue ); + + END_TEST; +} + +// SetPosition(float x, float y) +int UtcDaliActorSetPosition01(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Set to random to start off with + actor.SetPosition(Vector3(120.0f, 120.0f, 0.0f)); + + Vector3 vector(100.0f, 100.0f, 0.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentPosition()); + + actor.SetPosition(vector.x, vector.y); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK(vector == actor.GetCurrentPosition()); + + Stage::GetCurrent().Add( actor ); + actor.SetPosition( Vector3( 0.1f, 0.2f, 0.3f ) ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( Vector3( 0.1f, 0.2f, 0.3f ), actor.GetCurrentPosition(), TEST_LOCATION ); + + actor.SetX( 1.0f ); + actor.SetY( 1.1f ); + actor.SetZ( 1.2f ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( Vector3( 1.0f, 1.1f, 1.2f ), actor.GetCurrentPosition(), TEST_LOCATION ); + + actor.TranslateBy( Vector3( 0.1f, 0.1f, 0.1f ) ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( Vector3( 1.1f, 1.2f, 1.3f ), actor.GetCurrentPosition(), Math::MACHINE_EPSILON_10000, TEST_LOCATION ); + + Stage::GetCurrent().Remove( actor ); + END_TEST; +} + +// SetPosition(float x, float y, float z) +int UtcDaliActorSetPosition02(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Set to random to start off with + actor.SetPosition(Vector3(120.0f, 120.0f, 120.0f)); + + Vector3 vector(100.0f, 100.0f, 100.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentPosition()); + + actor.SetPosition(vector.x, vector.y, vector.z); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentPosition()); + END_TEST; +} + +// SetPosition(Vector3 position) +int UtcDaliActorSetPosition03(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Set to random to start off with + actor.SetPosition(Vector3(120.0f, 120.0f, 120.0f)); + + Vector3 vector(100.0f, 100.0f, 100.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentPosition()); + + actor.SetPosition(vector); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentPosition()); + END_TEST; +} + +int UtcDaliActorSetX(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + Vector3 vector(100.0f, 0.0f, 0.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentPosition()); + + actor.SetX(100.0f); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentPosition()); + END_TEST; +} + +int UtcDaliActorSetY(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + Vector3 vector(0.0f, 100.0f, 0.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentPosition()); + + actor.SetY(100.0f); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentPosition()); + END_TEST; +} + +int UtcDaliActorSetZ(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + Vector3 vector(0.0f, 0.0f, 100.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentPosition()); + + actor.SetZ(100.0f); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentPosition()); + END_TEST; +} + +int UtcDaliActorTranslateBy(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 vector(100.0f, 100.0f, 100.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentPosition()); + + actor.SetPosition(vector); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentPosition()); + + actor.TranslateBy(vector); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector*2.0f == actor.GetCurrentPosition()); + END_TEST; +} + +int UtcDaliActorGetCurrentPosition(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 setVector(100.0f, 100.0f, 0.0f); + actor.SetPosition(setVector); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(actor.GetCurrentPosition() == setVector); + END_TEST; +} + +int UtcDaliActorGetCurrentWorldPosition(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + Vector3 parentPosition( 1.0f, 2.0f, 3.0f ); + parent.SetPosition( parentPosition ); + parent.SetParentOrigin( ParentOrigin::CENTER ); + parent.SetAnchorPoint( AnchorPoint::CENTER ); + Stage::GetCurrent().Add( parent ); + + Actor child = Actor::New(); + child.SetParentOrigin( ParentOrigin::CENTER ); + child.SetAnchorPoint( AnchorPoint::CENTER ); + Vector3 childPosition( 6.0f, 6.0f, 6.0f ); + child.SetPosition( childPosition ); + parent.Add( child ); + + // The actors should not have a world position yet + DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), Vector3::ZERO, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), Vector3::ZERO, TEST_LOCATION ); + + application.SendNotification(); + application.Render(0); + + DALI_TEST_EQUALS( parent.GetCurrentPosition(), parentPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentPosition(), childPosition, TEST_LOCATION ); + + // The actors should have a world position now + DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), parentPosition + childPosition, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliActorInheritPosition(void) +{ + tet_infoline("Testing Actor::SetPositionInheritanceMode"); + TestApplication application; + + Actor parent = Actor::New(); + Vector3 parentPosition( 1.0f, 2.0f, 3.0f ); + parent.SetPosition( parentPosition ); + parent.SetParentOrigin( ParentOrigin::CENTER ); + parent.SetAnchorPoint( AnchorPoint::CENTER ); + Stage::GetCurrent().Add( parent ); + + Actor child = Actor::New(); + child.SetParentOrigin( ParentOrigin::CENTER ); + child.SetAnchorPoint( AnchorPoint::CENTER ); + Vector3 childPosition( 10.0f, 11.0f, 12.0f ); + child.SetPosition( childPosition ); + parent.Add( child ); + + // The actors should not have a world position yet + DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), Vector3::ZERO, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), Vector3::ZERO, TEST_LOCATION ); + + // first test default, which is INHERIT_PARENT_POSITION + DALI_TEST_EQUALS( child.GetPositionInheritanceMode(), Dali::INHERIT_PARENT_POSITION, TEST_LOCATION ); + application.SendNotification(); + application.Render(0); // should only really call Update as Render is not required to update scene + DALI_TEST_EQUALS( parent.GetCurrentPosition(), parentPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentPosition(), childPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), parentPosition + childPosition, TEST_LOCATION ); + + // Change inheritance mode to use parent + child.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION ); + DALI_TEST_EQUALS( child.GetPositionInheritanceMode(), Dali::USE_PARENT_POSITION, TEST_LOCATION ); + application.SendNotification(); + application.Render(0); // should only really call Update as Render is not required to update scene + DALI_TEST_EQUALS( parent.GetCurrentPosition(), parentPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentPosition(), childPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION ); + + // Change inheritance mode to use parent + offset + child.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION ); + Vector3 childOffset( -1.0f, 1.0f, 0.0f ); + child.SetPosition( childOffset ); + DALI_TEST_EQUALS( child.GetPositionInheritanceMode(), Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION, TEST_LOCATION ); + application.SendNotification(); + application.Render(0); // should only really call Update as Render is not required to update scene + DALI_TEST_EQUALS( parent.GetCurrentPosition(), parentPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentPosition(), childOffset, TEST_LOCATION ); + DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), parentPosition + childOffset, TEST_LOCATION ); + + // Change inheritance mode to not inherit + child.SetPositionInheritanceMode( Dali::DONT_INHERIT_POSITION ); + DALI_TEST_EQUALS( child.GetPositionInheritanceMode(), Dali::DONT_INHERIT_POSITION, TEST_LOCATION ); + application.SendNotification(); + application.Render(0); // should only really call Update as Render is not required to update scene + DALI_TEST_EQUALS( parent.GetCurrentPosition(), parentPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentPosition(), childOffset, TEST_LOCATION ); + DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), childOffset, TEST_LOCATION ); + END_TEST; +} + +// SetOrientation(float angleRadians, Vector3 axis) +int UtcDaliActorSetOrientation01(void) +{ + TestApplication application; + + Quaternion rotation( Radian(0.785f), Vector3(1.0f, 1.0f, 0.0f)); + Actor actor = Actor::New(); + + actor.SetOrientation(rotation); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS(rotation, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliActorSetOrientation02(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + Radian angle( 0.785f ); + Vector3 axis(1.0f, 1.0f, 0.0f); + + actor.SetOrientation( angle, axis); + Quaternion rotation( angle, axis ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(rotation, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION); + + Stage::GetCurrent().Add( actor ); + actor.RotateBy( Degree( 360 ), axis); + DALI_TEST_EQUALS(rotation, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION); + + actor.SetOrientation( Degree( 0 ), Vector3( 1.0f, 0.0f, 0.0f ) ); + Quaternion result( Radian( 0 ), Vector3( 1.0f, 0.0f, 0.0f ) ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( result, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION); + + actor.SetOrientation( angle, axis); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(rotation, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION); + + Stage::GetCurrent().Remove( actor ); + END_TEST; +} + +// RotateBy(float angleRadians, Vector3 axis) +int UtcDaliActorRotateBy01(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + Radian angle( M_PI * 0.25f ); + actor.RotateBy(( angle ), Vector3::ZAXIS); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(Quaternion( angle, Vector3::ZAXIS), actor.GetCurrentOrientation(), 0.001, TEST_LOCATION); + + Stage::GetCurrent().Add( actor ); + + actor.RotateBy( angle, Vector3::ZAXIS); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(Quaternion(angle * 2.0f, Vector3::ZAXIS), actor.GetCurrentOrientation(), 0.001, TEST_LOCATION); + + Stage::GetCurrent().Remove( actor ); + END_TEST; +} + +// RotateBy(Quaternion relativeRotation) +int UtcDaliActorRotateBy02(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + Radian angle( M_PI * 0.25f ); + Quaternion rotation(angle, Vector3::ZAXIS); + actor.RotateBy(rotation); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(rotation, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION); + + actor.RotateBy(rotation); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(Quaternion(angle * 2.0f, Vector3::ZAXIS), actor.GetCurrentOrientation(), 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliActorGetCurrentOrientation(void) +{ + TestApplication application; + Actor actor = Actor::New(); + + Quaternion rotation(Radian(0.785f), Vector3(1.0f, 1.0f, 0.0f)); + actor.SetOrientation(rotation); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(rotation, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliActorGetCurrentWorldOrientation(void) +{ + tet_infoline("Testing Actor::GetCurrentWorldRotation"); + TestApplication application; + + Actor parent = Actor::New(); + Radian rotationAngle( Degree(90.0f) ); + Quaternion rotation( rotationAngle, Vector3::YAXIS ); + parent.SetOrientation( rotation ); + Stage::GetCurrent().Add( parent ); + + Actor child = Actor::New(); + child.SetOrientation( rotation ); + parent.Add( child ); + + // The actors should not have a world rotation yet + DALI_TEST_EQUALS( parent.GetCurrentWorldOrientation(), Quaternion(Radian(0.0f), Vector3::YAXIS), 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldOrientation(), Quaternion(Radian(0.0f), Vector3::YAXIS), 0.001, TEST_LOCATION ); + + application.SendNotification(); + application.Render(0); + + DALI_TEST_EQUALS( parent.GetCurrentOrientation(), rotation, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentOrientation(), rotation, 0.001, TEST_LOCATION ); + + // The actors should have a world rotation now + DALI_TEST_EQUALS( parent.GetCurrentWorldOrientation(), Quaternion( rotationAngle, Vector3::YAXIS ), 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldOrientation(), Quaternion( rotationAngle * 2.0f, Vector3::YAXIS ), 0.001, TEST_LOCATION ); + + // turn off child rotation inheritance + child.SetInheritOrientation( false ); + DALI_TEST_EQUALS( child.IsOrientationInherited(), false, TEST_LOCATION ); + application.SendNotification(); + application.Render(0); + + // The actors should have a world rotation now + DALI_TEST_EQUALS( parent.GetCurrentWorldOrientation(), Quaternion( rotationAngle, Vector3::YAXIS ), 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldOrientation(), rotation, 0.001, TEST_LOCATION ); + END_TEST; +} + +// SetScale(float scale) +int UtcDaliActorSetScale01(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Set to random value first - GetCurrentScale() asserts if called before SetScale() + actor.SetScale(0.25f); + + Vector3 scale(10.0f, 10.0f, 10.0f); + DALI_TEST_CHECK(actor.GetCurrentScale() != scale); + + actor.SetScale(scale.x); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(actor.GetCurrentScale() == scale); + END_TEST; +} + +// SetScale(float scaleX, float scaleY, float scaleZ) +int UtcDaliActorSetScale02(void) +{ + TestApplication application; + Vector3 scale(10.0f, 10.0f, 10.0f); + + Actor actor = Actor::New(); + + // Set to random value first - GetCurrentScale() asserts if called before SetScale() + actor.SetScale(Vector3(12.0f, 1.0f, 2.0f)); + + DALI_TEST_CHECK(actor.GetCurrentScale() != scale); + + actor.SetScale(scale.x, scale.y, scale.z); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK(actor.GetCurrentScale() == scale); + + // add to stage and test + Stage::GetCurrent().Add( actor ); + actor.SetScale( 2.0f, 2.0f, 2.0f ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( Vector3( 2.0f, 2.0f, 2.0f ), actor.GetCurrentScale(), 0.001, TEST_LOCATION); + + Stage::GetCurrent().Remove( actor ); + + END_TEST; +} + +// SetScale(Vector3 scale) +int UtcDaliActorSetScale03(void) +{ + TestApplication application; + Vector3 scale(10.0f, 10.0f, 10.0f); + + Actor actor = Actor::New(); + + // Set to random value first - GetCurrentScale() asserts if called before SetScale() + actor.SetScale(Vector3(12.0f, 1.0f, 2.0f)); + + DALI_TEST_CHECK(actor.GetCurrentScale() != scale); + + actor.SetScale(scale); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(actor.GetCurrentScale() == scale); + END_TEST; +} + +int UtcDaliActorScaleBy(void) +{ + TestApplication application; + Actor actor = Actor::New(); + Vector3 vector(100.0f, 100.0f, 100.0f); + + DALI_TEST_CHECK(vector != actor.GetCurrentScale()); + + actor.SetScale(vector); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector == actor.GetCurrentScale()); + + actor.ScaleBy(vector); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(vector*100.0f == actor.GetCurrentScale()); + END_TEST; +} + +int UtcDaliActorGetCurrentScale(void) +{ + TestApplication application; + Vector3 scale(12.0f, 1.0f, 2.0f); + + Actor actor = Actor::New(); + + actor.SetScale(scale); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK(actor.GetCurrentScale() == scale); + END_TEST; +} + +int UtcDaliActorGetCurrentWorldScale(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + Vector3 parentScale( 1.0f, 2.0f, 3.0f ); + parent.SetScale( parentScale ); + Stage::GetCurrent().Add( parent ); + + Actor child = Actor::New(); + Vector3 childScale( 2.0f, 2.0f, 2.0f ); + child.SetScale( childScale ); + parent.Add( child ); + + // The actors should not have a scale yet + DALI_TEST_EQUALS( parent.GetCurrentScale(), Vector3::ONE, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentScale(), Vector3::ONE, TEST_LOCATION ); + + // The actors should not have a world scale yet + DALI_TEST_EQUALS( parent.GetCurrentWorldScale(), Vector3::ONE, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldScale(), Vector3::ONE, TEST_LOCATION ); + + application.SendNotification(); + application.Render(0); + + DALI_TEST_EQUALS( parent.GetCurrentScale(), parentScale, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentScale(), childScale, TEST_LOCATION ); + + // The actors should have a world scale now + DALI_TEST_EQUALS( parent.GetCurrentWorldScale(), parentScale, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldScale(), parentScale * childScale, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliActorInheritScale(void) +{ + tet_infoline("Testing Actor::SetInheritScale"); + TestApplication application; + + Actor parent = Actor::New(); + Vector3 parentScale( 1.0f, 2.0f, 3.0f ); + parent.SetScale( parentScale ); + Stage::GetCurrent().Add( parent ); + + Actor child = Actor::New(); + Vector3 childScale( 2.0f, 2.0f, 2.0f ); + child.SetScale( childScale ); + parent.Add( child ); + + application.SendNotification(); + application.Render(0); + + DALI_TEST_EQUALS( child.IsScaleInherited(), true, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldScale(), parentScale * childScale, TEST_LOCATION ); + + child.SetInheritScale( false ); + DALI_TEST_EQUALS( child.IsScaleInherited(), false, TEST_LOCATION ); + + application.SendNotification(); + application.Render(0); + + DALI_TEST_EQUALS( child.GetCurrentWorldScale(), childScale, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliActorSetVisible(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetVisible(false); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK(actor.IsVisible() == false); + + actor.SetVisible(true); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK(actor.IsVisible() == true); + + // put actor on stage + Stage::GetCurrent().Add( actor ); + actor.SetVisible(false); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK(actor.IsVisible() == false); + END_TEST; +} + +int UtcDaliActorIsVisible(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + DALI_TEST_CHECK(actor.IsVisible() == true); + END_TEST; +} + +int UtcDaliActorSetOpacity(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + // initial opacity is 1 + DALI_TEST_EQUALS(actor.GetCurrentOpacity(), 1.0f, TEST_LOCATION ); + + actor.SetOpacity( 0.4f); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(actor.GetCurrentOpacity(), 0.4f, TEST_LOCATION ); + + // change opacity, actor is on stage to change is not immediate + actor.SetOpacity( actor.GetCurrentOpacity() + 0.1f ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(actor.GetCurrentOpacity(), 0.5f, TEST_LOCATION ); + + // put actor on stage + Stage::GetCurrent().Add( actor ); + + // change opacity, actor is on stage to change is not immediate + actor.SetOpacity( 0.9f ); + DALI_TEST_EQUALS(actor.GetCurrentOpacity(), 0.5f, TEST_LOCATION ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(actor.GetCurrentOpacity(), 0.9f, TEST_LOCATION ); + + // change opacity, actor is on stage to change is not immediate + actor.SetOpacity( actor.GetCurrentOpacity() - 0.9f ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS(actor.GetCurrentOpacity(), 0.0f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliActorGetCurrentOpacity(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_CHECK(actor.GetCurrentOpacity() != 0.5f); + + actor.SetOpacity(0.5f); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK(actor.GetCurrentOpacity() == 0.5f); + END_TEST; +} + +int UtcDaliActorSetSensitive(void) +{ + TestApplication application; + Actor actor = Actor::New(); + + bool sensitive = !actor.IsSensitive(); + + actor.SetSensitive(sensitive); + + DALI_TEST_CHECK(sensitive == actor.IsSensitive()); + END_TEST; +} + +int UtcDaliActorIsSensitive(void) +{ + TestApplication application; + Actor actor = Actor::New(); + actor.SetSensitive(false); + + DALI_TEST_CHECK(false == actor.IsSensitive()); + END_TEST; +} + +int UtcDaliActorSetColor(void) +{ + TestApplication application; + Actor actor = Actor::New(); + Vector4 color(1.0f, 1.0f, 1.0f, 0.5f); + + DALI_TEST_CHECK(color != actor.GetCurrentColor()); + + actor.SetColor(color); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK(color == actor.GetCurrentColor()); + + actor.SetColor( actor.GetCurrentColor() + Vector4( -0.4f, -0.5f, -0.6f, -0.4f ) ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( Vector4( 0.6f, 0.5f, 0.4f, 0.1f ), actor.GetCurrentColor(), TEST_LOCATION ); + + Stage::GetCurrent().Add( actor ); + actor.SetColor( color ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( color, actor.GetCurrentColor(), TEST_LOCATION ); + + actor.SetColor( actor.GetCurrentColor() + Vector4( 1.1f, 1.1f, 1.1f, 1.1f ) ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + // Actor color is not clamped + DALI_TEST_EQUALS( Vector4( 2.1f, 2.1f, 2.1f, 1.6f ), actor.GetCurrentColor(), TEST_LOCATION ); + // world color is clamped + DALI_TEST_EQUALS( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ), actor.GetCurrentWorldColor(), TEST_LOCATION ); + + Stage::GetCurrent().Remove( actor ); + END_TEST; +} + +int UtcDaliActorGetCurrentColor(void) +{ + TestApplication application; + Actor actor = Actor::New(); + Vector4 color(1.0f, 1.0f, 1.0f, 0.5f); + + actor.SetColor(color); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK(color == actor.GetCurrentColor()); + END_TEST; +} + +int UtcDaliActorGetCurrentWorldColor(void) +{ + tet_infoline("Actor::GetCurrentWorldColor"); + TestApplication application; + + Actor parent = Actor::New(); + Vector4 parentColor( 1.0f, 0.5f, 0.0f, 0.8f ); + parent.SetColor( parentColor ); + Stage::GetCurrent().Add( parent ); + + Actor child = Actor::New(); + Vector4 childColor( 0.5f, 0.6f, 0.5f, 1.0f ); + child.SetColor( childColor ); + parent.Add( child ); + + DALI_TEST_EQUALS( parent.GetCurrentColor(), Color::WHITE, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentColor(), Color::WHITE, TEST_LOCATION ); + + // verify the default color mode + DALI_TEST_EQUALS( USE_OWN_MULTIPLY_PARENT_ALPHA, child.GetColorMode(), TEST_LOCATION ); + + // The actors should not have a world color yet + DALI_TEST_EQUALS( parent.GetCurrentWorldColor(), Color::WHITE, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldColor(), Color::WHITE, TEST_LOCATION ); + + application.SendNotification(); + application.Render(0); + + DALI_TEST_EQUALS( parent.GetCurrentColor(), parentColor, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentColor(), childColor, TEST_LOCATION ); + + // The actors should have a world color now + DALI_TEST_EQUALS( parent.GetCurrentWorldColor(), parentColor, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldColor(), Vector4( childColor.r, childColor.g, childColor.b, childColor.a * parentColor.a), TEST_LOCATION ); + + // use own color + child.SetColorMode( USE_OWN_COLOR ); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( child.GetCurrentWorldColor(), childColor, TEST_LOCATION ); + + // use parent color + child.SetColorMode( USE_PARENT_COLOR ); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( child.GetCurrentColor(), childColor, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldColor(), parentColor, TEST_LOCATION ); + + // use parent alpha + child.SetColorMode( USE_OWN_MULTIPLY_PARENT_ALPHA ); + application.SendNotification(); + application.Render(0); + Vector4 expectedColor( childColor ); + expectedColor.a *= parentColor.a; + DALI_TEST_EQUALS( child.GetCurrentColor(), childColor, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldColor(), expectedColor, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliActorSetColorMode(void) +{ + tet_infoline("Actor::SetColorMode"); + TestApplication application; + Actor actor = Actor::New(); + Actor child = Actor::New(); + actor.Add( child ); + + actor.SetColorMode( USE_OWN_COLOR ); + DALI_TEST_EQUALS( USE_OWN_COLOR, actor.GetColorMode(), TEST_LOCATION ); + + actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR ); + DALI_TEST_EQUALS( USE_OWN_MULTIPLY_PARENT_COLOR, actor.GetColorMode(), TEST_LOCATION ); + + actor.SetColorMode( USE_PARENT_COLOR ); + DALI_TEST_EQUALS( USE_PARENT_COLOR, actor.GetColorMode(), TEST_LOCATION ); + + actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_ALPHA ); + DALI_TEST_EQUALS( USE_OWN_MULTIPLY_PARENT_ALPHA, actor.GetColorMode(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliActorScreenToLocal(void) +{ + TestApplication application; + Actor actor = Actor::New(); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + actor.SetSize(100.0f, 100.0f); + actor.SetPosition(10.0f, 10.0f); + Stage::GetCurrent().Add(actor); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + float localX; + float localY; + + DALI_TEST_CHECK( actor.ScreenToLocal(localX, localY, 50.0f, 50.0f) ); + + DALI_TEST_EQUALS(localX, 40.0f, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(localY, 40.0f, 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliActorSetLeaveRequired(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + actor.SetLeaveRequired(false); + DALI_TEST_CHECK(actor.GetLeaveRequired() == false); + + actor.SetLeaveRequired(true); + DALI_TEST_CHECK(actor.GetLeaveRequired() == true); + END_TEST; +} + +int UtcDaliActorGetLeaveRequired(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + DALI_TEST_CHECK(actor.GetLeaveRequired() == false); + END_TEST; +} + +int UtcDaliActorSetKeyboardFocusable(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + actor.SetKeyboardFocusable(true); + DALI_TEST_CHECK(actor.IsKeyboardFocusable() == true); + + actor.SetKeyboardFocusable(false); + DALI_TEST_CHECK(actor.IsKeyboardFocusable() == false); + END_TEST; +} + +int UtcDaliActorIsKeyboardFocusable(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + DALI_TEST_CHECK(actor.IsKeyboardFocusable() == false); + END_TEST; +} + +int UtcDaliActorRemoveConstraints(void) +{ + tet_infoline(" UtcDaliActorRemoveConstraints"); + TestApplication application; + + gTestConstraintCalled = false; + + Actor actor = Actor::New(); + + Constraint constraint = Constraint::New( actor, Actor::Property::COLOR, TestConstraint() ); + constraint.Apply(); + actor.RemoveConstraints(); + + DALI_TEST_CHECK( gTestConstraintCalled == false ); + + Stage::GetCurrent().Add( actor ); + constraint.Apply(); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + actor.RemoveConstraints(); + + DALI_TEST_CHECK( gTestConstraintCalled == true ); + END_TEST; +} + +int UtcDaliActorRemoveConstraintTag(void) +{ + tet_infoline(" UtcDaliActorRemoveConstraintTag"); + TestApplication application; + + Actor actor = Actor::New(); + + // 1. Apply Constraint1 and Constraint2, and test... + unsigned int result1 = 0u; + unsigned int result2 = 0u; + + unsigned constraint1Tag = 1u; + Constraint constraint1 = Constraint::New( actor, Actor::Property::COLOR, TestConstraintRef(result1, 1) ); + constraint1.SetTag( constraint1Tag ); + constraint1.Apply(); + + unsigned constraint2Tag = 2u; + Constraint constraint2 = Constraint::New( actor, Actor::Property::COLOR, TestConstraintRef(result2, 2) ); + constraint2.SetTag( constraint2Tag ); + constraint2.Apply(); + + Stage::GetCurrent().Add( actor ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( result1, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( result2, 2u, TEST_LOCATION ); + + // 2. Remove Constraint1 and test... + result1 = 0; + result2 = 0; + actor.RemoveConstraints(constraint1Tag); + // make color property dirty, which will trigger constraints to be reapplied. + actor.SetColor( Color::WHITE ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( result1, 0u, TEST_LOCATION ); ///< constraint 1 should not apply now. + DALI_TEST_EQUALS( result2, 2u, TEST_LOCATION ); + + // 3. Re-Apply Constraint1 and test... + result1 = 0; + result2 = 0; + constraint1.Apply(); + // make color property dirty, which will trigger constraints to be reapplied. + actor.SetColor( Color::WHITE ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( result1, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( result2, 2u, TEST_LOCATION ); + + // 2. Remove Constraint2 and test... + result1 = 0; + result2 = 0; + actor.RemoveConstraints(constraint2Tag); + // make color property dirty, which will trigger constraints to be reapplied. + actor.SetColor( Color::WHITE ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( result1, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( result2, 0u, TEST_LOCATION ); ///< constraint 2 should not apply now. + + // 2. Remove Constraint1 as well and test... + result1 = 0; + result2 = 0; + actor.RemoveConstraints(constraint1Tag); + // make color property dirty, which will trigger constraints to be reapplied. + actor.SetColor( Color::WHITE ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( result1, 0u, TEST_LOCATION ); ///< constraint 1 should not apply now. + DALI_TEST_EQUALS( result2, 0u, TEST_LOCATION ); ///< constraint 2 should not apply now. + END_TEST; +} + +int UtcDaliActorTouchedSignal(void) +{ + TestApplication application; + + gTouchCallBackCalled = false; + + // get the root layer + Actor actor = Stage::GetCurrent().GetRootLayer(); + DALI_TEST_CHECK( gTouchCallBackCalled == false ); + + application.SendNotification(); + application.Render(); + + // connect to its touch signal + actor.TouchedSignal().Connect( TestCallback ); + + // simulate a touch event in the middle of the screen + Vector2 touchPoint( Stage::GetCurrent().GetSize() * 0.5 ); + Dali::TouchPoint point( 1, TouchPoint::Down, touchPoint.x, touchPoint.y ); + Dali::Integration::TouchEvent event; + event.AddPoint( point ); + application.ProcessEvent( event ); + + DALI_TEST_CHECK( gTouchCallBackCalled == true ); + END_TEST; +} + +int UtcDaliActorHoveredSignal(void) +{ + TestApplication application; + + gHoverCallBackCalled = false; + + // get the root layer + Actor actor = Stage::GetCurrent().GetRootLayer(); + DALI_TEST_CHECK( gHoverCallBackCalled == false ); + + application.SendNotification(); + application.Render(); + + // connect to its hover signal + actor.HoveredSignal().Connect( TestCallback3 ); + + // simulate a hover event in the middle of the screen + Vector2 touchPoint( Stage::GetCurrent().GetSize() * 0.5 ); + Dali::TouchPoint point( 1, TouchPoint::Motion, touchPoint.x, touchPoint.y ); + Dali::Integration::HoverEvent event; + event.AddPoint( point ); + application.ProcessEvent( event ); + + DALI_TEST_CHECK( gHoverCallBackCalled == true ); + END_TEST; +} + +int UtcDaliActorOnOffStageSignal(void) +{ + tet_infoline("Testing Dali::Actor::OnStageSignal() and OffStageSignal()"); + + TestApplication application; + + // clean test data + gOnStageCallBackCalled = gOffStageCallBackCalled = 0; + gActorNamesOnOffStage.clear(); + + Actor parent = Actor::New(); + parent.SetName( "parent" ); + parent.OnStageSignal().Connect( OnStageCallback ); + parent.OffStageSignal().Connect( OffStageCallback ); + // sanity check + DALI_TEST_CHECK( gOnStageCallBackCalled == 0 ); + DALI_TEST_CHECK( gOffStageCallBackCalled == 0 ); + + // add parent to stage + Stage::GetCurrent().Add( parent ); + // onstage emitted, offstage not + DALI_TEST_EQUALS( gOnStageCallBackCalled, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( gOffStageCallBackCalled, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( "parent", gActorNamesOnOffStage[ 0 ], TEST_LOCATION ); + + // test adding a child, should get onstage emitted + // clean test data + gOnStageCallBackCalled = gOffStageCallBackCalled = 0; + gActorNamesOnOffStage.clear(); + + Actor child = Actor::New(); + child.SetName( "child" ); + child.OnStageSignal().Connect( OnStageCallback ); + child.OffStageSignal().Connect( OffStageCallback ); + parent.Add( child ); // add child + // onstage emitted, offstage not + DALI_TEST_EQUALS( gOnStageCallBackCalled, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( gOffStageCallBackCalled, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( "child", gActorNamesOnOffStage[ 0 ], TEST_LOCATION ); + + // test removing parent from stage + // clean test data + gOnStageCallBackCalled = gOffStageCallBackCalled = 0; + gActorNamesOnOffStage.clear(); + + Stage::GetCurrent().Remove( parent ); + // onstage not emitted, offstage is + DALI_TEST_EQUALS( gOnStageCallBackCalled, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( gOffStageCallBackCalled, 2, TEST_LOCATION ); + DALI_TEST_EQUALS( "child", gActorNamesOnOffStage[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "parent", gActorNamesOnOffStage[ 1 ], TEST_LOCATION ); + + // test adding parent back to stage + // clean test data + gOnStageCallBackCalled = gOffStageCallBackCalled = 0; + gActorNamesOnOffStage.clear(); + + Stage::GetCurrent().Add( parent ); + // onstage emitted, offstage not + DALI_TEST_EQUALS( gOnStageCallBackCalled, 2, TEST_LOCATION ); + DALI_TEST_EQUALS( gOffStageCallBackCalled, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( "parent", gActorNamesOnOffStage[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "child", gActorNamesOnOffStage[ 1 ], TEST_LOCATION ); + + // test removing child + // clean test data + gOnStageCallBackCalled = gOffStageCallBackCalled = 0; + gActorNamesOnOffStage.clear(); + + parent.Remove( child ); + // onstage not emitted, offstage is + DALI_TEST_EQUALS( gOnStageCallBackCalled, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( gOffStageCallBackCalled, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( "child", gActorNamesOnOffStage[ 0 ], TEST_LOCATION ); + + // test removing parent + // clean test data + gOnStageCallBackCalled = gOffStageCallBackCalled = 0; + gActorNamesOnOffStage.clear(); + + Stage::GetCurrent().Remove( parent ); + // onstage not emitted, offstage is + DALI_TEST_EQUALS( gOnStageCallBackCalled, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( gOffStageCallBackCalled, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( "parent", gActorNamesOnOffStage[ 0 ], TEST_LOCATION ); + END_TEST; +} + +int UtcDaliActorFindChildByName(void) +{ + tet_infoline("Testing Dali::Actor::FindChildByName()"); + TestApplication application; + + Actor parent = Actor::New(); + parent.SetName( "parent" ); + Actor first = Actor::New(); + first .SetName( "first" ); + Actor second = Actor::New(); + second.SetName( "second" ); + + parent.Add(first); + first.Add(second); + + Actor found = parent.FindChildByName( "foo" ); + DALI_TEST_CHECK( !found ); + + found = parent.FindChildByName( "parent" ); + DALI_TEST_CHECK( found == parent ); + + found = parent.FindChildByName( "first" ); + DALI_TEST_CHECK( found == first ); + + found = parent.FindChildByName( "second" ); + DALI_TEST_CHECK( found == second ); + END_TEST; +} + +int UtcDaliActorFindChildById(void) +{ + tet_infoline("Testing Dali::Actor::UtcDaliActorFindChildById()"); + TestApplication application; + + Actor parent = Actor::New(); + Actor first = Actor::New(); + Actor second = Actor::New(); + + parent.Add(first); + first.Add(second); + + Actor found = parent.FindChildById( 100000 ); + DALI_TEST_CHECK( !found ); + + found = parent.FindChildById( parent.GetId() ); + DALI_TEST_CHECK( found == parent ); + + found = parent.FindChildById( first.GetId() ); + DALI_TEST_CHECK( found == first ); + + found = parent.FindChildById( second.GetId() ); + DALI_TEST_CHECK( found == second ); + END_TEST; +} + +int UtcDaliActorHitTest(void) +{ + struct HitTestData + { + public: + HitTestData( const Vector3& scale, const Vector2& touchPoint, bool result ) + : mScale( scale ), + mTouchPoint( touchPoint ), + mResult( result ) + {} + + Vector3 mScale; + Vector2 mTouchPoint; + bool mResult; + }; + + TestApplication application; + tet_infoline(" UtcDaliActorHitTest"); + + // Fill a vector with different hit tests. + struct HitTestData* hitTestData[] = { + // scale touch point result + new HitTestData( Vector3( 100.f, 100.f, 1.f ), Vector2( 289.f, 400.f ), true ), // touch point close to the right edge (inside) + new HitTestData( Vector3( 100.f, 100.f, 1.f ), Vector2( 291.f, 400.f ), false ), // touch point close to the right edge (outside) + new HitTestData( Vector3( 110.f, 100.f, 1.f ), Vector2( 291.f, 400.f ), true ), // same point as above with a wider scale. Should be inside. + new HitTestData( Vector3( 100.f, 100.f, 1.f ), Vector2( 200.f, 451.f ), false ), // touch point close to the down edge (outside) + new HitTestData( Vector3( 100.f, 110.f, 1.f ), Vector2( 200.f, 451.f ), true ), // same point as above with a wider scale. Should be inside. + NULL, + }; + + // get the root layer + Actor actor = Actor::New(); + actor.SetAnchorPoint( AnchorPoint::CENTER ); + actor.SetParentOrigin( ParentOrigin::CENTER ); + + Stage::GetCurrent().Add( actor ); + + gTouchCallBackCalled = false; + + unsigned int index = 0; + while( NULL != hitTestData[index] ) + { + actor.SetSize( 1.f, 1.f ); + actor.SetScale( hitTestData[index]->mScale.x, hitTestData[index]->mScale.y, hitTestData[index]->mScale.z ); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( !gTouchCallBackCalled ); + + // connect to its touch signal + actor.TouchedSignal().Connect(TestCallback); + + Dali::TouchPoint point( 0, TouchPoint::Down, hitTestData[index]->mTouchPoint.x, hitTestData[index]->mTouchPoint.y ); + Dali::Integration::TouchEvent event; + event.AddPoint( point ); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + application.ProcessEvent( event ); + + DALI_TEST_CHECK( gTouchCallBackCalled == hitTestData[index]->mResult ); + + if( gTouchCallBackCalled != hitTestData[index]->mResult ) + tet_printf("Test failed:\nScale %f %f %f\nTouchPoint %f, %f\nResult %d\n", + hitTestData[index]->mScale.x, hitTestData[index]->mScale.y, hitTestData[index]->mScale.z, + hitTestData[index]->mTouchPoint.x, hitTestData[index]->mTouchPoint.y, + hitTestData[index]->mResult ); + + gTouchCallBackCalled = false; + ++index; + } + END_TEST; +} + +int UtcDaliActorSetDrawMode(void) +{ + TestApplication app; + tet_infoline(" UtcDaliActorSetDrawModeOverlay"); + + Actor a = Actor::New(); + + Stage::GetCurrent().Add(a); + app.SendNotification(); + app.Render(0); + app.SendNotification(); + app.Render(1); + + DALI_TEST_CHECK( DrawMode::NORMAL == a.GetDrawMode() ); // Ensure overlay is off by default + + a.SetDrawMode( DrawMode::OVERLAY_2D ); + app.SendNotification(); + app.Render(1); + + DALI_TEST_CHECK( DrawMode::OVERLAY_2D == a.GetDrawMode() ); // Check Actor is overlay + + a.SetDrawMode( DrawMode::STENCIL ); + app.SendNotification(); + app.Render(1); + + DALI_TEST_CHECK( DrawMode::STENCIL == a.GetDrawMode() ); // Check Actor is stencil, not overlay + + a.SetDrawMode( DrawMode::NORMAL ); + app.SendNotification(); + app.Render(1); + + DALI_TEST_CHECK( DrawMode::NORMAL == a.GetDrawMode() ); // Check Actor is not stencil + END_TEST; +} + +int UtcDaliActorSetDrawModeOverlayRender(void) +{ + TestApplication app; + tet_infoline(" UtcDaliActorSetDrawModeOverlayRender"); + + app.SendNotification(); + app.Render(1); + + std::vector ids; + ids.push_back( 8 ); // first rendered actor + ids.push_back( 9 ); // second rendered actor + ids.push_back( 10 ); // third rendered actor + app.GetGlAbstraction().SetNextTextureIds( ids ); + + BufferImage imageA = BufferImage::New(16, 16); + BufferImage imageB = BufferImage::New(16, 16); + BufferImage imageC = BufferImage::New(16, 16); + ImageActor a = ImageActor::New( imageA ); + ImageActor b = ImageActor::New( imageB ); + ImageActor c = ImageActor::New( imageC ); + + // Render a,b,c as regular non-overlays. so order will be: + // a (8) + // b (9) + // c (10) + Stage::GetCurrent().Add(a); + Stage::GetCurrent().Add(b); + Stage::GetCurrent().Add(c); + + app.SendNotification(); + app.Render(1); + + // Should be 3 textures changes. + const std::vector& boundTextures = app.GetGlAbstraction().GetBoundTextures( GL_TEXTURE0 ); + typedef std::vector::size_type TextureSize; + DALI_TEST_EQUALS( boundTextures.size(), static_cast( 3 ), TEST_LOCATION ); + if( boundTextures.size() == 3 ) + { + DALI_TEST_CHECK( boundTextures[0] == 8u ); + DALI_TEST_CHECK( boundTextures[1] == 9u ); + DALI_TEST_CHECK( boundTextures[2] == 10u ); + } + + // Now texture ids have been set, we can monitor their render order. + // render a as an overlay (last), so order will be: + // b (9) + // c (10) + // a (8) + a.SetDrawMode( DrawMode::OVERLAY_2D ); + app.GetGlAbstraction().ClearBoundTextures(); + + app.SendNotification(); + app.Render(1); + + // Should be 3 texture changes. + DALI_TEST_EQUALS( boundTextures.size(), static_cast(3), TEST_LOCATION ); + if( boundTextures.size() == 3 ) + { + DALI_TEST_CHECK( boundTextures[0] == 9u ); + DALI_TEST_CHECK( boundTextures[1] == 10u ); + DALI_TEST_CHECK( boundTextures[2] == 8u ); + } + END_TEST; +} + +int UtcDaliActorGetCurrentWorldMatrix(void) +{ + TestApplication app; + tet_infoline(" UtcDaliActorGetCurrentWorldMatrix"); + + Actor parent = Actor::New(); + parent.SetParentOrigin(ParentOrigin::CENTER); + parent.SetAnchorPoint(AnchorPoint::CENTER); + Vector3 parentPosition( 10.0f, 20.0f, 30.0f); + Radian rotationAngle(Degree(85.0f)); + Quaternion parentRotation(rotationAngle, Vector3::ZAXIS); + Vector3 parentScale( 1.0f, 2.0f, 3.0f ); + parent.SetPosition( parentPosition ); + parent.SetOrientation( parentRotation ); + parent.SetScale( parentScale ); + Stage::GetCurrent().Add( parent ); + + Actor child = Actor::New(); + child.SetParentOrigin(ParentOrigin::CENTER); + Vector3 childPosition( 0.0f, 0.0f, 100.0f ); + Radian childRotationAngle(Degree(23.0f)); + Quaternion childRotation( childRotationAngle, Vector3::YAXIS ); + Vector3 childScale( 2.0f, 2.0f, 2.0f ); + child.SetPosition( childPosition ); + child.SetOrientation( childRotation ); + child.SetScale( childScale ); + parent.Add( child ); + + // The actors should not have a world matrix yet + DALI_TEST_EQUALS( parent.GetCurrentWorldMatrix(), Matrix::IDENTITY, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldMatrix(), Matrix::IDENTITY, 0.001, TEST_LOCATION ); + + app.SendNotification(); + app.Render(0); + app.Render(); + app.SendNotification(); + + Matrix parentMatrix(false); + parentMatrix.SetTransformComponents(parentScale, parentRotation, parentPosition); + + Vector3 childWorldPosition = parentPosition + parentRotation * parentScale * childPosition; + Quaternion childWorldRotation = parentRotation * childRotation; + Vector3 childWorldScale = parentScale * childScale; + + Matrix childWorldMatrix(false); + childWorldMatrix.SetTransformComponents(childWorldScale, childWorldRotation, childWorldPosition); + + DALI_TEST_EQUALS( parent.GetCurrentWorldMatrix(), parentMatrix, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldMatrix(), childWorldMatrix, 0.001, TEST_LOCATION ); + END_TEST; +} + + + +int UtcDaliActorConstrainedToWorldMatrix(void) +{ + TestApplication app; + tet_infoline(" UtcDaliActorConstrainedToWorldMatrix"); + + Actor parent = Actor::New(); + parent.SetParentOrigin(ParentOrigin::CENTER); + parent.SetAnchorPoint(AnchorPoint::CENTER); + Vector3 parentPosition( 10.0f, 20.0f, 30.0f); + Radian rotationAngle(Degree(85.0f)); + Quaternion parentRotation(rotationAngle, Vector3::ZAXIS); + Vector3 parentScale( 1.0f, 2.0f, 3.0f ); + parent.SetPosition( parentPosition ); + parent.SetOrientation( parentRotation ); + parent.SetScale( parentScale ); + Stage::GetCurrent().Add( parent ); + + Actor child = Actor::New(); + child.SetParentOrigin(ParentOrigin::CENTER); + Constraint posConstraint = Constraint::New( child, Actor::Property::POSITION, PositionComponentConstraint() ); + posConstraint.AddSource( Source( parent, Actor::Property::WORLD_MATRIX ) ); + posConstraint.Apply(); + + Stage::GetCurrent().Add( child ); + + // The actors should not have a world matrix yet + DALI_TEST_EQUALS( parent.GetCurrentWorldMatrix(), Matrix::IDENTITY, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentWorldMatrix(), Matrix::IDENTITY, 0.001, TEST_LOCATION ); + + app.SendNotification(); + app.Render(0); + app.Render(); + app.SendNotification(); + + Matrix parentMatrix(false); + parentMatrix.SetTransformComponents(parentScale, parentRotation, parentPosition); + + DALI_TEST_EQUALS( parent.GetCurrentWorldMatrix(), parentMatrix, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( child.GetCurrentPosition(), parent.GetCurrentPosition(), 0.001, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliActorUnparent(void) +{ + TestApplication app; + tet_infoline(" UtcDaliActorUnparent"); + + Actor parent = Actor::New(); + Stage::GetCurrent().Add( parent ); + + Actor child = Actor::New(); + + DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION ); + DALI_TEST_CHECK( !child.GetParent() ); + + // Test that calling Unparent with no parent is a NOOP + child.Unparent(); + + DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION ); + DALI_TEST_CHECK( !child.GetParent() ); + + // Test that Unparent works + parent.Add( child ); + + DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION ); + DALI_TEST_CHECK( parent == child.GetParent() ); + + child.Unparent(); + + DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION ); + DALI_TEST_CHECK( !child.GetParent() ); + + // Test that UnparentAndReset works + parent.Add( child ); + + DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION ); + DALI_TEST_CHECK( parent == child.GetParent() ); + + UnparentAndReset( child ); + + DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION ); + DALI_TEST_CHECK( !child ); + + // Test that UnparentAndReset is a NOOP with empty handle + UnparentAndReset( child ); + + DALI_TEST_CHECK( !child ); + END_TEST; +} + +int UtcDaliActorGetChildAt(void) +{ + TestApplication app; + tet_infoline(" UtcDaliActorGetChildAt"); + + Actor parent = Actor::New(); + Stage::GetCurrent().Add( parent ); + + Actor child0 = Actor::New(); + parent.Add( child0 ); + + Actor child1 = Actor::New(); + parent.Add( child1 ); + + Actor child2 = Actor::New(); + parent.Add( child2 ); + + DALI_TEST_EQUALS( parent.GetChildAt( 0 ), child0, TEST_LOCATION ); + DALI_TEST_EQUALS( parent.GetChildAt( 1 ), child1, TEST_LOCATION ); + DALI_TEST_EQUALS( parent.GetChildAt( 2 ), child2, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliActorSetGetOverlay(void) +{ + TestApplication app; + tet_infoline(" UtcDaliActorSetGetOverlay"); + + Actor parent = Actor::New(); + parent.SetDrawMode(DrawMode::OVERLAY_2D ); + DALI_TEST_CHECK( parent.GetDrawMode() == DrawMode::OVERLAY_2D ); + END_TEST; +} + + +int UtcDaliActorCreateDestroy(void) +{ + Actor* actor = new Actor; + DALI_TEST_CHECK( actor ); + delete actor; + END_TEST; +} + +namespace +{ +struct PropertyStringIndex +{ + const char * const name; + const Property::Index index; + const Property::Type type; +}; + +const PropertyStringIndex PROPERTY_TABLE[] = +{ + { "parent-origin", Actor::Property::PARENT_ORIGIN, Property::VECTOR3 }, + { "parent-origin-x", Actor::Property::PARENT_ORIGIN_X, Property::FLOAT }, + { "parent-origin-y", Actor::Property::PARENT_ORIGIN_Y, Property::FLOAT }, + { "parent-origin-z", Actor::Property::PARENT_ORIGIN_Z, Property::FLOAT }, + { "anchor-point", Actor::Property::ANCHOR_POINT, Property::VECTOR3 }, + { "anchor-point-x", Actor::Property::ANCHOR_POINT_X, Property::FLOAT }, + { "anchor-point-y", Actor::Property::ANCHOR_POINT_Y, Property::FLOAT }, + { "anchor-point-z", Actor::Property::ANCHOR_POINT_Z, Property::FLOAT }, + { "size", Actor::Property::SIZE, Property::VECTOR3 }, + { "size-width", Actor::Property::SIZE_WIDTH, Property::FLOAT }, + { "size-height", Actor::Property::SIZE_HEIGHT, Property::FLOAT }, + { "size-depth", Actor::Property::SIZE_DEPTH, Property::FLOAT }, + { "position", Actor::Property::POSITION, Property::VECTOR3 }, + { "position-x", Actor::Property::POSITION_X, Property::FLOAT }, + { "position-y", Actor::Property::POSITION_Y, Property::FLOAT }, + { "position-z", Actor::Property::POSITION_Z, Property::FLOAT }, + { "world-position", Actor::Property::WORLD_POSITION, Property::VECTOR3 }, + { "world-position-x", Actor::Property::WORLD_POSITION_X, Property::FLOAT }, + { "world-position-y", Actor::Property::WORLD_POSITION_Y, Property::FLOAT }, + { "world-position-z", Actor::Property::WORLD_POSITION_Z, Property::FLOAT }, + { "orientation", Actor::Property::ORIENTATION, Property::ROTATION }, + { "world-orientation", Actor::Property::WORLD_ORIENTATION, Property::ROTATION }, + { "scale", Actor::Property::SCALE, Property::VECTOR3 }, + { "scale-x", Actor::Property::SCALE_X, Property::FLOAT }, + { "scale-y", Actor::Property::SCALE_Y, Property::FLOAT }, + { "scale-z", Actor::Property::SCALE_Z, Property::FLOAT }, + { "world-scale", Actor::Property::WORLD_SCALE, Property::VECTOR3 }, + { "visible", Actor::Property::VISIBLE, Property::BOOLEAN }, + { "color", Actor::Property::COLOR, Property::VECTOR4 }, + { "color-red", Actor::Property::COLOR_RED, Property::FLOAT }, + { "color-green", Actor::Property::COLOR_GREEN, Property::FLOAT }, + { "color-blue", Actor::Property::COLOR_BLUE, Property::FLOAT }, + { "color-alpha", Actor::Property::COLOR_ALPHA, Property::FLOAT }, + { "world-color", Actor::Property::WORLD_COLOR, Property::VECTOR4 }, + { "world-matrix", Actor::Property::WORLD_MATRIX, Property::MATRIX }, + { "name", Actor::Property::NAME, Property::STRING }, + { "sensitive", Actor::Property::SENSITIVE, Property::BOOLEAN }, + { "leave-required", Actor::Property::LEAVE_REQUIRED, Property::BOOLEAN }, + { "inherit-orientation", Actor::Property::INHERIT_ORIENTATION, Property::BOOLEAN }, + { "inherit-scale", Actor::Property::INHERIT_SCALE, Property::BOOLEAN }, + { "color-mode", Actor::Property::COLOR_MODE, Property::STRING }, + { "position-inheritance", Actor::Property::POSITION_INHERITANCE, Property::STRING }, + { "draw-mode", Actor::Property::DRAW_MODE, Property::STRING }, + { "size-mode-factor", Actor::Property::SIZE_MODE_FACTOR, Property::VECTOR3 }, + { "width-resize-policy", Actor::Property::WIDTH_RESIZE_POLICY, Property::STRING }, + { "height-resize-policy", Actor::Property::HEIGHT_RESIZE_POLICY, Property::STRING }, + { "size-scale-policy", Actor::Property::SIZE_SCALE_POLICY, Property::STRING }, + { "width-for-height", Actor::Property::WIDTH_FOR_HEIGHT, Property::BOOLEAN }, + { "height-for-width", Actor::Property::HEIGHT_FOR_WIDTH, Property::BOOLEAN }, + { "padding", Actor::Property::PADDING, Property::VECTOR4 }, + { "minimum-size", Actor::Property::MINIMUM_SIZE, Property::VECTOR2 }, + { "maximum-size", Actor::Property::MAXIMUM_SIZE, Property::VECTOR2 }, +}; +const unsigned int PROPERTY_TABLE_COUNT = sizeof( PROPERTY_TABLE ) / sizeof( PROPERTY_TABLE[0] ); +} // unnamed namespace + +int UtcDaliActorProperties(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + for ( unsigned int i = 0; i < PROPERTY_TABLE_COUNT; ++i ) + { + tet_printf( "Checking %s == %d\n", PROPERTY_TABLE[i].name, PROPERTY_TABLE[i].index ); + DALI_TEST_EQUALS( actor.GetPropertyName( PROPERTY_TABLE[i].index ), PROPERTY_TABLE[i].name, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetPropertyIndex( PROPERTY_TABLE[i].name ), PROPERTY_TABLE[i].index, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetPropertyType( PROPERTY_TABLE[i].index ), PROPERTY_TABLE[i].type, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliRelayoutProperties_ResizePolicies(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + // Defaults + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::WIDTH_RESIZE_POLICY ).Get< std::string >(), "USE_NATURAL_SIZE", TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::HEIGHT_RESIZE_POLICY ).Get< std::string >(), "USE_NATURAL_SIZE", TEST_LOCATION ); + + // Set resize policy for all dimensions + actor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i) + { + DALI_TEST_EQUALS( actor.GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) ), ResizePolicy::USE_NATURAL_SIZE, TEST_LOCATION ); + } + + // Set individual dimensions + const char* const widthPolicy = "FILL_TO_PARENT"; + const char* const heightPolicy = "FIXED"; + + actor.SetProperty( Actor::Property::WIDTH_RESIZE_POLICY, widthPolicy ); + actor.SetProperty( Actor::Property::HEIGHT_RESIZE_POLICY, heightPolicy ); + + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::WIDTH_RESIZE_POLICY ).Get< std::string >(), widthPolicy, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::HEIGHT_RESIZE_POLICY ).Get< std::string >(), heightPolicy, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRelayoutProperties_SizeScalePolicy(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + // Defaults + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::SIZE_SCALE_POLICY ).Get< std::string >(), "USE_SIZE_SET", TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetSizeScalePolicy(), SizeScalePolicy::USE_SIZE_SET, TEST_LOCATION ); + + SizeScalePolicy::Type policy = SizeScalePolicy::FILL_WITH_ASPECT_RATIO; + actor.SetSizeScalePolicy( policy ); + DALI_TEST_EQUALS( actor.GetSizeScalePolicy(), policy, TEST_LOCATION ); + + // Set + const char* const policy1 = "FIT_WITH_ASPECT_RATIO"; + const char* const policy2 = "FILL_WITH_ASPECT_RATIO"; + + actor.SetProperty( Actor::Property::SIZE_SCALE_POLICY, policy1 ); + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::SIZE_SCALE_POLICY ).Get< std::string >(), policy1, TEST_LOCATION ); + + actor.SetProperty( Actor::Property::SIZE_SCALE_POLICY, policy2 ); + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::SIZE_SCALE_POLICY ).Get< std::string >(), policy2, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRelayoutProperties_SizeModeFactor(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + // Defaults + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::SIZE_MODE_FACTOR ).Get< Vector3 >(), Vector3( 1.0f, 1.0f, 1.0f ), TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetSizeModeFactor(), Vector3( 1.0f, 1.0f, 1.0f ), TEST_LOCATION ); + + Vector3 sizeMode( 1.0f, 2.0f, 3.0f ); + actor.SetSizeModeFactor( sizeMode ); + DALI_TEST_EQUALS( actor.GetSizeModeFactor(), sizeMode, TEST_LOCATION ); + + // Set + Vector3 sizeMode1( 2.0f, 3.0f, 4.0f ); + + actor.SetProperty( Actor::Property::SIZE_MODE_FACTOR, sizeMode1 ); + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::SIZE_MODE_FACTOR ).Get< Vector3 >(), sizeMode1, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRelayoutProperties_DimensionDependency(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + // Defaults + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::WIDTH_FOR_HEIGHT ).Get< bool >(), false, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::HEIGHT_FOR_WIDTH ).Get< bool >(), false, TEST_LOCATION ); + + // Set + actor.SetProperty( Actor::Property::WIDTH_FOR_HEIGHT, true ); + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::WIDTH_FOR_HEIGHT ).Get< bool >(), true, TEST_LOCATION ); + + actor.SetProperty( Actor::Property::HEIGHT_FOR_WIDTH, true ); + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::HEIGHT_FOR_WIDTH ).Get< bool >(), true, TEST_LOCATION ); + + // Test setting another resize policy + actor.SetProperty( Actor::Property::WIDTH_RESIZE_POLICY, "FIXED" ); + DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::WIDTH_FOR_HEIGHT ).Get< bool >(), false, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRelayoutProperties_Padding(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + // Data + Vector4 padding( 1.0f, 2.0f, 3.0f, 4.0f ); + + // PADDING + actor.SetProperty( Actor::Property::PADDING, padding ); + Vector4 paddingResult = actor.GetProperty( Actor::Property::PADDING ).Get< Vector4 >(); + + DALI_TEST_EQUALS( paddingResult, padding, Math::MACHINE_EPSILON_0, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRelayoutProperties_MinimumMaximumSize(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + // Data + Vector2 minSize( 1.0f, 2.0f ); + + actor.SetProperty( Actor::Property::MINIMUM_SIZE, minSize ); + Vector2 resultMin = actor.GetProperty( Actor::Property::MINIMUM_SIZE ).Get< Vector2 >(); + + DALI_TEST_EQUALS( resultMin, minSize, Math::MACHINE_EPSILON_0, TEST_LOCATION ); + + Vector2 maxSize( 3.0f, 4.0f ); + + actor.SetProperty( Actor::Property::MAXIMUM_SIZE, maxSize ); + Vector2 resultMax = actor.GetProperty( Actor::Property::MAXIMUM_SIZE ).Get< Vector2 >(); + + DALI_TEST_EQUALS( resultMax, maxSize, Math::MACHINE_EPSILON_0, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliActorGetHeightForWidth(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + DALI_TEST_EQUALS( actor.GetHeightForWidth( 1.0f ), 1.0f, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliActorGetWidthForHeight(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + DALI_TEST_EQUALS( actor.GetWidthForHeight( 1.0f ), 1.0f, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliActorGetRelayoutSize(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + // Add actor to stage + Stage::GetCurrent().Add( actor ); + + DALI_TEST_EQUALS( actor.GetRelayoutSize( Dimension::WIDTH ), 0.0f, TEST_LOCATION ); + + actor.SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH ); + actor.SetSize( Vector2( 1.0f, 0.0f ) ); + + // Flush the queue and render once + app.SendNotification(); + app.Render(); + + DALI_TEST_EQUALS( actor.GetRelayoutSize( Dimension::WIDTH ), 1.0f, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliActorSetPadding(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + Padding padding; + actor.GetPadding( padding ); + + DALI_TEST_EQUALS( padding.left, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( padding.right, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( padding.bottom, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( padding.top, 0.0f, TEST_LOCATION ); + + Padding padding2( 1.0f, 2.0f, 3.0f, 4.0f ); + actor.SetPadding( padding2 ); + + actor.GetPadding( padding ); + + DALI_TEST_EQUALS( padding.left, padding2.left, TEST_LOCATION ); + DALI_TEST_EQUALS( padding.right, padding2.right, TEST_LOCATION ); + DALI_TEST_EQUALS( padding.bottom, padding2.bottom, TEST_LOCATION ); + DALI_TEST_EQUALS( padding.top, padding2.top, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliActorSetMinimumSize(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + Vector2 size = actor.GetMinimumSize(); + + DALI_TEST_EQUALS( size.width, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( size.height, 0.0f, TEST_LOCATION ); + + Vector2 size2( 1.0f, 2.0f ); + actor.SetMinimumSize( size2 ); + + size = actor.GetMinimumSize(); + + DALI_TEST_EQUALS( size.width, size2.width, TEST_LOCATION ); + DALI_TEST_EQUALS( size.height, size2.height, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliActorSetMaximumSize(void) +{ + TestApplication app; + + Actor actor = Actor::New(); + + Vector2 size = actor.GetMaximumSize(); + + DALI_TEST_EQUALS( size.width, FLT_MAX, TEST_LOCATION ); + DALI_TEST_EQUALS( size.height, FLT_MAX, TEST_LOCATION ); + + Vector2 size2( 1.0f, 2.0f ); + actor.SetMaximumSize( size2 ); + + size = actor.GetMaximumSize(); + + DALI_TEST_EQUALS( size.width, size2.width, TEST_LOCATION ); + DALI_TEST_EQUALS( size.height, size2.height, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliActorOnRelayoutSignal(void) +{ + tet_infoline("Testing Dali::Actor::OnRelayoutSignal()"); + + TestApplication application; + + // Clean test data + gOnRelayoutCallBackCalled = 0; + gActorNamesRelayout.clear(); + + Actor actor = Actor::New(); + actor.SetName( "actor" ); + actor.OnRelayoutSignal().Connect( OnRelayoutCallback ); + + // Sanity check + DALI_TEST_CHECK( gOnRelayoutCallBackCalled == 0 ); + + // Add actor to stage + Stage::GetCurrent().Add( actor ); + + actor.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS ); + actor.SetSize( Vector2( 1.0f, 2.0 ) ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + // OnRelayout emitted + DALI_TEST_EQUALS( gOnRelayoutCallBackCalled, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( "actor", gActorNamesRelayout[ 0 ], TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliActorGetHierachyDepth(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Actor::GetHierarchyDepth()"); + + + /* Build tree of actors: + * + * Depth + * + * A (parent) 1 + * / \ + * B C 2` + * / \ \ + * D E F 3 + * + * GetHierarchyDepth should return 1 for A, 2 for B and C, and 3 for D, E and F. + */ + Stage stage( Stage::GetCurrent() ); + + Actor actorA = Actor::New(); + Actor actorB = Actor::New(); + Actor actorC = Actor::New(); + Actor actorD = Actor::New(); + Actor actorE = Actor::New(); + Actor actorF = Actor::New(); + + //Test that root actor has depth equal 0 + DALI_TEST_EQUALS( 0, stage.GetRootLayer().GetHierarchyDepth(), TEST_LOCATION ); + + //Test actors return depth -1 when not connected to the tree + DALI_TEST_EQUALS( -1, actorA.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( -1, actorB.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( -1, actorC.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( -1, actorD.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( -1, actorE.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( -1, actorF.GetHierarchyDepth(), TEST_LOCATION ); + + //Create the hierarchy + stage.Add( actorA ); + actorA.Add( actorB ); + actorA.Add( actorC ); + actorB.Add( actorD ); + actorB.Add( actorE ); + actorC.Add( actorF ); + + //Test actors return correct depth + DALI_TEST_EQUALS( 1, actorA.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( 2, actorB.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( 2, actorC.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( 3, actorD.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( 3, actorE.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( 3, actorF.GetHierarchyDepth(), TEST_LOCATION ); + + //Removing actorB from the hierarchy. actorB, actorD and actorE should now have depth equal -1 + actorA.Remove( actorB ); + + DALI_TEST_EQUALS( -1, actorB.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( -1, actorD.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( -1, actorE.GetHierarchyDepth(), TEST_LOCATION ); + + //Removing actorA from the stage. All actors should have depth equal -1 + stage.Remove( actorA ); + + DALI_TEST_EQUALS( -1, actorA.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( -1, actorB.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( -1, actorC.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( -1, actorD.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( -1, actorE.GetHierarchyDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( -1, actorF.GetHierarchyDepth(), TEST_LOCATION ); + + END_TEST; +} + diff --git a/automated-tests/src/dali/utc-Dali-AlphaFunction.cpp b/automated-tests/src/dali/utc-Dali-AlphaFunction.cpp new file mode 100644 index 0000000..858a3eb --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-AlphaFunction.cpp @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +float customAlphaFunction( float progress ) +{ + return progress; +} + +void utc_dali_alpha_function_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_alpha_function_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliAlphaFunctionDefaultConstructorP(void) +{ + TestApplication application; + AlphaFunction alpha; + + //Should return the default alpha function + DALI_TEST_EQUALS( alpha.GetBuiltinFunction(), AlphaFunction::DEFAULT, TEST_LOCATION); + + //Check the mode is BUILTIN_FUNCTION + DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::BUILTIN_FUNCTION, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliAlphaFunctionConstructorFromBuiltinP(void) +{ + TestApplication application; + + //Construct the alpha function with a built-in function + AlphaFunction alpha( AlphaFunction::EASE_IN_OUT); + + //Check if the built-in alpha function is EASE_IN_OUT + DALI_TEST_EQUALS( alpha.GetBuiltinFunction(), AlphaFunction::EASE_IN_OUT, TEST_LOCATION); + + //Check the mode is BUILTIN_FUNCTION + DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::BUILTIN_FUNCTION, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliAlphaFunctionConstructorFromFunctionPointerdP(void) +{ + TestApplication application; + + //Construct the alpha function with a function pointer + AlphaFunction alpha( &customAlphaFunction ); + + //Check that the custom function points to the custom alpha function + DALI_TEST_EQUALS( alpha.GetCustomFunction(), &customAlphaFunction, TEST_LOCATION); + + //Check the mode is CUSTOM_FUNCTION + DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::CUSTOM_FUNCTION, TEST_LOCATION); + + + END_TEST; +} + +int UtcDaliAlphaFunctionConstructorFromControlPointsP(void) +{ + TestApplication application; + + //Construct the alpha function with two control points + Vector2 controlPoint0 = Vector2(0.0f,1.0f); + Vector2 controlPoint1 = Vector2(1.0f,0.0f); + AlphaFunction alpha(controlPoint0,controlPoint1); + + //Check if the control points have the correct value + Vector4 controlPoints = alpha.GetBezierControlPoints(); + DALI_TEST_EQUALS( Vector2(controlPoints.x,controlPoints.y), controlPoint0, TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(controlPoints.z,controlPoints.w), controlPoint1, TEST_LOCATION); + + //Check the mode is BEZIER + DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::BEZIER, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliAlphaFunctionConstructorFromControlPointsN(void) +{ + TestApplication application; + + //Construct the alpha function with two control points + Vector2 controlPoint0 = Vector2(-10.0f,1.0f); + Vector2 controlPoint1 = Vector2(10.0f,0.0f); + AlphaFunction alpha(controlPoint0,controlPoint1); + + //x components of the control points should have been clamped to [0,1] to ensure the curve is monotonic + Vector4 controlPoints = alpha.GetBezierControlPoints(); + DALI_TEST_EQUALS( Vector2(controlPoints.x,controlPoints.y), Vector2(0.0f,1.0f), TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(controlPoints.z,controlPoints.w), Vector2(1.0f,0.0f), TEST_LOCATION); + + //Check the mode is BEZIER + DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::BEZIER, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliAlphaFunctionGetBuiltinFunctionP(void) +{ + TestApplication application; + AlphaFunction alpha( AlphaFunction::EASE_IN); + + //Check if the builtin alpha function is EASE_IN + DALI_TEST_EQUALS( alpha.GetBuiltinFunction(), AlphaFunction::EASE_IN, TEST_LOCATION); + + //Check the mode is BUILTIN_FUNCTION + DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::BUILTIN_FUNCTION, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliAlphaFunctionGetCustomFunctionP(void) +{ + TestApplication application; + AlphaFunction alpha( &customAlphaFunction ); + + //Check that the custom function points to the custom alpha function + DALI_TEST_EQUALS( alpha.GetCustomFunction(), &customAlphaFunction, TEST_LOCATION); + + //Check the mode is CUSTOM_FUNCTION + DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::CUSTOM_FUNCTION, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliAlphaFunctionGetControlPointsFunctionP(void) +{ + TestApplication application; + + Vector2 controlPoint0 = Vector2(0.0f,1.0f); + Vector2 controlPoint1 = Vector2(1.0f,0.0f); + AlphaFunction alpha( controlPoint0,controlPoint1 ); + + //Check if the control points have the correct value + Vector4 controlPoints = alpha.GetBezierControlPoints(); + DALI_TEST_EQUALS( Vector2(controlPoints.x,controlPoints.y), controlPoint0, TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(controlPoints.z,controlPoints.w), controlPoint1, TEST_LOCATION); + + //Check the mode is BEZIER + DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::BEZIER, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliAlphaFunctionGetModeP(void) +{ + TestApplication application; + + //Create alpha function using a built-in function + AlphaFunction alphaBuiltin( AlphaFunction::EASE_IN); + + //Check the mode is BUILTIN_FUNCTION + DALI_TEST_EQUALS( alphaBuiltin.GetMode(), AlphaFunction::BUILTIN_FUNCTION, TEST_LOCATION); + + //Create alpha function with pointer to function + AlphaFunction alphaCustom( &customAlphaFunction ); + //Check the mode is CUSTOM_FUNCTION + DALI_TEST_EQUALS( alphaCustom.GetMode(), AlphaFunction::CUSTOM_FUNCTION, TEST_LOCATION); + + //Create alpha function with control points + Vector2 controlPoint0 = Vector2(0.0f,1.0f); + Vector2 controlPoint1 = Vector2(1.0f,0.0f); + AlphaFunction alphaBezier( controlPoint0,controlPoint1 ); + //Check the mode is BEZIER + DALI_TEST_EQUALS( alphaBezier.GetMode(), AlphaFunction::BEZIER, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliAlphaFunctionBezier(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a float property + float startValue(0.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetValue(1.0f); + + Vector2 controlPoint0 = Vector2(0.25f,0.5f); + Vector2 controlPoint1 = Vector2(0.75f,0.5f); + animation.AnimateTo(Property(actor, "test-property"), targetValue, AlphaFunction(controlPoint0,controlPoint1)); + + // Start the animation + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 20% progress */); + application.SendNotification(); + float epsilon(0.01f); + DALI_TEST_EQUALS( actor.GetProperty(index), 0.271964f, epsilon, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f) + 1u/*40% progress*/); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(index), 0.432387f, epsilon, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f) + 1u/*60% progress*/); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(index), 0.567613f, epsilon, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f) + 1u/*80% progress*/); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(index), 0.728037f, epsilon, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + END_TEST; +} + diff --git a/automated-tests/src/dali/utc-Dali-AngleAxis.cpp b/automated-tests/src/dali/utc-Dali-AngleAxis.cpp new file mode 100644 index 0000000..515ead5 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-AngleAxis.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + +void utc_dali_angle_axis_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_angle_axis_cleanup(void) +{ + test_return_value = TET_PASS; +} + + + +int UtcDaliAngleAxisNew01(void) +{ + TestApplication application; + + AngleAxis a; + DALI_TEST_EQUALS(float(a.angle), 0.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(a.axis, Vector3(0.0f, 0.0f, 0.0f), 0.001f, TEST_LOCATION); + END_TEST; +} + + + +int UtcDaliAngleAxisNew02(void) +{ + TestApplication application; + + Degree d(75.0f); + AngleAxis a(d, Vector3::XAXIS); + + DALI_TEST_EQUALS(a.angle, Radian(d), 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(a.axis, Vector3::XAXIS, 0.001f, TEST_LOCATION); + END_TEST; +} + + +int UtcDaliAngleAxisNew03(void) +{ + TestApplication application; + + Radian r(Math::PI_2); + AngleAxis a(r, Vector3::ZAXIS); + + // AngleAxis stores its angle as a degree, so should only do degree comparison. + DALI_TEST_EQUALS(a.angle, Radian(Math::PI_2), 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(a.axis, Vector3::ZAXIS, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliAngleAxisAssign(void) +{ + TestApplication application; + + Radian r(Math::PI_2); + AngleAxis a(r, Vector3::ZAXIS); + + AngleAxis b = a; + + // AngleAxis stores its angle as a degree, so should only do degree comparison. + DALI_TEST_EQUALS(b.angle, Radian(Math::PI_2), 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(b.axis, Vector3::ZAXIS, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliAngleAxisCopy(void) +{ + TestApplication application; + + Radian r(Math::PI_2); + AngleAxis a(r, Vector3::ZAXIS); + AngleAxis b(a); + + // AngleAxis stores its angle as a degree, so should only do degree comparison. + DALI_TEST_EQUALS(b.angle, Radian(Math::PI_2), 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(b.axis, Vector3::ZAXIS, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliAngleAxisEqual(void) +{ + TestApplication application; + + Radian r(Math::PI_2); + AngleAxis a(r, Vector3::ZAXIS); + AngleAxis b(a); + + tet_result((a == b) ? TET_PASS : TET_FAIL); + + b.axis = Vector3::YAXIS; + tet_result(!(a == b) ? TET_PASS : TET_FAIL); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Animation.cpp b/automated-tests/src/dali/utc-Dali-Animation.cpp new file mode 100644 index 0000000..25f5235 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Animation.cpp @@ -0,0 +1,8925 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include + +using std::max; +using namespace Dali; + +void utc_dali_animation_startuP(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_animation_cleanuP(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +static const float ROTATION_EPSILON = 0.0001f; +static const float VECTOR4_EPSILON = 0.0001f; + +// Functor to test whether a Finish signal is emitted +struct AnimationFinishCheck +{ + AnimationFinishCheck(bool& signalReceived) + : mSignalReceived(signalReceived) + { + } + + void operator()(Animation& animation) + { + mSignalReceived = true; + } + + void Reset() + { + mSignalReceived = false; + } + + void CheckSignalReceived() + { + if (!mSignalReceived) + { + tet_printf("Expected Finish signal was not received\n"); + tet_result(TET_FAIL); + } + else + { + tet_result(TET_PASS); + } + } + + void CheckSignalNotReceived() + { + if (mSignalReceived) + { + tet_printf("Unexpected Finish signal was received\n"); + tet_result(TET_FAIL); + } + else + { + tet_result(TET_PASS); + } + } + + bool& mSignalReceived; // owned by individual tests +}; + +} // anon namespace + +int UtcDaliAnimationConstructorP(void) +{ + TestApplication application; + + Animation animation; + + DALI_TEST_CHECK( !animation ); + END_TEST; +} + +int UtcDaliAnimationNewP(void) +{ + TestApplication application; + + Animation animation = Animation::New( 1.0f ); + + DALI_TEST_CHECK(animation); + END_TEST; +} + +int UtcDaliAnimationNewN(void) +{ + TestApplication application; + + Animation animation = Animation::New( -1.0f ); + + DALI_TEST_CHECK(animation); + DALI_TEST_EQUALS(animation.GetDuration(), 0.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliAnimationDownCastP(void) +{ + TestApplication application; + + tet_infoline("Testing Dali::Animation::DownCast()"); + + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + BaseHandle object(animation); + + Animation animation2 = Animation::DownCast(object); + DALI_TEST_CHECK(animation2); + + Animation animation3 = DownCast< Animation >(object); + DALI_TEST_CHECK(animation3); + END_TEST; +} + +int UtcDaliAnimationDownCastN(void) +{ + TestApplication application; + + BaseHandle unInitializedObject; + + Animation animation1 = Animation::DownCast( unInitializedObject ); + DALI_TEST_CHECK( !animation1 ); + + Animation animation2 = DownCast< Animation >( unInitializedObject ); + DALI_TEST_CHECK( !animation2 ); + END_TEST; +} + +int UtcDaliAnimationCopyConstructorP(void) +{ + TestApplication application; + + // Initialize an object, ref count == 1 + Animation animation = Animation::New( 1.0f ); + + Animation copy( animation ); + DALI_TEST_CHECK( copy ); + + DALI_TEST_CHECK( copy.GetDuration() == animation.GetDuration() ); + END_TEST; +} + +int UtcDaliAnimationAssignmentOperatorP(void) +{ + TestApplication application; + + Animation animation = Animation::New( 1.0f ); + + Animation copy = animation; + DALI_TEST_CHECK( copy ); + + DALI_TEST_CHECK( animation == copy ); + + DALI_TEST_CHECK( copy.GetDuration() == animation.GetDuration() ); + END_TEST; +} + +int UtcDaliAnimationSetDurationP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + DALI_TEST_EQUALS(animation.GetDuration(), durationSeconds, TEST_LOCATION); + + // Start the animation + Vector3 targetPosition(10.0f, 10.0f, 10.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*1000.0f) - 1u/*just less than the animation duration*/); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + application.Render(2u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + + // Restart the animation, with a different duration + finishCheck.Reset(); + actor.SetPosition(Vector3::ZERO); + durationSeconds = 3.5f; + animation.SetDuration(durationSeconds); + DALI_TEST_EQUALS(animation.GetDuration(), durationSeconds, TEST_LOCATION); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*1000.0f) - 1u/*just less than the animation duration*/); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + application.Render(2u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationSetDurationN(void) +{ + TestApplication application; + + Animation animation = Animation::New( 1.0f ); + DALI_TEST_EQUALS( animation.GetDuration(), 1.0f, TEST_LOCATION ); + + animation.SetDuration( -1.0f ); + DALI_TEST_EQUALS( animation.GetDuration(), 0.0f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationGetDurationP(void) +{ + TestApplication application; + + Animation animation = Animation::New(1.0f); + DALI_TEST_EQUALS(animation.GetDuration(), 1.0f, TEST_LOCATION); + + animation.SetDuration(2.0f); + DALI_TEST_EQUALS(animation.GetDuration(), 2.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliAnimationSetLoopingP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(10.0f, 10.0f, 10.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + // Start the animation + animation.SetLooping(true); + DALI_TEST_CHECK(animation.IsLooping()); + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + + // Loop 5 times + float intervalSeconds = 0.25f; + float progress = 0.0f; + for (int iterations = 0; iterations < 5;) + { + application.Render(static_cast(durationSeconds*intervalSeconds*1000.0f)); + + progress += intervalSeconds; + DALI_TEST_EQUALS( targetPosition*progress, actor.GetCurrentPosition(), 0.001f, TEST_LOCATION ); + + if (progress >= 1.0f) + { + progress = progress - 1.0f; + ++iterations; + } + } + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + animation.SetLooping(false); + DALI_TEST_CHECK(!animation.IsLooping()); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*1000.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationIsLoopingP(void) +{ + TestApplication application; + + Animation animation = Animation::New(1.0f); + DALI_TEST_CHECK(!animation.IsLooping()); + + animation.SetLooping(true); + DALI_TEST_CHECK(animation.IsLooping()); + END_TEST; +} + +int UtcDaliAnimationSetEndActioN(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + DALI_TEST_CHECK(animation.GetEndAction() == Animation::Bake); + + Vector3 targetPosition(10.0f, 10.0f, 10.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*1000.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + + // Go back to the start + actor.SetPosition(Vector3::ZERO); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( Vector3::ZERO, actor.GetCurrentPosition(), TEST_LOCATION ); + + // Test BakeFinal, animate again, for half the duration + finishCheck.Reset(); + animation.SetEndAction(Animation::BakeFinal); + DALI_TEST_CHECK(animation.GetEndAction() == Animation::BakeFinal); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*1000.0f*0.5f) /*half of the animation duration*/); + + // Stop the animation early + animation.Stop(); + + // We did NOT expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( targetPosition * 0.5f, actor.GetCurrentPosition(), VECTOR4_EPSILON, TEST_LOCATION ); + + // The position should be same with target position in the next frame + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + + // Go back to the start + actor.SetPosition(Vector3::ZERO); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( Vector3::ZERO, actor.GetCurrentPosition(), TEST_LOCATION ); + + // Test EndAction::Discard, animate again, but don't bake this time + finishCheck.Reset(); + animation.SetEndAction(Animation::Discard); + DALI_TEST_CHECK(animation.GetEndAction() == Animation::Discard); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*1000.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + + // The position should be discarded in the next frame + application.Render(0); + DALI_TEST_EQUALS( Vector3::ZERO/*discarded*/, actor.GetCurrentPosition(), TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( Vector3::ZERO, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( Vector3::ZERO, actor.GetCurrentPosition(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationGetEndActionP(void) +{ + TestApplication application; + + Animation animation = Animation::New(1.0f); + DALI_TEST_CHECK(animation.GetEndAction() == Animation::Bake); + + animation.SetEndAction(Animation::Discard); + DALI_TEST_CHECK(animation.GetEndAction() == Animation::Discard); + + animation.SetEndAction(Animation::BakeFinal); + DALI_TEST_CHECK(animation.GetEndAction() == Animation::BakeFinal); + + END_TEST; +} + +int UtcDaliAnimationSetDisconnectActionP(void) +{ + TestApplication application; + Stage stage( Stage::GetCurrent() ); + + // Default: BakeFinal + { + Actor actor = Actor::New(); + stage.Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + DALI_TEST_CHECK(animation.GetDisconnectAction() == Animation::BakeFinal); + + Vector3 targetPosition(10.0f, 10.0f, 10.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + // Start the animation + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*0.5f*1000.0f)/*Only half the animation*/); + + actor.Unparent(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + } + + // Bake + { + Actor actor = Actor::New(); + stage.Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + animation.SetDisconnectAction( Animation::Bake ); + + Vector3 targetPosition(10.0f, 10.0f, 10.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + // Start the animation + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*0.5f*1000.0f)/*Only half the animation*/); + + actor.Unparent(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition*0.5f, TEST_LOCATION ); + } + + // Discard + { + Actor actor = Actor::New(); + stage.Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + animation.SetDisconnectAction( Animation::Discard ); + + Vector3 targetPosition(10.0f, 10.0f, 10.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + // Start the animation + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*0.5f*1000.0f)/*Only half the animation*/); + + actor.Unparent(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION ); + } + + // Don't play the animation: disconnect action should not be applied + { + Actor actor = Actor::New(); + stage.Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + Vector3 targetPosition(10.0f, 10.0f, 10.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*0.5f*1000.0f)/*Only half the animation*/); + + actor.Unparent(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliAnimationGetDisconnectActionP(void) +{ + TestApplication application; + Animation animation = Animation::New(1.0f); + DALI_TEST_CHECK(animation.GetDisconnectAction() == Animation::BakeFinal); // default! + + animation.SetDisconnectAction(Animation::Discard); + DALI_TEST_CHECK(animation.GetDisconnectAction() == Animation::Discard); + + animation.SetDisconnectAction(Animation::Bake); + DALI_TEST_CHECK(animation.GetDisconnectAction() == Animation::Bake); + + END_TEST; +} + +int UtcDaliAnimationSetDefaultAlphaFunctionP(void) +{ + TestApplication application; + + Animation animation = Animation::New(1.0f); + AlphaFunction func = animation.GetDefaultAlphaFunction(); + DALI_TEST_EQUALS(func.GetBuiltinFunction(), AlphaFunction::DEFAULT, TEST_LOCATION); + + animation.SetDefaultAlphaFunction(AlphaFunction::EASE_IN); + AlphaFunction func2 = animation.GetDefaultAlphaFunction(); + DALI_TEST_EQUALS(func2.GetBuiltinFunction(), AlphaFunction::EASE_IN, TEST_LOCATION); + END_TEST; +} + +int UtcDaliAnimationGetDefaultAlphaFunctionP(void) +{ + TestApplication application; + + Animation animation = Animation::New(1.0f); + AlphaFunction func = animation.GetDefaultAlphaFunction(); + + // Test that the default is linear + DALI_TEST_EQUALS(func.GetBuiltinFunction(), AlphaFunction::DEFAULT, TEST_LOCATION); + + animation.SetDefaultAlphaFunction(AlphaFunction::EASE_IN); + AlphaFunction func2 = animation.GetDefaultAlphaFunction(); + DALI_TEST_EQUALS(func2.GetBuiltinFunction(), AlphaFunction::EASE_IN, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliAnimationSetCurrentProgressP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + Animation animation = Animation::New(0.0f); + + //Set duration + float durationSeconds(1.0f); + animation.SetDuration(durationSeconds); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + // Start the animation from 40% progress + animation.SetCurrentProgress( 0.4f ); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 60% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION ); + DALI_TEST_EQUALS( 0.6f, animation.GetCurrentProgress(), TEST_LOCATION ); + + animation.Play(); // Test that calling play has no effect, when animation is already playing + application.SendNotification(); + + //Set the progress to 70% + animation.SetCurrentProgress( 0.7f ); + application.SendNotification(); + application.Render(static_cast(durationSeconds*100.0f)/* 80% progress */); + DALI_TEST_EQUALS( 0.8f, animation.GetCurrentProgress(), TEST_LOCATION ); + + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION ); + DALI_TEST_EQUALS( 0.8f, animation.GetCurrentProgress(), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/); + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationSetCurrentProgressN(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + Animation animation = Animation::New(0.0f); + + //Set duration + float durationSeconds(1.0f); + animation.SetDuration(durationSeconds); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + //Trying to set the current cursor outside the range [0..1] is ignored + animation.SetCurrentProgress( -1.0f); + application.SendNotification(); + DALI_TEST_EQUALS( 0.0f, animation.GetCurrentProgress(), TEST_LOCATION ); + + animation.SetCurrentProgress( 100.0f); + application.SendNotification(); + DALI_TEST_EQUALS( 0.0f, animation.GetCurrentProgress(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationGetCurrentProgressP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + Animation animation = Animation::New(0.0f); + animation.Play(); + + //Test GetCurrentProgress return 0.0 as the duration is 0.0 + DALI_TEST_EQUALS( 0.0f, animation.GetCurrentProgress(), TEST_LOCATION ); + + animation.SetCurrentProgress( 0.5f ); + application.SendNotification(); + application.Render(static_cast(100.0f)); + + //Progress should still be 0.0 + DALI_TEST_EQUALS( 0.0f, animation.GetCurrentProgress(), TEST_LOCATION ); + + //Set duration + float durationSeconds(1.0f); + animation.SetDuration(durationSeconds); + application.SendNotification(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + // Start the animation from 40% progress + animation.SetCurrentProgress( 0.4f ); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 60% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( 0.6f, animation.GetCurrentProgress(), TEST_LOCATION ); + + animation.Play(); // Test that calling play has no effect, when animation is already playing + application.SendNotification(); + + //Set the progress to 70% + animation.SetCurrentProgress( 0.7f ); + application.SendNotification(); + application.Render(static_cast(durationSeconds*100.0f)/* 80% progress */); + DALI_TEST_EQUALS( 0.8f, animation.GetCurrentProgress(), TEST_LOCATION ); + + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( 0.8f, animation.GetCurrentProgress(), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/); + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationSetSpeedFactorP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + const Vector3 initialPosition(0.0f, 0.0f, 0.0f); + const Vector3 targetPosition(100.0f, 100.0f, 100.0f); + + KeyFrames keyframes = KeyFrames::New(); + keyframes.Add( 0.0f, initialPosition); + keyframes.Add( 1.0f, targetPosition ); + animation.AnimateBetween( Property(actor, Actor::Property::POSITION), keyframes, AlphaFunction::LINEAR); + + //Set speed to be x2 + animation.SetSpeedFactor(2.0f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 40% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.4f), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*200.0f)/* 80% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*100.0f) + 1u/*just beyond half the duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + + finishCheck.Reset(); + + //Test -1 speed factor. Animation will play in reverse at normal speed + animation.SetSpeedFactor( -1.0f ); + + // Start the animation + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 80% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*200.0f)/* 60% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*200.0f)/* 40% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.4f), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*200.0f)/* 20% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), initialPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( initialPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( initialPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + + //Test change speed factor on the fly + finishCheck.Reset(); + + //Set speed to be half of normal speed + animation.SetSpeedFactor( 0.5f ); + + // Start the animation + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 10% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.1f), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*200.0f)/* 20% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*200.0f)/* 30% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.3f), TEST_LOCATION ); + + //Change speed factor while animation still playing. + animation.SetSpeedFactor(-1.0f); + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 10% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.1f), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*100.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), initialPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( initialPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( initialPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationGetSpeedFactorP(void) +{ + TestApplication application; + + Animation animation = Animation::New(1.0f); + animation.SetSpeedFactor(0.5f); + DALI_TEST_EQUALS(animation.GetSpeedFactor(), 0.5f, TEST_LOCATION); + + animation.SetSpeedFactor(-2.5f); + DALI_TEST_EQUALS(animation.GetSpeedFactor(), -2.5f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliAnimationSetPlayRangeP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + // Build the animation + float durationSeconds( 1.0f ); + Animation animation = Animation::New( durationSeconds ); + + bool signalReceived( false ); + AnimationFinishCheck finishCheck( signalReceived ); + animation.FinishedSignal().Connect( &application, finishCheck ); + application.SendNotification(); + + // Set range between 0.4 and 0.8 + animation.SetPlayRange( Vector2( 0.4f, 0.9f ) ); + application.SendNotification(); + DALI_TEST_EQUALS( Vector2( 0.4f, 0.9f ), animation.GetPlayRange(), TEST_LOCATION ); + + Vector3 targetPosition( 100.0f, 100.0f, 100.0f ); + animation.AnimateTo( Property( actor, Actor::Property::POSITION ), targetPosition, AlphaFunction::LINEAR ); + + // Start the animation from 40% progress + animation.Play(); + + application.SendNotification(); + application.Render( static_cast< unsigned int >( durationSeconds * 200.0f )/* 60% progress */ ); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), ( targetPosition * 0.6f ), TEST_LOCATION ); + + application.SendNotification(); + application.Render( static_cast< unsigned int >( durationSeconds * 200.0f )/* 80% progress */ ); + + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), ( targetPosition * 0.8f ), TEST_LOCATION ); + + application.SendNotification(); + application.Render( static_cast< unsigned int >( durationSeconds*100.0f ) + 1u/*just beyond the animation duration*/ ); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), ( targetPosition * 0.9f ), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationSetPlayRangeN(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + Animation animation = Animation::New(0); + application.SendNotification(); + + //PlayRange out of bounds + animation.SetPlayRange( Vector2(-1.0f,1.0f) ); + application.SendNotification(); + DALI_TEST_EQUALS( Vector2(0.0f,1.0f), animation.GetPlayRange(), TEST_LOCATION ); + animation.SetPlayRange( Vector2(0.0f,2.0f) ); + application.SendNotification(); + DALI_TEST_EQUALS( Vector2(0.0f,1.0f), animation.GetPlayRange(), TEST_LOCATION ); + + //If playRange is not in the correct order it has to be ordered + animation.SetPlayRange( Vector2(0.8f,0.2f) ); + application.SendNotification(); + DALI_TEST_EQUALS( Vector2(0.2f,0.8f), animation.GetPlayRange(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliAnimationGetPlayRangeP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + // Build the animation + Animation animation = Animation::New( 1.0f ); + application.SendNotification(); + + //If PlayRange not specified it should be 0.0-1.0 by default + DALI_TEST_EQUALS( Vector2( 0.0f,1.0f ), animation.GetPlayRange(), TEST_LOCATION ); + + // Set range between 0.4 and 0.8 + animation.SetPlayRange( Vector2( 0.4f, 0.8f ) ); + application.SendNotification(); + DALI_TEST_EQUALS( Vector2( 0.4f, 0.8f ), animation.GetPlayRange(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliAnimationPlayP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 20% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION ); + + animation.Play(); // Test that calling play has no effect, when animation is already playing + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 40% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.4f), TEST_LOCATION ); + + animation.Play(); // Test that calling play has no effect, when animation is already playing + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 60% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION ); + + animation.Play(); // Test that calling play has no effect, when animation is already playing + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 80% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION ); + + animation.Play(); // Test that calling play has no effect, when animation is already playing + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationPlayOffStageP(void) +{ + // Test that an animation can be played, when the actor is off-stage. + // When the actor is added to the stage, it should appear at the current position + // i.e. where it would have been anyway, if on-stage from the beginning. + + TestApplication application; + + Actor actor = Actor::New(); + Vector3 basePosition(Vector3::ZERO); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), basePosition, TEST_LOCATION ); + // Not added to the stage! + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + animation.SetDisconnectAction( Animation::Discard ); + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 20% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO/*off-stage*/, TEST_LOCATION ); + + // Add to the stage + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 40% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + Vector3 expectedPosition(basePosition + (targetPosition - basePosition)*0.4f); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), expectedPosition/*on-stage*/, TEST_LOCATION ); + + // Remove from the stage + Stage::GetCurrent().Remove(actor); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 60% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO/*back to start position*/, TEST_LOCATION ); + + // Add to the stage + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 80% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + expectedPosition = Vector3(basePosition + (targetPosition - basePosition)*0.8f); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), expectedPosition, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationPlayDiscardHandleP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + // Start the animation + animation.Play(); + + // This is a test of the "Fire and Forget" behaviour + // Discard the animation handle! + animation.Reset(); + DALI_TEST_CHECK( !animation ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 20% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 40% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.4f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 60% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 80% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationPlayStopDiscardHandleP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 20% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION ); + + // This is a test of the "Fire and Forget" behaviour + // Stop the animation, and Discard the animation handle! + animation.Stop(); + animation.Reset(); + DALI_TEST_CHECK( !animation ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 40% progress */); + + // We expect the animation to finish at 20% progress + application.SendNotification(); + finishCheck.CheckSignalReceived(); + finishCheck.Reset(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 60% progress */); + + // Check that nothing has changed + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 80% progress */); + + // Check that nothing has changed + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 100% progress */); + + // Check that nothing has changed + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationPlayRangeP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + KeyFrames keyframes = KeyFrames::New(); + keyframes.Add( 0.0f , Vector3(0.0f,0.0f,0.0f ) ); + keyframes.Add( 1.0f , Vector3(100.0f,100.0f,100.0f ) ); + + animation.AnimateBetween( Property( actor, Actor::Property::POSITION), keyframes ); + + // Set range between 0.4 and 0.8 + animation.SetPlayRange( Vector2(0.4f,0.8f) ); + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + //Test that setting progress outside the range doesn't work + animation.SetCurrentProgress( 0.9f ); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( animation.GetCurrentProgress(), 0.4f, TEST_LOCATION ); + animation.SetCurrentProgress( 0.2f ); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( animation.GetCurrentProgress(), 0.4f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 60% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION ); + + animation.Play(); // Test that calling play has no effect, when animation is already playing + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f) + 1u/* 80% progress */); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( targetPosition * 0.8f, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( targetPosition * 0.8f, actor.GetCurrentPosition(), TEST_LOCATION ); + + + //Loop inside the range + finishCheck.Reset(); + animation.SetLooping( true ); + animation.Play(); + application.SendNotification(); + float intervalSeconds = 0.1f; + float progress = 0.4f; + for (int iterations = 0; iterations < 10; ++iterations ) + { + application.Render(static_cast(durationSeconds*intervalSeconds*1000.0f)); + + progress += intervalSeconds; + if (progress > 0.8f) + { + progress = progress - 0.4f; + } + + DALI_TEST_EQUALS( targetPosition*progress, actor.GetCurrentPosition(), 0.001f, TEST_LOCATION ); + } + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + + //Test change range on the fly + animation.SetPlayRange( Vector2( 0.2f, 0.9f ) ); + application.SendNotification(); + + for (int iterations = 0; iterations < 10; ++iterations ) + { + application.Render(static_cast(durationSeconds*intervalSeconds*1000.0f)); + + progress += intervalSeconds; + if (progress > 0.9f) + { + progress = progress - 0.7f; + } + + DALI_TEST_EQUALS( targetPosition*progress, actor.GetCurrentPosition(), 0.001f, TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliAnimationPlayFromP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + // Start the animation from 40% progress + animation.PlayFrom( 0.4f ); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 60% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION ); + + animation.Play(); // Test that calling play has no effect, when animation is already playing + application.SendNotification(); + application.Render(static_cast(durationSeconds*200.0f)/* 80% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/); + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationPlayFromN(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + //PlayFrom with an argument outside the range [0..1] will be ignored + animation.PlayFrom(-1.0f); + application.SendNotification(); + DALI_TEST_EQUALS(0.0f, animation.GetCurrentProgress(), TEST_LOCATION ); + + animation.PlayFrom(100.0f); + application.SendNotification(); + DALI_TEST_EQUALS(0.0f, animation.GetCurrentProgress(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationPauseP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + Vector3 fiftyPercentProgress(targetPosition * 0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress, TEST_LOCATION ); + + // Pause the animation + animation.Pause(); + application.SendNotification(); + + // Loop 5 times + for (int i=0; i<5; ++i) + { + application.Render(static_cast(durationSeconds*500.0f)); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress/* Still 50% progress when paused */, TEST_LOCATION ); + } + + // Keep going + animation.Play(); + application.SendNotification(); + application.Render(static_cast(durationSeconds*490.0f)/*slightly less than the animation duration*/); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationStoP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + Vector3 fiftyPercentProgress(targetPosition * 0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress, TEST_LOCATION ); + + // Stop the animation + animation.Stop(); + application.SendNotification(); + + // Loop 5 times + for (int i=0; i<5; ++i) + { + application.Render(static_cast(durationSeconds*500.0f)); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress/* Still 50% progress when stopped */, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliAnimationStopSetPositionP(void) +{ + // Test that Animation::Stop & Actor::SetPosition can be used in conjunction + // i.e. to check that the animation does not interfere with the position set. + + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + Vector3 fiftyPercentProgress(targetPosition * 0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress, TEST_LOCATION ); + + // Stop the animation + animation.Stop(); + Vector3 positionSet(2.0f, 3.0f, 4.0f); + actor.SetPosition(positionSet); + application.SendNotification(); + + // Loop 5 times + for (int i=0; i<5; ++i) + { + application.Render(static_cast(durationSeconds*500.0f)); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), positionSet/*Animation should not interfere with this*/, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliAnimationClearP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + Vector3 fiftyPercentProgress(targetPosition * 0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress, TEST_LOCATION ); + + // Clear the animation + animation.Clear(); + application.SendNotification(); + + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We don't expect the animation to finish now + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress/* Still 50% progress since the animator was destroyed */, TEST_LOCATION ); + + // Restart as a scale animation; this should not move the actor's position + finishCheck.Reset(); + actor.SetPosition(Vector3::ZERO); + Vector3 targetScale(3.0f, 3.0f, 3.0f); + animation.AnimateTo( Property( actor, Actor::Property::SCALE ), targetScale, AlphaFunction::LINEAR ); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO/*Check move-animator was destroyed*/, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3(2.0f, 2.0f, 2.0f), TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO/*Check move-animator was destroyed*/, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationFinishedSignalP(void) +{ + TestApplication application; + + // Start the empty animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*1000.0f) + 1u/*beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateByBooleanP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a boolean property + bool startValue(false); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + const bool relativeValue(true); + const bool finalValue( false || relativeValue ); + animation.AnimateBy(Property(actor, index), relativeValue); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + // Repeat with relative value "false" - this should be an NOOP + animation = Animation::New(durationSeconds); + bool noOpValue(false); + animation.AnimateBy(Property(actor, index), noOpValue); + + // Start the animation + animation.Play(); + + finishCheck.Reset(); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + END_TEST; +} + +int UtcDaliAnimationAnimateByBooleanAlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a boolean property + bool startValue(false); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + bool relativeValue(true); + bool finalValue( false || relativeValue ); + animation.AnimateBy(Property(actor, index), relativeValue, AlphaFunction::EASE_IN); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + // Repeat with relative value "false" - this should be an NOOP + animation = Animation::New(durationSeconds); + bool noOpValue(false); + animation.AnimateBy(Property(actor, index), noOpValue, AlphaFunction::EASE_IN); + + // Start the animation + animation.Play(); + + finishCheck.Reset(); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + END_TEST; +} + +int UtcDaliAnimationAnimateByBooleanTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a boolean property + bool startValue(false); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + bool relativeValue(true); + bool finalValue( false || relativeValue ); + float animatorDurationSeconds(durationSeconds * 0.5f); + animation.AnimateBy( Property(actor, index), + relativeValue, + TimePeriod( animatorDurationSeconds ) ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(animatorDurationSeconds*950.0f)/* 95% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + application.SendNotification(); + application.Render(static_cast(animatorDurationSeconds*50.0f) + 1u/*just beyond the animator duration*/); + + // We didn't expect the animation to finish yet... + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // ...however we should have reached the final value + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + application.SendNotification(); + application.Render(static_cast(animatorDurationSeconds*1000.0f)/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + END_TEST; +} + +int UtcDaliAnimationAnimateByBooleanAlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a boolean property + bool startValue(false); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + bool relativeValue(true); + bool finalValue( false || relativeValue ); + float animatorDurationSeconds(durationSeconds * 0.5f); + animation.AnimateBy( Property(actor, index), + relativeValue, + AlphaFunction::EASE_IN_OUT, + TimePeriod( animatorDurationSeconds ) ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(animatorDurationSeconds*950.0f)/* 95% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + application.SendNotification(); + application.Render(static_cast(animatorDurationSeconds*50.0f) + 1u/*just beyond the animator duration*/); + + // We didn't expect the animation to finish yet... + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // ...however we should have reached the final value + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + application.SendNotification(); + application.Render(static_cast(animatorDurationSeconds*1000.0f)/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + END_TEST; +} + +int UtcDaliAnimationAnimateByFloatP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a float property + float startValue(10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + float targetValue(50.0f); + float relativeValue(targetValue - startValue); + animation.AnimateBy(Property(actor, index), relativeValue); + + float ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), ninetyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByFloatAlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a float property + float startValue(10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetValue(90.0f); + float relativeValue(targetValue - startValue); + animation.AnimateBy(Property(actor, index), relativeValue, AlphaFunction::EASE_OUT); + + float ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The position should have moved more, than with a linear alpha function + float current(actor.GetProperty(index)); + DALI_TEST_CHECK( current > ninetyFivePercentProgress ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByFloatTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a float property + float startValue(10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetValue(30.0f); + float relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateBy(Property(actor, index), + relativeValue, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByFloatAlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a float property + float startValue(10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetValue(30.0f); + float relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateBy(Property(actor, index), + relativeValue, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByIntegerP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register an integer property + int startValue(1); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + int targetValue(50); + int relativeValue(targetValue - startValue); + animation.AnimateBy(Property(actor, index), relativeValue); + + int ninetyFivePercentProgress(static_cast(startValue + relativeValue*0.95f + 0.5f)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), ninetyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByIntegerAlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register an integer property + int startValue(1); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + int targetValue(90); + int relativeValue(targetValue - startValue); + animation.AnimateBy(Property(actor, index), relativeValue, AlphaFunction::EASE_OUT); + + int ninetyFivePercentProgress(static_cast(startValue + relativeValue*0.95f + 0.5f)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The position should have moved more, than with a linear alpha function + int current(actor.GetProperty(index)); + DALI_TEST_CHECK( current > ninetyFivePercentProgress ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByIntegerTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register an integer property + int startValue(10); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + int targetValue(30); + int relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateBy(Property(actor, index), + relativeValue, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), static_cast(startValue+(relativeValue*0.5f)+0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByIntegerAlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register an integer property + int startValue(10); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + int targetValue(30); + int relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateBy(Property(actor, index), + relativeValue, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), static_cast(startValue+(relativeValue*0.5f)+0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByVector2P(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector2 property + Vector2 startValue(10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + Vector2 targetValue(60.0f, 60.0f); + Vector2 relativeValue(targetValue - startValue); + animation.AnimateBy(Property(actor, index), relativeValue); + + Vector2 ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), ninetyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByVector2AlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector2 property + Vector2 startValue(100.0f, 100.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector2 targetValue(20.0f, 20.0f); + Vector2 relativeValue(targetValue - startValue); + animation.AnimateBy(Property(actor, index), relativeValue, AlphaFunction::EASE_OUT); + + Vector2 ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The position should have moved more, than with a linear alpha function + Vector2 current(actor.GetProperty(index)); + DALI_TEST_CHECK( current.x < ninetyFivePercentProgress.x ); + DALI_TEST_CHECK( current.y < ninetyFivePercentProgress.y ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByVector2TimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector2 property + Vector2 startValue(10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector2 targetValue(30.0f, 30.0f); + Vector2 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateBy(Property(actor, index), + relativeValue, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByVector2AlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector2 property + Vector2 startValue(5.0f, 5.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector2 targetValue(10.0f, 10.0f); + Vector2 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateBy(Property(actor, index), + relativeValue, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByVector3P(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector3 property + Vector3 startValue(10.0f, 10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetValue(60.0f, 60.0f, 60.0f); + Vector3 relativeValue(targetValue - startValue); + animation.AnimateBy(Property(actor, index), relativeValue); + + Vector3 ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), ninetyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByVector3AlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector3 property + Vector3 startValue(100.0f, 100.0f, 100.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetValue(20.0f, 20.0f, 20.0f); + Vector3 relativeValue(targetValue - startValue); + animation.AnimateBy(Property(actor, index), relativeValue, AlphaFunction::EASE_OUT); + + Vector3 ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The position should have moved more, than with a linear alpha function + Vector3 current(actor.GetProperty(index)); + DALI_TEST_CHECK( current.x < ninetyFivePercentProgress.x ); + DALI_TEST_CHECK( current.y < ninetyFivePercentProgress.y ); + DALI_TEST_CHECK( current.z < ninetyFivePercentProgress.z ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByVector3TimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector3 property + Vector3 startValue(10.0f, 10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetValue(30.0f, 30.0f, 30.0f); + Vector3 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateBy(Property(actor, index), + relativeValue, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByVector3AlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector3 property + Vector3 startValue(5.0f, 5.0f, 5.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetValue(10.0f, 10.0f, 10.0f); + Vector3 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateBy(Property(actor, index), + relativeValue, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByVector4P(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector4 property + Vector4 startValue(10.0f, 10.0f, 10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + Vector4 targetValue(60.0f, 60.0f, 60.0f, 60.0f); + Vector4 relativeValue(targetValue - startValue); + animation.AnimateBy(Property(actor, index), relativeValue); + + Vector4 ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), ninetyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByVector4AlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector4 property + Vector4 startValue(100.0f, 100.0f, 100.0f, 100.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector4 targetValue(20.0f, 20.0f, 20.0f, 20.0f); + Vector4 relativeValue(targetValue - startValue); + animation.AnimateBy(Property(actor, index), relativeValue, AlphaFunction::EASE_OUT); + + Vector4 ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The position should have moved more, than with a linear alpha function + Vector4 current(actor.GetProperty(index)); + DALI_TEST_CHECK( current.x < ninetyFivePercentProgress.x ); + DALI_TEST_CHECK( current.y < ninetyFivePercentProgress.y ); + DALI_TEST_CHECK( current.z < ninetyFivePercentProgress.z ); + DALI_TEST_CHECK( current.w < ninetyFivePercentProgress.w ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByVector4TimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector4 property + Vector4 startValue(10.0f, 10.0f, 10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector4 targetValue(30.0f, 30.0f, 30.0f, 30.0f); + Vector4 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateBy(Property(actor, index), + relativeValue, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByVector4AlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector4 property + Vector4 startValue(5.0f, 5.0f, 5.0f, 5.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector4 targetValue(10.0f, 10.0f, 10.0f, 10.0f); + Vector4 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateBy(Property(actor, index), + relativeValue, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByActorPositionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 startPosition(10.0f, 10.0f, 10.0f); + actor.SetPosition(startPosition); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), startPosition, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(20.0f, 20.0f, 20.0f); + Vector3 relativePosition(targetPosition - startPosition); + animation.AnimateBy(Property(actor, Actor::Property::POSITION), relativePosition); + + Vector3 ninetyFivePercentProgress(startPosition + relativePosition*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), ninetyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByActorPositionAlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 startPosition(10.0f, 10.0f, 10.0f); + actor.SetPosition(startPosition); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), startPosition, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(20.0f, 20.0f, 20.0f); + Vector3 relativePosition(targetPosition - startPosition); + animation.AnimateBy(Property(actor, Actor::Property::POSITION), relativePosition, AlphaFunction::EASE_OUT); + + Vector3 ninetyFivePercentProgress(startPosition + relativePosition*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The position should have moved more, than with a linear alpha function + Vector3 current(actor.GetCurrentPosition()); + DALI_TEST_CHECK( current.x > ninetyFivePercentProgress.x ); + DALI_TEST_CHECK( current.y > ninetyFivePercentProgress.y ); + DALI_TEST_CHECK( current.z > ninetyFivePercentProgress.z ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByActorPositionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 startPosition(10.0f, 10.0f, 10.0f); + actor.SetPosition(startPosition); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), startPosition, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(20.0f, 20.0f, 20.0f); + Vector3 relativePosition(targetPosition - startPosition); + float delay = 0.5f; + animation.AnimateBy(Property(actor, Actor::Property::POSITION), + relativePosition, + TimePeriod(delay, durationSeconds - delay)); + + Vector3 ninetyFivePercentProgress(startPosition + relativePosition*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), startPosition, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByActorPositionAlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Vector3 startPosition(10.0f, 10.0f, 10.0f); + actor.SetPosition(startPosition); + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), startPosition, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(20.0f, 20.0f, 20.0f); + Vector3 relativePosition(targetPosition - startPosition); + float delay = 0.5f; + animation.AnimateBy(Property(actor, Actor::Property::POSITION), + relativePosition, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + + Vector3 ninetyFivePercentProgress(startPosition + relativePosition*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), startPosition, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByActorOrientationP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetOrientation( Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Degree relativeRotationDegrees(360.0f); + Radian relativeRotationRadians(relativeRotationDegrees); + animation.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::YAXIS ) ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * 0.25f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * 0.5f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * 0.75f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByActorOrientationAlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetOrientation( Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Degree relativeRotationDegrees(360.0f); + Radian relativeRotationRadians(relativeRotationDegrees); + animation.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::YAXIS ), AlphaFunction::EASE_IN ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * 0.25f*0.25f*0.25f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * 0.5f*0.5f*0.5f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * 0.75f*0.75f*0.75f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByActorOrientationAlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetOrientation( Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Degree relativeRotationDegrees(360.0f); + Radian relativeRotationRadians(relativeRotationDegrees); + float delay = 0.3f; + animation.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::YAXIS ), + AlphaFunction::EASE_IN, TimePeriod( delay, durationSeconds - delay ) ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + float progress = max(0.0f, 0.25f - delay) / (1.0f - delay); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * progress*progress*progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + progress = max(0.0f, 0.5f - delay) / (1.0f - delay); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * progress*progress*progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + progress = max(0.0f, 0.75f - delay) / (1.0f - delay); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * progress*progress*progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateByActorScaleP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetScale(2.0f, 2.0f, 2.0f); + Vector3 relativeScale(targetScale - Vector3::ONE); + animation.AnimateBy( Property( actor, Actor::Property::SCALE ), Vector3( relativeScale.x, relativeScale.y, relativeScale.z ) ); + + Vector3 ninetyNinePercentProgress(Vector3::ONE + relativeScale*0.99f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*990.0f)/* 99% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale(), ninetyNinePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION ); + + // Reset everything + finishCheck.Reset(); + actor.SetScale(Vector3::ONE); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION ); + + // Repeat with a different (ease-in) alpha function + animation = Animation::New(durationSeconds); + animation.AnimateBy( Property( actor, Actor::Property::SCALE ), relativeScale, AlphaFunction::EASE_IN ); + animation.FinishedSignal().Connect(&application, finishCheck); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*990.0f)/* 99% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The scale should have grown less, than with a linear alpha function + Vector3 current(actor.GetCurrentScale()); + DALI_TEST_CHECK( current.x > 1.0f ); + DALI_TEST_CHECK( current.y > 1.0f ); + DALI_TEST_CHECK( current.z > 1.0f ); + DALI_TEST_CHECK( current.x < ninetyNinePercentProgress.x ); + DALI_TEST_CHECK( current.y < ninetyNinePercentProgress.y ); + DALI_TEST_CHECK( current.z < ninetyNinePercentProgress.z ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION ); + + // Reset everything + finishCheck.Reset(); + actor.SetScale(Vector3::ONE); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION ); + + // Repeat with a delay + float delay = 0.5f; + animation = Animation::New(durationSeconds); + animation.AnimateBy( Property( actor, Actor::Property::SCALE ), relativeScale, AlphaFunction::LINEAR, TimePeriod( delay, durationSeconds - delay ) ); + animation.FinishedSignal().Connect(&application, finishCheck); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToBooleanP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a boolean property + const bool startValue(false); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + const bool targetValue( !startValue ); + animation.AnimateTo(Property(actor, index), targetValue); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == targetValue ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == targetValue ); + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == targetValue ); + + // Repeat with target value "false" + animation = Animation::New(durationSeconds); + const bool finalValue( !targetValue ); + animation.AnimateTo(Property(actor, index), finalValue); + + // Start the animation + animation.Play(); + + finishCheck.Reset(); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == targetValue ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + END_TEST; +} + +int UtcDaliAnimationAnimateToBooleanAlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a boolean property + const bool startValue(false); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + const bool targetValue( !startValue ); + animation.AnimateTo(Property(actor, "test-property"), targetValue, AlphaFunction::EASE_OUT); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == targetValue ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == targetValue ); + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == targetValue ); + + // Repeat with target value "false" + animation = Animation::New(durationSeconds); + const bool finalValue( !targetValue ); + animation.AnimateTo(Property(actor, index), finalValue, AlphaFunction::EASE_OUT); + + // Start the animation + animation.Play(); + + finishCheck.Reset(); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == targetValue ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + END_TEST; +} + +int UtcDaliAnimationAnimateToBooleanTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a boolean property + bool startValue(false); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + bool finalValue( !startValue ); + float animatorDurationSeconds(durationSeconds * 0.5f); + animation.AnimateTo( Property(actor, index), + finalValue, + TimePeriod( animatorDurationSeconds ) ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(animatorDurationSeconds*950.0f)/* 95% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + application.SendNotification(); + application.Render(static_cast(animatorDurationSeconds*50.0f) + 1u/*just beyond the animator duration*/); + + // We didn't expect the animation to finish yet... + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // ...however we should have reached the final value + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + application.SendNotification(); + application.Render(static_cast(animatorDurationSeconds*1000.0f)/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + END_TEST; +} + +int UtcDaliAnimationAnimateToBooleanAlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a boolean property + bool startValue(false); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + bool finalValue( !startValue ); + float animatorDurationSeconds(durationSeconds * 0.5f); + animation.AnimateTo( Property(actor, index), + finalValue, + AlphaFunction::LINEAR, + TimePeriod( animatorDurationSeconds ) ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(animatorDurationSeconds*950.0f)/* 95% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == startValue ); + + application.SendNotification(); + application.Render(static_cast(animatorDurationSeconds*50.0f) + 1u/*just beyond the animator duration*/); + + // We didn't expect the animation to finish yet... + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // ...however we should have reached the final value + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + application.SendNotification(); + application.Render(static_cast(animatorDurationSeconds*1000.0f)/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + + // Check that nothing has changed after a couple of buffer swaps + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + application.Render(0); + DALI_TEST_CHECK( actor.GetProperty(index) == finalValue ); + END_TEST; +} + +int UtcDaliAnimationAnimateToFloatP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a float property + float startValue(10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + float targetValue(50.0f); + float relativeValue(targetValue - startValue); + animation.AnimateTo(Property(actor, "test-property"), targetValue); + + float ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), ninetyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToFloatAlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a float property + float startValue(10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetValue(90.0f); + float relativeValue(targetValue - startValue); + animation.AnimateTo(Property(actor, index), targetValue, AlphaFunction::EASE_OUT); + + float ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The position should have moved more, than with a linear alpha function + float current(actor.GetProperty(index)); + DALI_TEST_CHECK( current > ninetyFivePercentProgress ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToFloatTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a float property + float startValue(10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetValue(30.0f); + float relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateTo(Property(actor, index), + targetValue, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToFloatAlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a float property + float startValue(10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetValue(30.0f); + float relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateTo(Property(actor, index), + targetValue, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToIntegerP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register an integer property + int startValue(10); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + int targetValue(50); + int relativeValue(targetValue - startValue); + animation.AnimateTo(Property(actor, "test-property"), targetValue); + + int ninetyFivePercentProgress(static_cast(startValue + relativeValue*0.95f + 0.5f)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), ninetyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToIntegerAlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register an integer property + int startValue(10); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + int targetValue(90); + int relativeValue(targetValue - startValue); + animation.AnimateTo(Property(actor, index), targetValue, AlphaFunction::EASE_OUT); + + int ninetyFivePercentProgress(static_cast(startValue + relativeValue*0.95f + 0.5f)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The position should have moved more, than with a linear alpha function + int current(actor.GetProperty(index)); + DALI_TEST_CHECK( current > ninetyFivePercentProgress ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToIntegerTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register an integer property + int startValue(10); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + int targetValue(30); + int relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateTo(Property(actor, index), + targetValue, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), static_cast(startValue+(relativeValue*0.5f)+0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToIntegerAlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register an integer property + int startValue(10); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + int targetValue(30); + int relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateTo(Property(actor, index), + targetValue, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), static_cast(startValue+(relativeValue*0.5f)+0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector2P(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector2 property + Vector2 startValue(-50.0f, -50.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + Vector2 targetValue(50.0f, 50.0f); + Vector2 relativeValue(targetValue - startValue); + animation.AnimateTo(Property(actor, index), targetValue); + + Vector2 ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), ninetyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector2AlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector2 property + Vector2 startValue(1000.0f, 1000.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector2 targetValue(9000.0f, 9000.0f); + Vector2 relativeValue(targetValue - startValue); + animation.AnimateTo(Property(actor, "test-property"), targetValue, AlphaFunction::EASE_OUT); + + Vector2 ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The position should have moved more, than with a linear alpha function + Vector2 current(actor.GetProperty(index)); + DALI_TEST_CHECK( current.x > ninetyFivePercentProgress.x ); + DALI_TEST_CHECK( current.y > ninetyFivePercentProgress.y ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector2TimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector2 property + Vector2 startValue(10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector2 targetValue(-10.0f, 20.0f); + Vector2 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateTo(Property(actor, index), + targetValue, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector2AlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector2 property + Vector2 startValue(10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector2 targetValue(30.0f, 30.0f); + Vector2 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateTo(Property(actor, index), + targetValue, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector3P(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector3 property + Vector3 startValue(-50.0f, -50.0f, -50.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetValue(50.0f, 50.0f, 50.0f); + Vector3 relativeValue(targetValue - startValue); + animation.AnimateTo(Property(actor, index), targetValue); + + Vector3 ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), ninetyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector3AlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector3 property + Vector3 startValue(1000.0f, 1000.0f, 1000.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetValue(9000.0f, 9000.0f, 9000.0f); + Vector3 relativeValue(targetValue - startValue); + animation.AnimateTo(Property(actor, index), targetValue, AlphaFunction::EASE_OUT); + + Vector3 ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The position should have moved more, than with a linear alpha function + Vector3 current(actor.GetProperty(index)); + DALI_TEST_CHECK( current.x > ninetyFivePercentProgress.x ); + DALI_TEST_CHECK( current.y > ninetyFivePercentProgress.y ); + DALI_TEST_CHECK( current.z > ninetyFivePercentProgress.z ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector3TimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector3 property + Vector3 startValue(10.0f, 10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetValue(-10.0f, 20.0f, 100.0f); + Vector3 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateTo(Property(actor, index), + targetValue, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector3AlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector3 property + Vector3 startValue(10.0f, 10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetValue(30.0f, 30.0f, 30.0f); + Vector3 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateTo(Property(actor, "test-property"), + targetValue, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector3ComponentP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector3 property + Vector3 startValue(10.0f, 10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetValue(30.0f, 30.0f, 10.0f); + Vector3 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateTo(Property(actor, "test-property", 0), + 30.0f, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + animation.AnimateTo(Property(actor, index, 1), + 30.0f, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector4P(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector4 property + Vector4 startValue(-50.0f, -40.0f, -30.0f, -20.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + Vector4 targetValue(50.0f, 50.0f, 50.0f, 50.0f); + Vector4 relativeValue(targetValue - startValue); + animation.AnimateTo(Property(actor, index), targetValue); + + Vector4 ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), ninetyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector4AlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector4 property + Vector4 startValue(1000.0f, 1000.0f, 1000.0f, 1000.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector4 targetValue(9000.0f, 9000.0f, 9000.0f, 9000.0f); + Vector4 relativeValue(targetValue - startValue); + animation.AnimateTo(Property(actor, index), targetValue, AlphaFunction::EASE_OUT); + + Vector4 ninetyFivePercentProgress(startValue + relativeValue*0.95f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*950.0f)/* 95% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The position should have moved more, than with a linear alpha function + Vector4 current(actor.GetProperty(index)); + DALI_TEST_CHECK( current.x > ninetyFivePercentProgress.x ); + DALI_TEST_CHECK( current.y > ninetyFivePercentProgress.y ); + DALI_TEST_CHECK( current.z > ninetyFivePercentProgress.z ); + DALI_TEST_CHECK( current.w > ninetyFivePercentProgress.w ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector4TimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector4 property + Vector4 startValue(10.0f, 10.0f, 10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, VECTOR4_EPSILON, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector4 targetValue(-10.0f, 20.0f, 100.0f, 100.0f); + Vector4 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateTo(Property(actor, index), + targetValue, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, VECTOR4_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), VECTOR4_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, VECTOR4_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToVector4AlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a Vector4 property + Vector4 startValue(10.0f, 10.0f, 10.0f, 10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector4 targetValue(30.0f, 30.0f, 30.0f, 30.0f); + Vector4 relativeValue(targetValue - startValue); + float delay = 0.5f; + animation.AnimateTo(Property(actor, index), + targetValue, + AlphaFunction::LINEAR, + TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorParentOriginP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentParentOrigin(), ParentOrigin::TOP_LEFT, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetParentOrigin(ParentOrigin::BOTTOM_RIGHT); + + try + { + animation.AnimateTo( Property(actor, Actor::Property::PARENT_ORIGIN), targetParentOrigin ); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationAnimateToActorParentOriginXP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(0.0f); + DALI_TEST_EQUALS( actor.GetCurrentParentOrigin().x, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::PARENT_ORIGIN_X), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetX(1.0f); + + try + { + animation.AnimateTo( Property(actor, Actor::Property::PARENT_ORIGIN_X), targetX ); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationAnimateToActorParentOriginYP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(0.0f); + DALI_TEST_EQUALS( actor.GetCurrentParentOrigin().y, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::PARENT_ORIGIN_Y), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetY(1.0f); + + try + { + animation.AnimateTo( Property(actor, Actor::Property::PARENT_ORIGIN_Y), targetY ); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationAnimateToActorParentOriginZP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(0.5f); + DALI_TEST_EQUALS( actor.GetCurrentParentOrigin().z, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::PARENT_ORIGIN_Z), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetZ(1.0f); + + try + { + animation.AnimateTo( Property(actor, Actor::Property::PARENT_ORIGIN_Z), targetZ ); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationAnimateToActorAnchorPointP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentAnchorPoint(), AnchorPoint::CENTER, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetAnchorPoint(AnchorPoint::TOP_LEFT); + + try + { + animation.AnimateTo( Property(actor, Actor::Property::ANCHOR_POINT), targetAnchorPoint); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationAnimateToActorAnchorPointXP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(0.5f); + DALI_TEST_EQUALS( actor.GetCurrentAnchorPoint().x, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::ANCHOR_POINT_X), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetX(1.0f); + + try + { + animation.AnimateTo( Property(actor, Actor::Property::ANCHOR_POINT_X), targetX ); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationAnimateToActorAnchorPointYP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(0.5f); + DALI_TEST_EQUALS( actor.GetCurrentAnchorPoint().y, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::ANCHOR_POINT_Y), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetY(0.0f); + + try + { + animation.AnimateTo( Property(actor, Actor::Property::ANCHOR_POINT_Y), targetY ); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationAnimateToActorAnchorPointZP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(0.5f); + DALI_TEST_EQUALS( actor.GetCurrentAnchorPoint().z, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::ANCHOR_POINT_Z), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetZ(100.0f); + + try + { + animation.AnimateTo( Property(actor, Actor::Property::ANCHOR_POINT_Z), targetZ ); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationAnimateToActorSizeP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetSize(100.0f, 100.0f, 100.0f); + animation.AnimateTo( Property(actor, Actor::Property::SIZE), targetSize ); + + Vector3 ninetyNinePercentProgress(targetSize * 0.99f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*990.0f)/* 99% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize(), ninetyNinePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize(), targetSize, TEST_LOCATION ); + + // Reset everything + finishCheck.Reset(); + actor.SetSize(Vector3::ZERO); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION ); + + // Repeat with a different (ease-in) alpha function + animation = Animation::New(durationSeconds); + animation.AnimateTo( Property(actor, Actor::Property::SIZE), targetSize, AlphaFunction::EASE_IN); + animation.FinishedSignal().Connect(&application, finishCheck); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*990.0f)/* 99% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The size should have travelled less, than with a linear alpha function + Vector3 current(actor.GetCurrentSize()); + DALI_TEST_CHECK( current.x > 0.0f ); + DALI_TEST_CHECK( current.y > 0.0f ); + DALI_TEST_CHECK( current.z > 0.0f ); + DALI_TEST_CHECK( current.x < ninetyNinePercentProgress.x ); + DALI_TEST_CHECK( current.y < ninetyNinePercentProgress.y ); + DALI_TEST_CHECK( current.z < ninetyNinePercentProgress.z ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize(), targetSize, TEST_LOCATION ); + + // Reset everything + finishCheck.Reset(); + actor.SetSize(Vector3::ZERO); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION ); + + // Repeat with a delay + float delay = 0.5f; + animation = Animation::New(durationSeconds); + animation.AnimateTo( Property(actor, Actor::Property::SIZE), targetSize, AlphaFunction::LINEAR, TimePeriod(delay, durationSeconds - delay)); + animation.FinishedSignal().Connect(&application, finishCheck); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize(), targetSize, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorSizeWidthP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(0.0f); + DALI_TEST_EQUALS( actor.GetCurrentSize().width, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SIZE_WIDTH), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetWidth(10.0f); + animation.AnimateTo( Property(actor, Actor::Property::SIZE_WIDTH), targetWidth ); + + float fiftyPercentProgress(startValue + (targetWidth - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize().width, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SIZE_WIDTH), fiftyPercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize().width, targetWidth, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SIZE_WIDTH), targetWidth, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorSizeHeightP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(0.0f); + DALI_TEST_EQUALS( actor.GetCurrentSize().height, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SIZE_HEIGHT), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetHeight(-10.0f); + animation.AnimateTo( Property(actor, Actor::Property::SIZE_HEIGHT), targetHeight ); + + float fiftyPercentProgress(startValue + (targetHeight - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize().height, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SIZE_HEIGHT), fiftyPercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize().height, targetHeight, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SIZE_HEIGHT), targetHeight, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorSizeDepthP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(0.0f); + DALI_TEST_EQUALS( actor.GetCurrentSize().depth, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SIZE_DEPTH), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetDepth(-10.0f); + animation.AnimateTo( Property(actor, Actor::Property::SIZE_DEPTH), targetDepth ); + + float fiftyPercentProgress(startValue + (targetDepth - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize().depth, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SIZE_DEPTH), fiftyPercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize().depth, targetDepth, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SIZE_DEPTH), targetDepth, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorSizeWidthHeightP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetSize(100.0f, 100.0f, 100.0f); + animation.AnimateTo( Property( actor, Actor::Property::SIZE ), targetSize ); + + Vector3 ninetyNinePercentProgress(targetSize * 0.99f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*990.0f)/* 99% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize(), ninetyNinePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize(), targetSize, TEST_LOCATION ); + + // Reset everything + finishCheck.Reset(); + actor.SetSize(Vector3::ZERO); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION ); + + // Repeat with a different (ease-in) alpha function + animation = Animation::New(durationSeconds); + animation.AnimateTo( Property( actor, Actor::Property::SIZE_WIDTH ), targetSize.x, AlphaFunction::EASE_IN ); + animation.AnimateTo( Property( actor, Actor::Property::SIZE_HEIGHT ), targetSize.y, AlphaFunction::EASE_IN ); + animation.FinishedSignal().Connect(&application, finishCheck); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*990.0f)/* 99% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The size should have travelled less, than with a linear alpha function + Vector3 current(actor.GetCurrentSize()); + DALI_TEST_CHECK( current.x > 0.0f ); + DALI_TEST_CHECK( current.y > 0.0f ); + DALI_TEST_CHECK( current.x < ninetyNinePercentProgress.x ); + DALI_TEST_CHECK( current.y < ninetyNinePercentProgress.y ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize().x, targetSize.x, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentSize().y, targetSize.y, TEST_LOCATION ); + + // Reset everything + finishCheck.Reset(); + actor.SetSize(Vector3::ZERO); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION ); + + // Repeat with a delay + float delay = 0.5f; + animation = Animation::New(durationSeconds); + animation.AnimateTo( Property( actor, Actor::Property::SIZE_WIDTH ), targetSize.x, AlphaFunction::LINEAR, TimePeriod( delay, durationSeconds - delay ) ); + animation.AnimateTo( Property( actor, Actor::Property::SIZE_HEIGHT ), targetSize.y, AlphaFunction::LINEAR, TimePeriod( delay, durationSeconds - delay ) ); + animation.FinishedSignal().Connect(&application, finishCheck); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentSize().x, targetSize.x, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentSize().y, targetSize.y, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorPositionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(200.0f, 200.0f, 200.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition); + + Vector3 seventyFivePercentProgress(targetPosition * 0.75f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*750.0f)/* 75% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), seventyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorPositionXP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(0.0f); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Z), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetX(1.0f); + animation.AnimateTo( Property(actor, Actor::Property::POSITION_X), targetX ); + + float fiftyPercentProgress(startValue + (targetX - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_X), fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Z), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, targetX, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_X), targetX, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Z), startValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorPositionYP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(0.0f); + DALI_TEST_EQUALS( actor.GetCurrentPosition().y, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Z), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetY(10.0f); + animation.AnimateTo( Property(actor, Actor::Property::POSITION_Y), targetY ); + + float fiftyPercentProgress(startValue + (targetY - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition().y, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Y), fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Z), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition().y, targetY, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Y), targetY, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Z), startValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorPositionZP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(0.0f); + DALI_TEST_EQUALS( actor.GetCurrentPosition().z, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Z), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetZ(-5.0f); + animation.AnimateTo( Property(actor, Actor::Property::POSITION_Z), targetZ ); + + float fiftyPercentProgress(startValue + (targetZ - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition().z, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Z), fiftyPercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition().z, targetZ, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::POSITION_Z), targetZ, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorPositionAlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(200.0f, 200.0f, 200.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::EASE_IN); + + Vector3 seventyFivePercentProgress(targetPosition * 0.75f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*750.0f)/* 75% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The position should have moved less, than with a linear alpha function + Vector3 current(actor.GetCurrentPosition()); + DALI_TEST_CHECK( current.x > Vector3::ZERO.x ); + DALI_TEST_CHECK( current.y > Vector3::ZERO.y ); + DALI_TEST_CHECK( current.z > Vector3::ZERO.z ); + DALI_TEST_CHECK( current.x < seventyFivePercentProgress.x ); + DALI_TEST_CHECK( current.y < seventyFivePercentProgress.y ); + DALI_TEST_CHECK( current.z < seventyFivePercentProgress.z ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorPositionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(200.0f, 200.0f, 200.0f); + float delay = 0.5f; + animation.AnimateTo( Property(actor, Actor::Property::POSITION), + targetPosition, + TimePeriod( delay, durationSeconds - delay ) ); + + Vector3 seventyFivePercentProgress(targetPosition * 0.75f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f*0.75)/* 7/8 animation progress, 3/4 animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), seventyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f*0.25) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorPositionAlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetPosition(200.0f, 200.0f, 200.0f); + float delay = 0.5f; + animation.AnimateTo( Property(actor, Actor::Property::POSITION), + targetPosition, + AlphaFunction::LINEAR, + TimePeriod( delay, durationSeconds - delay ) ); + + Vector3 seventyFivePercentProgress(targetPosition * 0.75f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f*0.75)/* 7/8 animation progress, 3/4 animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), seventyFivePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f*0.25) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorOrientationAngleAxisP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetOrientation(Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Degree targetRotationDegrees(90.0f); + Radian targetRotationRadians(targetRotationDegrees); + animation.AnimateTo( Property(actor, Actor::Property::ORIENTATION), AngleAxis(targetRotationRadians, Vector3::YAXIS) ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.25f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.5f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.75f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorOrientationQuaternionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetOrientation(Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Degree targetRotationDegrees(90.0f); + Radian targetRotationRadians(targetRotationDegrees); + Quaternion targetRotation(targetRotationRadians, Vector3::YAXIS); + animation.AnimateTo( Property(actor, Actor::Property::ORIENTATION), targetRotation ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.25f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.5f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.75f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorOrientationAlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetOrientation(Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(Radian(0.0f), Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Degree targetRotationDegrees(90.0f); + Radian targetRotationRadians(targetRotationDegrees); + animation.AnimateTo( Property(actor, Actor::Property::ORIENTATION), AngleAxis(targetRotationDegrees, Vector3::YAXIS), AlphaFunction::EASE_IN); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.25f*0.25f*0.25f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.5f*0.5f*0.5f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.75f*0.75f*0.75f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorOrientationTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetOrientation(Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Degree targetRotationDegrees(90.0f); + Radian targetRotationRadians(targetRotationDegrees); + float delay(0.1f); + animation.AnimateTo( Property(actor, Actor::Property::ORIENTATION), AngleAxis(targetRotationDegrees, Vector3::YAXIS), TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + float progress = max(0.0f, 0.25f - delay) / (1.0f - delay); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + progress = max(0.0f, 0.5f - delay) / (1.0f - delay); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + progress = max(0.0f, 0.75f - delay) / (1.0f - delay); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorOrientationAlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetOrientation(Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Degree targetRotationDegrees(90.0f); + Radian targetRotationRadians(targetRotationDegrees); + float delay(0.1f); + animation.AnimateTo( Property(actor, Actor::Property::ORIENTATION), AngleAxis(targetRotationDegrees, Vector3::YAXIS), AlphaFunction::EASE_IN, TimePeriod(delay, durationSeconds - delay)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + float progress = max(0.0f, 0.25f - delay) / (1.0f - delay); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * progress*progress*progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + progress = max(0.0f, 0.5f - delay) / (1.0f - delay); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * progress*progress*progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + progress = max(0.0f, 0.75f - delay) / (1.0f - delay); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * progress*progress*progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorScaleP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector3 targetScale(2.0f, 2.0f, 2.0f); + animation.AnimateTo( Property(actor, Actor::Property::SCALE), targetScale ); + + Vector3 ninetyNinePercentProgress(Vector3::ONE + (targetScale - Vector3::ONE)*0.99f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*990.0f)/* 99% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale(), ninetyNinePercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION ); + + // Reset everything + finishCheck.Reset(); + actor.SetScale(Vector3::ONE); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION ); + + // Repeat with a different (ease-in) alpha function + animation = Animation::New(durationSeconds); + animation.AnimateTo( Property(actor, Actor::Property::SCALE), targetScale, AlphaFunction::EASE_IN); + animation.FinishedSignal().Connect(&application, finishCheck); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*990.0f)/* 99% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The scale should have grown less, than with a linear alpha function + Vector3 current(actor.GetCurrentScale()); + DALI_TEST_CHECK( current.x > 1.0f ); + DALI_TEST_CHECK( current.y > 1.0f ); + DALI_TEST_CHECK( current.z > 1.0f ); + DALI_TEST_CHECK( current.x < ninetyNinePercentProgress.x ); + DALI_TEST_CHECK( current.y < ninetyNinePercentProgress.y ); + DALI_TEST_CHECK( current.z < ninetyNinePercentProgress.z ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION ); + + // Reset everything + finishCheck.Reset(); + actor.SetScale(Vector3::ONE); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION ); + + // Repeat with a delay + float delay = 0.5f; + animation = Animation::New(durationSeconds); + animation.AnimateTo( Property(actor, Actor::Property::SCALE), targetScale, AlphaFunction::LINEAR, TimePeriod(delay, durationSeconds - delay)); + animation.FinishedSignal().Connect(&application, finishCheck); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorScaleXP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(1.0f); + DALI_TEST_EQUALS( actor.GetCurrentScale().x, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Z), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetX(10.0f); + animation.AnimateTo( Property(actor, Actor::Property::SCALE_X), targetX ); + + float fiftyPercentProgress(startValue + (targetX - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale().x, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_X), fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Z), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale().x, targetX, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_X), targetX, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Z), startValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorScaleYP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(1.0f); + DALI_TEST_EQUALS( actor.GetCurrentScale().y, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Z), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetY(1000.0f); + animation.AnimateTo( Property(actor, Actor::Property::SCALE_Y), targetY ); + + float fiftyPercentProgress(startValue + (targetY - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale().y, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Y), fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Z), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale().y, targetY, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Y), targetY, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Z), startValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorScaleZP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(1.0f); + DALI_TEST_EQUALS( actor.GetCurrentScale().z, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Z), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetZ(-1000.0f); + animation.AnimateTo( Property(actor, Actor::Property::SCALE_Z), targetZ ); + + float fiftyPercentProgress(startValue + (targetZ - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale().z, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Z), fiftyPercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentScale().z, targetZ, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_X), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Y), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::SCALE_Z), targetZ, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorColorP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetCurrentColor(), Color::WHITE, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + Vector4 targetColor(Color::RED); + animation.AnimateTo( Property(actor, Actor::Property::COLOR), targetColor ); + + Vector4 tenPercentProgress(Vector4(1.0f, 0.9f, 0.9f, 1.0f)); + Vector4 twentyPercentProgress(Vector4(1.0f, 0.8f, 0.8f, 1.0f)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*100.0f)/* 10% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor(), tenPercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*900.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor(), targetColor, TEST_LOCATION ); + + // Reset everything + finishCheck.Reset(); + actor.SetColor(Color::WHITE); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentColor(), Color::WHITE, TEST_LOCATION ); + + // Repeat with a different (ease-in) alpha function + animation = Animation::New(durationSeconds); + animation.AnimateTo( Property(actor, Actor::Property::COLOR), targetColor, AlphaFunction::EASE_IN); + animation.FinishedSignal().Connect(&application, finishCheck); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*100.0f)/* 10% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + // The color should have changed less, than with a linear alpha function + Vector4 current(actor.GetCurrentColor()); + DALI_TEST_CHECK( current.x == 1.0f ); // doesn't change + DALI_TEST_CHECK( current.y < 1.0f ); + DALI_TEST_CHECK( current.y > tenPercentProgress.y ); + DALI_TEST_CHECK( current.z < 1.0f ); + DALI_TEST_CHECK( current.z > tenPercentProgress.z ); + DALI_TEST_CHECK( current.w == 1.0f ); // doesn't change + + application.SendNotification(); + application.Render(static_cast(durationSeconds*900.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor(), targetColor, TEST_LOCATION ); + + // Reset everything + finishCheck.Reset(); + actor.SetColor(Color::WHITE); + application.SendNotification(); + application.Render(0); + DALI_TEST_EQUALS( actor.GetCurrentColor(), Color::WHITE, TEST_LOCATION ); + + // Repeat with a shorter animator duration + float animatorDuration = 0.5f; + animation = Animation::New(durationSeconds); + animation.AnimateTo( Property(actor, Actor::Property::COLOR), targetColor, AlphaFunction::LINEAR, TimePeriod(animatorDuration)); + animation.FinishedSignal().Connect(&application, finishCheck); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*100.0f)/* 10% animation progress, 20% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor(), twentyPercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*400.0f)/* 50% animation progress, 100% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor(), targetColor, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor(), targetColor, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorColorRedP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(1.0f); + DALI_TEST_EQUALS( actor.GetCurrentColor().r, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetRed(0.5f); + animation.AnimateTo( Property(actor, Actor::Property::COLOR_RED), targetRed ); + + float fiftyPercentProgress(startValue + (targetRed - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor().r, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor().r, targetRed, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), targetRed, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorColorGreenP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(1.0f); + DALI_TEST_EQUALS( actor.GetCurrentColor().g, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetGreen(0.5f); + animation.AnimateTo( Property(actor, Actor::Property::COLOR_GREEN), targetGreen ); + + float fiftyPercentProgress(startValue + (targetGreen - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor().g, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor().g, targetGreen, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), targetGreen, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorColorBlueP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(1.0f); + DALI_TEST_EQUALS( actor.GetCurrentColor().b, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetBlue(0.5f); + animation.AnimateTo( Property(actor, Actor::Property::COLOR_BLUE), targetBlue ); + + float fiftyPercentProgress(startValue + (targetBlue - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor().b, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor().b, targetBlue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), targetBlue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationAnimateToActorColorAlphaP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + float startValue(1.0f); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + float targetAlpha(0.5f); + animation.AnimateTo( Property(actor, Actor::Property::COLOR_ALPHA), targetAlpha ); + + float fiftyPercentProgress(startValue + (targetAlpha - startValue)*0.5f); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, fiftyPercentProgress, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), fiftyPercentProgress, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, targetAlpha, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), targetAlpha, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationKeyFrames01P(void) +{ + TestApplication application; + + KeyFrames keyFrames = KeyFrames::New(); + DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION); + + keyFrames.Add(0.0f, 0.1f); + + DALI_TEST_EQUALS(keyFrames.GetType(), Property::FLOAT, TEST_LOCATION); + + KeyFrames keyFrames2( keyFrames); + DALI_TEST_CHECK( keyFrames2 ); + DALI_TEST_EQUALS(keyFrames2.GetType(), Property::FLOAT, TEST_LOCATION); + + KeyFrames keyFrames3 = KeyFrames::New(); + keyFrames3.Add(0.6f, true); + DALI_TEST_CHECK( keyFrames3 ); + DALI_TEST_EQUALS(keyFrames3.GetType(), Property::BOOLEAN, TEST_LOCATION); + + keyFrames3 = keyFrames; + DALI_TEST_CHECK( keyFrames3 ); + DALI_TEST_EQUALS(keyFrames3.GetType(), Property::FLOAT, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliAnimationKeyFrames02P(void) +{ + TestApplication application; + + KeyFrames keyFrames = KeyFrames::New(); + DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION); + + keyFrames.Add(0.0f, 0.1f); + keyFrames.Add(0.2f, 0.5f); + keyFrames.Add(0.4f, 0.0f); + keyFrames.Add(0.6f, 1.0f); + keyFrames.Add(0.8f, 0.7f); + keyFrames.Add(1.0f, 0.9f); + + DALI_TEST_EQUALS(keyFrames.GetType(), Property::FLOAT, TEST_LOCATION); + + try + { + keyFrames.Add(1.9f, false); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "mType == value.GetType()", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationKeyFrames03P(void) +{ + TestApplication application; + + KeyFrames keyFrames = KeyFrames::New(); + DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION); + + keyFrames.Add(0.0f, true); + keyFrames.Add(0.2f, false); + keyFrames.Add(0.4f, false); + keyFrames.Add(0.6f, true); + keyFrames.Add(0.8f, true); + keyFrames.Add(1.0f, false); + + DALI_TEST_EQUALS(keyFrames.GetType(), Property::BOOLEAN, TEST_LOCATION); + + try + { + keyFrames.Add(0.7f, Vector3(1.0f, 1.0f, 1.0f)); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "mType == value.GetType()", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationKeyFrames04P(void) +{ + TestApplication application; + + KeyFrames keyFrames = KeyFrames::New(); + DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION); + + keyFrames.Add(0.0f, Vector2(0.0f, 0.0f)); + keyFrames.Add(0.2f, Vector2(1.0f, 1.0f)); + keyFrames.Add(0.4f, Vector2(2.0f, 2.0f)); + keyFrames.Add(0.6f, Vector2(3.0f, 5.0f)); + keyFrames.Add(0.8f, Vector2(4.0f, 3.0f)); + keyFrames.Add(1.0f, Vector2(6.0f, 2.0f)); + + DALI_TEST_EQUALS(keyFrames.GetType(), Property::VECTOR2, TEST_LOCATION); + + try + { + keyFrames.Add(0.7f, Vector3(1.0f, 1.0f, 1.0f)); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "mType == value.GetType()", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationKeyFrames05P(void) +{ + TestApplication application; + + KeyFrames keyFrames = KeyFrames::New(); + DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION); + + keyFrames.Add(0.0f, Vector3(0.0f, 4.0f, 0.0f)); + keyFrames.Add(0.2f, Vector3(1.0f, 3.0f, 1.0f)); + keyFrames.Add(0.4f, Vector3(2.0f, 2.0f, 2.0f)); + keyFrames.Add(0.6f, Vector3(3.0f, 2.0f, 5.0f)); + keyFrames.Add(0.8f, Vector3(4.0f, 4.0f, 3.0f)); + keyFrames.Add(1.0f, Vector3(6.0f, 8.0f, 2.0f)); + + DALI_TEST_EQUALS(keyFrames.GetType(), Property::VECTOR3, TEST_LOCATION); + + try + { + keyFrames.Add(0.7f, 1.0f); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "mType == value.GetType()", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationKeyFrames06P(void) +{ + TestApplication application; + + KeyFrames keyFrames = KeyFrames::New(); + DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION); + + keyFrames.Add(0.0f, Vector4(0.0f, 0.0f, 0.0f, 0.0f)); + keyFrames.Add(0.2f, Vector4(1.0f, 1.0f, 1.0f, 1.0f)); + keyFrames.Add(0.4f, Vector4(2.0f, 2.0f, 2.0f, 2.0f)); + keyFrames.Add(0.6f, Vector4(3.0f, 5.0f, 3.0f, 5.0f)); + keyFrames.Add(0.8f, Vector4(4.0f, 3.0f, 4.0f, 3.0f)); + keyFrames.Add(1.0f, Vector4(6.0f, 2.0f, 6.0f, 2.0f)); + + DALI_TEST_EQUALS(keyFrames.GetType(), Property::VECTOR4, TEST_LOCATION); + + try + { + keyFrames.Add(0.7f, Quaternion(Radian(1.717f), Vector3::XAXIS)); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "mType == value.GetType()", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationKeyFrames07P(void) +{ + TestApplication application; + + KeyFrames keyFrames = KeyFrames::New(); + DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION); + + keyFrames.Add(0.0f, Quaternion(Radian(1.717f), Vector3::XAXIS)); + keyFrames.Add(0.2f, Quaternion(Radian(2.0f), Vector3::XAXIS)); + keyFrames.Add(0.4f, Quaternion(Radian(3.0f), Vector3::ZAXIS)); + keyFrames.Add(0.6f, Quaternion(Radian(4.0f), Vector3(1.0f, 1.0f, 1.0f))); + keyFrames.Add(0.8f, AngleAxis(Degree(90), Vector3::XAXIS)); + keyFrames.Add(1.0f, Quaternion(Radian(3.0f), Vector3::YAXIS)); + + DALI_TEST_EQUALS(keyFrames.GetType(), Property::ROTATION, TEST_LOCATION); + + try + { + keyFrames.Add(0.7f, 1.1f); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "mType == value.GetType()", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorColorAlphaP(void) +{ + TestApplication application; + + float startValue(1.0f); + Actor actor = Actor::New(); + actor.SetColor(Vector4(startValue, startValue, startValue, startValue)); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, 0.1f); + keyFrames.Add(0.2f, 0.5f); + keyFrames.Add(0.4f, 0.0f); + keyFrames.Add(0.6f, 1.0f); + keyFrames.Add(0.8f, 0.7f); + keyFrames.Add(1.0f, 0.9f); + + animation.AnimateBetween( Property(actor, Actor::Property::COLOR_ALPHA), keyFrames ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.Render(0); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.1f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*100.0f)/* 10% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.3f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.3f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*200.0f)/* 30% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.25f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.25f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*100.0f)/* 40% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.0f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*400.0f)/* 80% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.7f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.7f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*100.0f)/* 90% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.8f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.8f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*100.0f)+1/* 100% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.9f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.9f, 0.01f, TEST_LOCATION ); + + // We did expect the animation to finish + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorColorAlphaCubicP(void) +{ + TestApplication application; + + float startValue(1.0f); + Actor actor = Actor::New(); + actor.SetColor(Vector4(startValue, startValue, startValue, startValue)); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, 0.1f); + keyFrames.Add(0.2f, 0.5f); + keyFrames.Add(0.4f, 0.0f); + keyFrames.Add(0.6f, 1.0f); + keyFrames.Add(0.8f, 0.7f); + keyFrames.Add(1.0f, 0.9f); + + animation.AnimateBetween( Property(actor, Actor::Property::COLOR_ALPHA), keyFrames, Animation::Cubic ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.Render(0); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.1f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*100.0f)/* 10% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.36f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.36f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*200.0f)/* 30% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.21f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.21f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*100.0f)/* 40% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.0f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*400.0f)/* 80% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.7f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.7f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*100.0f)/* 90% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.76f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.76f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*100.0f)+1/* 100% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.9f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.9f, 0.01f, TEST_LOCATION ); + + // We did expect the animation to finish + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorColorP(void) +{ + TestApplication application; + + float startValue(1.0f); + Actor actor = Actor::New(); + actor.SetColor(Vector4(startValue, startValue, startValue, startValue)); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f)); + keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f)); + keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f)); + + animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.Render(0); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.1f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.3f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.5f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.5f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.5f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.5f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.9f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.7f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.95f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.90f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.85f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.80f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)+1/* 100% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION ); + + // We did expect the animation to finish + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorColorCubicP(void) +{ + TestApplication application; + + float startValue(1.0f); + Actor actor = Actor::New(); + actor.SetColor(Vector4(startValue, startValue, startValue, startValue)); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f)); + keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f)); + keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f)); + + animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, Animation::Cubic ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.Render(0); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.1f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.3f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.55f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.525f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.506f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.4875f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.9f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.7f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.99375f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.925f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.85625f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.7875f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)+1/* 100% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION ); + + // We did expect the animation to finish + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorVisibleP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + AngleAxis aa(Degree(90), Vector3::XAXIS); + actor.SetOrientation(aa.angle, aa.axis); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(0); + + DALI_TEST_EQUALS( actor.IsVisible(), true, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, false); + keyFrames.Add(0.2f, true); + keyFrames.Add(0.4f, true); + keyFrames.Add(0.8f, false); + keyFrames.Add(1.0f, true); + + animation.AnimateBetween( Property(actor, Actor::Property::VISIBLE), keyFrames ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)); + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)+1); + application.SendNotification(); + + DALI_TEST_EQUALS( actor.IsVisible(), true, TEST_LOCATION); + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorVisibleCubicP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + AngleAxis aa(Degree(90), Vector3::XAXIS); + actor.SetOrientation(aa.angle, aa.axis); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(0); + + DALI_TEST_EQUALS( actor.IsVisible(), true, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, false); + keyFrames.Add(0.2f, true); + keyFrames.Add(0.4f, true); + keyFrames.Add(0.8f, false); + keyFrames.Add(1.0f, true); + + //Cubic interpolation for boolean values should be ignored + animation.AnimateBetween( Property(actor, Actor::Property::VISIBLE), keyFrames, Animation::Cubic ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)); + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)+1); + application.SendNotification(); + + DALI_TEST_EQUALS( actor.IsVisible(), true, TEST_LOCATION); + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorOrientation01P(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + AngleAxis aa(Degree(90), Vector3::XAXIS); + actor.SetOrientation(aa.angle, aa.axis); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(0); + Quaternion start(Radian(aa.angle), aa.axis); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), start, 0.001f, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, AngleAxis(Degree(60), Vector3::ZAXIS)); + + animation.AnimateBetween( Property(actor, Actor::Property::ORIENTATION), keyFrames ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)); + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)+1); + application.SendNotification(); + + Quaternion check( Radian(Degree(60)), Vector3::ZAXIS ); + + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION ); + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorOrientation02P(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + AngleAxis aa(Degree(90), Vector3::XAXIS); + actor.SetOrientation(aa.angle, aa.axis); + application.SendNotification(); + application.Render(0); + Stage::GetCurrent().Add(actor); + + Quaternion start(Radian(aa.angle), aa.axis); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), start, 0.001f, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, AngleAxis(Degree(60), Vector3::XAXIS)); + keyFrames.Add(0.5f, AngleAxis(Degree(120), Vector3::XAXIS)); + keyFrames.Add(1.0f, AngleAxis(Degree(120), Vector3::YAXIS)); + + animation.AnimateBetween( Property(actor, Actor::Property::ORIENTATION), keyFrames ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.Render(0); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + Quaternion check(Radian(Degree(60)), Vector3::XAXIS); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + application.SendNotification(); + check = Quaternion( Radian(Degree(90)), Vector3::XAXIS ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + application.SendNotification(); + check = Quaternion( Radian(Degree(120)), Vector3::XAXIS ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + application.SendNotification(); + check = Quaternion( Radian(Degree(101.5)), Vector3(0.5f, 0.5f, 0.0f) ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)+1/* 100% progress */); + application.SendNotification(); + check = Quaternion( Radian(Degree(120)), Vector3::YAXIS ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION ); + + // We did expect the animation to finish + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorOrientation01CubicP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + AngleAxis aa(Degree(90), Vector3::XAXIS); + actor.SetOrientation(aa.angle, aa.axis); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(0); + Quaternion start(Radian(aa.angle), aa.axis); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), start, 0.001f, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, AngleAxis(Degree(60), Vector3::ZAXIS)); + + //Cubic interpolation should be ignored for quaternions + animation.AnimateBetween( Property(actor, Actor::Property::ORIENTATION), keyFrames, Animation::Cubic ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)); + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)+1); + application.SendNotification(); + + Quaternion check( Radian(Degree(60)), Vector3::ZAXIS ); + + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION ); + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorOrientation02CubicP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + AngleAxis aa(Degree(90), Vector3::XAXIS); + actor.SetOrientation(aa.angle, aa.axis); + application.SendNotification(); + application.Render(0); + Stage::GetCurrent().Add(actor); + + Quaternion start(Radian(aa.angle), aa.axis); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), start, 0.001f, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, AngleAxis(Degree(60), Vector3::XAXIS)); + keyFrames.Add(0.5f, AngleAxis(Degree(120), Vector3::XAXIS)); + keyFrames.Add(1.0f, AngleAxis(Degree(120), Vector3::YAXIS)); + + //Cubic interpolation should be ignored for quaternions + animation.AnimateBetween( Property(actor, Actor::Property::ORIENTATION), keyFrames, Animation::Cubic ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.Render(0); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + + Quaternion check(Radian(Degree(60)), Vector3::XAXIS); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + application.SendNotification(); + check = Quaternion( Radian(Degree(90)), Vector3::XAXIS ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + application.SendNotification(); + check = Quaternion( Radian(Degree(120)), Vector3::XAXIS ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + application.SendNotification(); + check = Quaternion( Radian(Degree(101.5)), Vector3(0.5f, 0.5f, 0.0f ) ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)+1/* 100% progress */); + application.SendNotification(); + check = Quaternion( Radian(Degree(120)), Vector3::YAXIS ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION ); + + // We did expect the animation to finish + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorColorAlphaFunctionP(void) +{ + TestApplication application; + + float startValue(1.0f); + Actor actor = Actor::New(); + actor.SetColor(Vector4(startValue, startValue, startValue, startValue)); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f)); + keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f)); + keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f)); + + animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, AlphaFunction::LINEAR ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.Render(0); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.1f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.3f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.5f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.5f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.5f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.5f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.9f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.7f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.95f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.90f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.85f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.80f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)+1/* 100% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION ); + + // We did expect the animation to finish + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorColorAlphaFunctionCubicP(void) +{ + TestApplication application; + + float startValue(1.0f); + Actor actor = Actor::New(); + actor.SetColor(Vector4(startValue, startValue, startValue, startValue)); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f)); + keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f)); + keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f)); + + animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, AlphaFunction::LINEAR, Animation::Cubic ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.Render(0); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.1f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.3f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.55f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.525f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.506f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.4875f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.9f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.7f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.99375f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.925f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.85625f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.7875f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)+1/* 100% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION ); + + // We did expect the animation to finish + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorColorTimePeriodP(void) +{ + TestApplication application; + + float startValue(1.0f); + Actor actor = Actor::New(); + actor.SetColor(Vector4(startValue, startValue, startValue, startValue)); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + float delay = 0.5f; + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f)); + keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f)); + keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f)); + + animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, TimePeriod( delay, durationSeconds - delay ) ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + + application.Render(static_cast(delay*1000.0f)/* 0% progress */); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.1f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.3f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)/* 25% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.5f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.5f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.5f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.5f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)/* 50% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.9f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.7f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)/* 75% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.95f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.90f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.85f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.80f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)+1/* 100% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION ); + + // We did expect the animation to finish + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorColorTimePeriodCubicP(void) +{ + TestApplication application; + + float startValue(1.0f); + Actor actor = Actor::New(); + actor.SetColor(Vector4(startValue, startValue, startValue, startValue)); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + float delay = 0.5f; + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f)); + keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f)); + keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f)); + + animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, TimePeriod( delay, durationSeconds - delay ), Animation::Cubic ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + + application.Render(static_cast(delay*1000.0f)/* 0% progress */); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.1f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.3f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)/* 25% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.55f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.525f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.506f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.4875f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)/* 50% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.9f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.7f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)/* 75% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.99375f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.925f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.85625f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.7875f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)+1/* 100% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION ); + + // We did expect the animation to finish + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateBetweenActorColorAlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + float startValue(1.0f); + float delay = 0.5f; + Actor actor = Actor::New(); + actor.SetColor(Vector4(startValue, startValue, startValue, startValue)); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f)); + keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f)); + keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f)); + + animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, AlphaFunction::LINEAR, TimePeriod( delay, durationSeconds - delay ) ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + + application.Render(static_cast(delay*1000.0f)/* 0% progress */); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.1f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.3f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)/* 25% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.5f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.5f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.5f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.5f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)/* 50% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.9f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.7f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)/* 75% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.95f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.90f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.85f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.80f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)+1/* 100% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION ); + + // We did expect the animation to finish + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int P(void) +{ + TestApplication application; + + float startValue(1.0f); + Actor actor = Actor::New(); + actor.SetColor(Vector4(startValue, startValue, startValue, startValue)); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), startValue, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + float delay = 0.5f; + Animation animation = Animation::New(durationSeconds); + + KeyFrames keyFrames = KeyFrames::New(); + keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f)); + keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f)); + keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f)); + + animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, AlphaFunction::LINEAR, TimePeriod( delay, durationSeconds - delay ), Animation::Cubic ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + + application.Render(static_cast(delay*1000.0f)/* 0% progress */); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.1f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.3f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)/* 25% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.55f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.525f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.506f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.4875f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)/* 50% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.9f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.7f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)/* 75% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 0.99375f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 0.925f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 0.85625f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 0.7875f, 0.01f, TEST_LOCATION ); + + application.Render(static_cast((durationSeconds - delay)*250.0f)+1/* 100% progress */); + application.SendNotification(); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_RED), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_BLUE), 1.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProperty(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION ); + + // We did expect the animation to finish + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + //Build the path + Vector3 position0( 30.0, 80.0, 0.0); + Vector3 position1( 70.0, 120.0, 0.0); + Vector3 position2( 100.0, 100.0, 0.0); + + Dali::Path path = Dali::Path::New(); + path.AddPoint(position0); + path.AddPoint(position1); + path.AddPoint(position2); + + //Control points for first segment + path.AddControlPoint( Vector3( 39.0, 90.0, 0.0) ); + path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) ); + + //Control points for second segment + path.AddControlPoint(Vector3( 78.0, 120.0, 0.0)); + path.AddControlPoint(Vector3( 93.0, 104.0, 0.0)); + + // Build the animation + float durationSeconds( 1.0f ); + Animation animation = Animation::New(durationSeconds); + animation.Animate(actor, path, Vector3::XAXIS); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.Render(0); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + Vector3 position, tangent; + Quaternion rotation; + path.Sample( 0.0f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + application.SendNotification(); + path.Sample( 0.25f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + application.SendNotification(); + path.Sample( 0.5f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + application.SendNotification(); + path.Sample( 0.75f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)+1/* 100% progress */); + application.SendNotification(); + path.Sample( 1.0f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateAlphaFunctionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + //Build the path + Vector3 position0( 30.0, 80.0, 0.0); + Vector3 position1( 70.0, 120.0, 0.0); + Vector3 position2( 100.0, 100.0, 0.0); + + Dali::Path path = Dali::Path::New(); + path.AddPoint(position0); + path.AddPoint(position1); + path.AddPoint(position2); + + //Control points for first segment + path.AddControlPoint( Vector3( 39.0, 90.0, 0.0) ); + path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) ); + + //Control points for second segment + path.AddControlPoint(Vector3( 78.0, 120.0, 0.0)); + path.AddControlPoint(Vector3( 93.0, 104.0, 0.0)); + + // Build the animation + float durationSeconds( 1.0f ); + Animation animation = Animation::New(durationSeconds); + animation.Animate(actor, path, Vector3::XAXIS, AlphaFunction::LINEAR); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.Render(0); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + Vector3 position, tangent; + Quaternion rotation; + path.Sample( 0.0f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + application.SendNotification(); + path.Sample( 0.25f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + application.SendNotification(); + path.Sample( 0.5f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + application.SendNotification(); + path.Sample( 0.75f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)+1/* 100% progress */); + application.SendNotification(); + path.Sample( 1.0f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + //Build the path + Vector3 position0( 30.0, 80.0, 0.0); + Vector3 position1( 70.0, 120.0, 0.0); + Vector3 position2( 100.0, 100.0, 0.0); + + Dali::Path path = Dali::Path::New(); + path.AddPoint(position0); + path.AddPoint(position1); + path.AddPoint(position2); + + //Control points for first segment + path.AddControlPoint( Vector3( 39.0, 90.0, 0.0) ); + path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) ); + + //Control points for second segment + path.AddControlPoint(Vector3( 78.0, 120.0, 0.0)); + path.AddControlPoint(Vector3( 93.0, 104.0, 0.0)); + + // Build the animation + float durationSeconds( 1.0f ); + Animation animation = Animation::New(durationSeconds); + animation.Animate(actor, path, Vector3::XAXIS, TimePeriod(0.0f, 1.0f)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.Render(0); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + Vector3 position, tangent; + Quaternion rotation; + path.Sample( 0.0f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + application.SendNotification(); + path.Sample( 0.25f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + application.SendNotification(); + path.Sample( 0.5f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + application.SendNotification(); + path.Sample( 0.75f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)+1/* 100% progress */); + application.SendNotification(); + path.Sample( 1.0f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationAnimateAlphaFunctionTimePeriodP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + //Build the path + Vector3 position0( 30.0, 80.0, 0.0); + Vector3 position1( 70.0, 120.0, 0.0); + Vector3 position2( 100.0, 100.0, 0.0); + + Dali::Path path = Dali::Path::New(); + path.AddPoint(position0); + path.AddPoint(position1); + path.AddPoint(position2); + + //Control points for first segment + path.AddControlPoint( Vector3( 39.0, 90.0, 0.0) ); + path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) ); + + //Control points for second segment + path.AddControlPoint(Vector3( 78.0, 120.0, 0.0)); + path.AddControlPoint(Vector3( 93.0, 104.0, 0.0)); + + // Build the animation + float durationSeconds( 1.0f ); + Animation animation = Animation::New(durationSeconds); + animation.Animate(actor, path, Vector3::XAXIS, AlphaFunction::LINEAR, TimePeriod(0.0f, 1.0f)); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + application.SendNotification(); + application.Render(0); + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + Vector3 position, tangent; + Quaternion rotation; + path.Sample( 0.0f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + application.SendNotification(); + path.Sample( 0.25f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + application.SendNotification(); + path.Sample( 0.5f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + application.SendNotification(); + path.Sample( 0.75f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + application.Render(static_cast(durationSeconds*250.0f)+1/* 100% progress */); + application.SendNotification(); + path.Sample( 1.0f, position, tangent ); + rotation = Quaternion( Vector3::XAXIS, tangent ); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION ); + + finishCheck.CheckSignalReceived(); + END_TEST; +} + +int UtcDaliAnimationShowP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetVisible(false); + application.SendNotification(); + application.Render(0); + DALI_TEST_CHECK( !actor.IsVisible() ); + Stage::GetCurrent().Add(actor); + + // Start the animation + float durationSeconds(10.0f); + Animation animation = Animation::New(durationSeconds); + animation.Show(actor, durationSeconds*0.5f); + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*490.0f)); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( !actor.IsVisible() ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*10.0f)/*Should be shown now*/); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.IsVisible() ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.IsVisible() ); + END_TEST; +} + +int UtcDaliAnimationHideP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_CHECK( actor.IsVisible() ); + Stage::GetCurrent().Add(actor); + + // Start the animation + float durationSeconds(10.0f); + Animation animation = Animation::New(durationSeconds); + animation.Hide(actor, durationSeconds*0.5f); + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*490.0f)); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( actor.IsVisible() ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*10.0f)/*Should be hidden now*/); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_CHECK( !actor.IsVisible() ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( !actor.IsVisible() ); + END_TEST; +} + +int UtcDaliAnimationShowHideAtEndP(void) +{ + // Test that show/hide delay can be the same as animation duration + // i.e. to show/hide at the end of the animation + + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_CHECK( actor.IsVisible() ); + Stage::GetCurrent().Add(actor); + + // Start Hide animation + float durationSeconds(10.0f); + Animation animation = Animation::New(durationSeconds); + animation.Hide(actor, durationSeconds/*Hide at end*/); + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*1000.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( !actor.IsVisible() ); + + // Start Show animation + animation = Animation::New(durationSeconds); + animation.Show(actor, durationSeconds/*Show at end*/); + animation.FinishedSignal().Connect(&application, finishCheck); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*1000.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_CHECK( actor.IsVisible() ); + END_TEST; +} + +int UtcDaliKeyFramesCreateDestroyP(void) +{ + tet_infoline("Testing Dali::Animation::UtcDaliKeyFramesCreateDestroy()"); + + KeyFrames* keyFrames = new KeyFrames; + delete keyFrames; + DALI_TEST_CHECK( true ); + END_TEST; +} + +int UtcDaliKeyFramesDownCastP(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Animation::KeyFramesDownCast()"); + + KeyFrames keyFrames = KeyFrames::New(); + BaseHandle object(keyFrames); + + KeyFrames keyFrames2 = KeyFrames::DownCast(object); + DALI_TEST_CHECK(keyFrames2); + + KeyFrames keyFrames3 = DownCast< KeyFrames >(object); + DALI_TEST_CHECK(keyFrames3); + + BaseHandle unInitializedObject; + KeyFrames keyFrames4 = KeyFrames::DownCast(unInitializedObject); + DALI_TEST_CHECK(!keyFrames4); + + KeyFrames keyFrames5 = DownCast< KeyFrames >(unInitializedObject); + DALI_TEST_CHECK(!keyFrames5); + END_TEST; +} + +int UtcDaliAnimationCreateDestroyP(void) +{ + TestApplication application; + Animation* animation = new Animation; + DALI_TEST_CHECK( animation ); + delete animation; + END_TEST; +} + +struct UpdateManagerTestConstraint +{ + UpdateManagerTestConstraint(TestApplication& application) + : mApplication(application) + { + } + + void operator()( Vector3& current, const PropertyInputContainer& /* inputs */) + { + mApplication.SendNotification(); // Process events + } + + TestApplication& mApplication; +}; + +int UtcDaliAnimationUpdateManagerP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + // Build the animation + Animation animation = Animation::New( 0.0f ); + + bool signalReceived = false; + AnimationFinishCheck finishCheck( signalReceived ); + animation.FinishedSignal().Connect( &application, finishCheck ); + + Vector3 startValue(1.0f, 1.0f, 1.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Constraint constraint = Constraint::New( actor, index, UpdateManagerTestConstraint( application ) ); + constraint.Apply(); + + // Apply animation to actor + animation.AnimateTo( Property(actor, Actor::Property::POSITION), Vector3( 100.f, 90.f, 80.f ), AlphaFunction::LINEAR ); + + animation.Play(); + + application.SendNotification(); + application.UpdateOnly( 16 ); + + finishCheck.CheckSignalNotReceived(); + + application.SendNotification(); // Process events + + finishCheck.CheckSignalReceived(); + + END_TEST; +} + +int UtcDaliAnimationSignalOrderP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + // Build the animations + Animation animation1 = Animation::New( 0.0f ); // finishes first frame + Animation animation2 = Animation::New( 0.02f ); // finishes in 20 ms + + bool signal1Received = false; + animation1.FinishedSignal().Connect( &application, AnimationFinishCheck( signal1Received ) ); + + bool signal2Received = false; + animation2.FinishedSignal().Connect( &application, AnimationFinishCheck( signal2Received ) ); + + // Apply animations to actor + animation1.AnimateTo( Property(actor, Actor::Property::POSITION), Vector3( 3.0f, 2.0f, 1.0f ), AlphaFunction::LINEAR ); + animation1.Play(); + animation2.AnimateTo( Property(actor, Actor::Property::SIZE ), Vector3( 10.0f, 20.0f, 30.0f ), AlphaFunction::LINEAR ); + animation2.Play(); + + DALI_TEST_EQUALS( signal1Received, false, TEST_LOCATION ); + DALI_TEST_EQUALS( signal2Received, false, TEST_LOCATION ); + + application.SendNotification(); + application.UpdateOnly( 10 ); // 10ms progress + + // no notifications yet + DALI_TEST_EQUALS( signal1Received, false, TEST_LOCATION ); + DALI_TEST_EQUALS( signal2Received, false, TEST_LOCATION ); + + application.SendNotification(); + + // first completed + DALI_TEST_EQUALS( signal1Received, true, TEST_LOCATION ); + DALI_TEST_EQUALS( signal2Received, false, TEST_LOCATION ); + signal1Received = false; + + // 1st animation is complete now, do another update with no ProcessEvents in between + application.UpdateOnly( 20 ); // 20ms progress + + // ProcessEvents + application.SendNotification(); + + // 2nd should complete now + DALI_TEST_EQUALS( signal1Received, false, TEST_LOCATION ); + DALI_TEST_EQUALS( signal2Received, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliAnimationExtendDurationP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Register a float property + float startValue(10.0f); + Property::Index index = actor.RegisterProperty( "test-property", startValue ); + Stage::GetCurrent().Add(actor); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float initialDurationSeconds(1.0f); + float animatorDelay = 5.0f; + float animatorDurationSeconds(5.0f); + float extendedDurationSeconds(animatorDelay+animatorDurationSeconds); + Animation animation = Animation::New(initialDurationSeconds); + float targetValue(30.0f); + float relativeValue(targetValue - startValue); + + animation.AnimateTo(Property(actor, index), + targetValue, + TimePeriod(animatorDelay, animatorDurationSeconds)); + + // The duration should have been extended + DALI_TEST_EQUALS( animation.GetDuration(), extendedDurationSeconds, TEST_LOCATION ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(extendedDurationSeconds*500.0f)/* 50% animation progress, 0% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(extendedDurationSeconds*250.0f)/* 75% animation progress, 50% animator progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue+(relativeValue*0.5f), TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(extendedDurationSeconds*250.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), targetValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnimationCustomIntProperty(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + int startValue(0u); + + Property::Index index = actor.RegisterProperty("an-index", startValue); + DALI_TEST_EQUALS( actor.GetProperty(index), startValue, TEST_LOCATION ); + + // Build the animation + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + animation.AnimateTo( Property(actor, index), 20 ); + + // Start the animation + animation.Play(); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f)/* 50% progress */); + + // We didn't expect the animation to finish yet + application.SendNotification(); + finishCheck.CheckSignalNotReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), 10, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/); + + // We did expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetProperty(index), 20, TEST_LOCATION ); + END_TEST; +} + diff --git a/automated-tests/src/dali/utc-Dali-Any.cpp b/automated-tests/src/dali/utc-Dali-Any.cpp new file mode 100644 index 0000000..f516cf0 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Any.cpp @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include + +// Temp include +#include + +namespace +{ +struct MyStruct +{ + MyStruct() + : mFloatValue( 0.f ), + mIntValue( 0 ) + {} + + MyStruct( float fValue, int iValue ) + : mFloatValue( fValue ), + mIntValue( iValue ) + {} + + MyStruct( const MyStruct& myStruct ) + : mFloatValue( myStruct.mFloatValue ), + mIntValue( myStruct.mIntValue ) + {} + + MyStruct& operator=( const MyStruct& myStruct ) + { + mFloatValue = myStruct.mFloatValue; + mIntValue = myStruct.mIntValue; + + return *this; + } + + float mFloatValue; + int mIntValue; +}; +} + +using namespace Dali; + +void utc_dali_any_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_any_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliAnyConstructors(void) +{ + TestApplication application; + + tet_infoline("Test Any constructors."); + + // Test default constructor. + Any value; + + DALI_TEST_CHECK( typeid( void ) == value.GetType() ); + + // Test constructor Any( const Type& ) + Any value1 = 4u; + + // Test constructor Any( const Any& ) + Any value2 = value1; + + // Test constructor Any( const Any& ) with a non initialized Any + Any value3 = value; + + DALI_TEST_CHECK( typeid( unsigned int ) == value1.GetType() ); + DALI_TEST_CHECK( typeid( unsigned int ) == value2.GetType() ); + DALI_TEST_CHECK( typeid( void ) == value3.GetType() ); + + unsigned int uiValue1 = 0u; + unsigned int uiValue2 = 0u; + value1.Get( uiValue1 ); + value2.Get( uiValue2 ); + + DALI_TEST_EQUALS( uiValue1, uiValue2, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliAnyAssignmentOperators(void) +{ + TestApplication application; + + tet_infoline("Test assignment operators."); + + float fValue = 0.f; + + Any value1; + + value1 = 4.f; // Test operator=( const Type& ) when current object is not initialized. + + value1.Get( fValue ); + + DALI_TEST_EQUALS( fValue, 4.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + Any value2 = 0.f; + + value2 = 9.f; // Test operator=( const Type& ). + + value2.Get( fValue ); + + DALI_TEST_EQUALS( fValue, 9.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + Any value3 = 5.f; + + value1 = value3; // Test operator=( const Any& ). + + value1.Get( fValue ); + + DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + Any value4; + + value4 = value3; // Test operator=( const Any& ) when current object is not initialized. + + value4.Get( fValue ); + + DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + // Test assign a value to value3 doesn't modify value1. + value3 = 3.f; + + value1.Get( fValue ); + + DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + value3.Get( fValue ); + + DALI_TEST_EQUALS( fValue, 3.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + // Test the branch when copying the same object. + Any value5 = 3.f; + Any& value6( value5 ); + + value6 = value5; + + value6.Get( fValue ); + DALI_TEST_EQUALS( fValue, 3.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + // test assignment for non-empty Any = empty Any + Any value7; + value6 = value7; + DALI_TEST_CHECK( value6.Empty() ); + + + END_TEST; +} + +int UtcDaliAnyNegativeAssignmentOperators(void) +{ + TestApplication application; + + tet_infoline("Test assignment operators."); + + Any value1 = 4.f; + Any value2 = 5u; + + bool assert = false; + + try + { + value1 = value2; // Test operator=( const Any& ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + assert = true; + } + + if( assert ) + { + tet_result( TET_PASS ); + } + else + { + tet_result( TET_FAIL ); + } + END_TEST; +} + +int UtcDaliAnyGetType(void) +{ + TestApplication application; + + tet_infoline("Test GetType()."); + + Any value; + + DALI_TEST_CHECK( typeid( void ) == value.GetType() ); + + value = 5.f; + + DALI_TEST_CHECK( typeid( float ) == value.GetType() ); + END_TEST; +} + +int UtcDaliAnyGet(void) +{ + TestApplication application; + + tet_infoline("Test Get()."); + + Any value1( 5.f ); + + float fValue = value1.Get(); + + DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + fValue = 0.f; + value1.Get( fValue ); + DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + + class MyClass + { + public: + MyClass( float fValue, int iValue ) + : mAny( MyStruct( fValue, iValue ) ) + { + } + + const MyStruct& Get() const + { + return AnyCastReference( mAny ); + } + + MyStruct* GetPointer() + { + return AnyCast( &mAny ); + } + + const MyStruct* GetPointer() const + { + return AnyCast( &mAny ); + } + + private: + Dali::Any mAny; + }; + + MyClass myClass( 3.25f, 3 ); + + MyStruct myStruct1 = myClass.Get(); + const MyStruct& myStruct2 = myClass.Get(); + MyStruct* myStruct3 = myClass.GetPointer(); + const MyStruct* myStruct4 = myClass.GetPointer(); + + DALI_TEST_EQUALS( myStruct1.mFloatValue, 3.25f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_EQUALS( myStruct2.mFloatValue, 3.25f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_EQUALS( myStruct3->mFloatValue, 3.25f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_EQUALS( myStruct4->mFloatValue, 3.25f, Math::MACHINE_EPSILON_1000, TEST_LOCATION ); + DALI_TEST_EQUALS( myStruct1.mIntValue, 3, TEST_LOCATION ); + DALI_TEST_EQUALS( myStruct2.mIntValue, 3, TEST_LOCATION ); + DALI_TEST_EQUALS( myStruct3->mIntValue, 3, TEST_LOCATION ); + DALI_TEST_EQUALS( myStruct4->mIntValue, 3, TEST_LOCATION ); + + // Test on empty any object + Dali::Any myAny; + float* f = myAny.GetPointer(); + DALI_TEST_CHECK( f == NULL ); + + // Test on getting wrong type + myAny = 1.f; + try + { + myAny.GetPointer(); + tet_result( TET_FAIL ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + } + + END_TEST; +} + +int UtcDaliAnyNegativeGet(void) +{ + TestApplication application; + tet_infoline("Test Get()."); + + Any value1; + Any value2( 5.f ); + + bool assert1 = false; + bool assert2 = false; + + unsigned int uiValue = 0u; + + try + { + uiValue = value1.Get< unsigned int >(); + } + + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + assert1 = true; + } + + try + { + uiValue = value2.Get< unsigned int >(); + } + + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + assert2 = true; + } + + if( assert1 && assert2 ) + { + tet_result( TET_PASS ); + } + else + { + tet_result( TET_FAIL ); + } + uiValue++; // supresss warning from unused variable + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-BaseHandle.cpp b/automated-tests/src/dali/utc-Dali-BaseHandle.cpp new file mode 100644 index 0000000..9e3da41 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-BaseHandle.cpp @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +#include "dali-test-suite-utils/dali-test-suite-utils.h" + +using namespace Dali; + + +void utc_base_handle_startup(void) +{ + test_return_value = TET_UNDEF; +} + +// Called after each test +void utc_base_handle_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +// Functor to test whether an animation finish signal is emitted +struct AnimationFinishCheck +{ + AnimationFinishCheck(bool& signalReceived) + : mSignalReceived(signalReceived) + { + } + + void operator()(Animation& animation) + { + mSignalReceived = true; + } + + void Reset() + { + mSignalReceived = false; + } + + void CheckSignalReceived() + { + if (!mSignalReceived) + { + tet_printf("Expected Finish signal was not received\n"); + tet_result(TET_FAIL); + } + else + { + tet_result(TET_PASS); + } + } + + bool& mSignalReceived; // owned by individual tests +}; + +BaseHandle ImplicitCopyConstructor(BaseHandle passedByValue) +{ + // object + copy + passedByValue, ref count == 3 + DALI_TEST_CHECK(passedByValue); + if (passedByValue) + { + DALI_TEST_EQUALS(3, passedByValue.GetBaseObject().ReferenceCount(), TEST_LOCATION); + } + + return passedByValue; +} + +static bool gTouchCallBackCalled; + +struct TestCallback +{ + void operator()() + { + gTouchCallBackCalled = true; + } +}; + +// Used for testing BaseObject::GetTypeName with an object that is not registered +class FakeObject : public BaseObject +{ +}; +// used for testing ThisIsSaferThanReturningVoidStar +class FakeHandle : public BaseHandle +{ +public: + + void RunTest() + { + return ThisIsSaferThanReturningVoidStar(); + } +}; +} // anon namespace + +int UtcDaliBaseHandleConstructorVoid(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle::BaseHandle()"); + + BaseHandle object; + + DALI_TEST_CHECK(!object); + END_TEST; +} + + +int UtcDaliBaseHandleCopyConstructor(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle::BaseHandle(const BaseHandle&)"); + + // Initialize an object, ref count == 1 + BaseHandle object = Actor::New(); + + DALI_TEST_EQUALS(1, object.GetBaseObject().ReferenceCount(), TEST_LOCATION); + + // Copy the object, ref count == 2 + BaseHandle copy(object); + DALI_TEST_CHECK(copy); + if (copy) + { + DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION); + } + + { + // Pass by value, and return another copy, ref count == 3 + BaseHandle anotherCopy = ImplicitCopyConstructor(copy); + + DALI_TEST_CHECK(anotherCopy); + if (anotherCopy) + { + DALI_TEST_EQUALS(3, anotherCopy.GetBaseObject().ReferenceCount(), TEST_LOCATION); + } + } + + // anotherCopy out of scope, ref count == 2 + DALI_TEST_CHECK(copy); + if (copy) + { + DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliBaseHandleAssignmentOperator(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle::operator="); + + BaseHandle object = Actor::New(); + + DALI_TEST_CHECK(object); + if (object) + { + DALI_TEST_EQUALS(1, object.GetBaseObject().ReferenceCount(), TEST_LOCATION); + } + + BaseHandle copy = object; + + DALI_TEST_CHECK(copy); + if (copy) + { + DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliBaseHandleGetBaseObject(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle::GetBaseObject()"); + + BaseHandle object = Actor::New(); + + BaseObject& handle = object.GetBaseObject(); + + DALI_TEST_EQUALS(1, handle.ReferenceCount(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliBaseHandleReset(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle::Reset()"); + + // Initialize an object, ref count == 1 + BaseHandle object = Actor::New(); + + DALI_TEST_EQUALS(1, object.GetBaseObject().ReferenceCount(), TEST_LOCATION); + + object.Reset(); + + DALI_TEST_CHECK(!object); + END_TEST; +} + +int UtcDaliBaseHandleEqualityOperator01(void) +{ + TestApplication application; + tet_infoline("Positive Test Dali::BaseHandle::operator=="); + + BaseHandle object = Actor::New(); + + DALI_TEST_CHECK(object); + + BaseHandle theSameBaseHandle = object; + + DALI_TEST_CHECK(object == theSameBaseHandle); + END_TEST; +} + +int UtcDaliBaseHandleEqualityOperator02(void) +{ + TestApplication application; + tet_infoline("Negative Test Dali::BaseHandle::operator=="); + + BaseHandle object = Actor::New(); + + DALI_TEST_CHECK(object); + + BaseHandle aDifferentBaseHandle = Actor::New(); + + DALI_TEST_CHECK(!(object == aDifferentBaseHandle)); + END_TEST; +} + +int UtcDaliBaseHandleInequalityOperator01(void) +{ + TestApplication application; + tet_infoline("Positive Test Dali::BaseHandle::operator!="); + + BaseHandle object = Actor::New(); + + DALI_TEST_CHECK(object); + + BaseHandle aDifferentBaseHandle = Actor::New(); + + DALI_TEST_CHECK(object != aDifferentBaseHandle); + END_TEST; +} + +int UtcDaliBaseHandleInequalityOperator02(void) +{ + TestApplication application; + tet_infoline("Negative Test Dali::BaseHandle::operator!="); + + BaseHandle object = Actor::New(); + + DALI_TEST_CHECK(object); + + BaseHandle theSameBaseHandle = object; + + DALI_TEST_CHECK(!(object != theSameBaseHandle)); + END_TEST; +} + +int UtcDaliBaseHandleStlVector(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle compatibility with std::vector"); + + const int TargetVectorSize(5); + + std::vector myVector; + + for (int i=0; i(myVector.size()), TEST_LOCATION); + + DALI_TEST_CHECK(myVector[0].GetName() == "Actor 1"); + DALI_TEST_CHECK(myVector[1].GetName() == "Actor 2"); + DALI_TEST_CHECK(myVector[2].GetName() == "Actor 3"); + DALI_TEST_CHECK(myVector[3].GetName() == "Actor 4"); + DALI_TEST_CHECK(myVector[4].GetName() == "Actor 5"); + END_TEST; +} + +int UtcDaliBaseHandleDoAction(void) +{ + TestApplication application; + tet_infoline("Positive Test Dali::BaseHandle::UtcDaliBaseHandleDoAction"); + + Actor actor = Actor::New(); + BaseHandle actorObject = actor; + + DALI_TEST_CHECK(actorObject); + + // Check that an invalid command is not performed + Property::Map attributes; + DALI_TEST_CHECK(actorObject.DoAction("invalidCommand", attributes) == false); + + // Check that the actor is visible + actor.SetVisible(true); + DALI_TEST_CHECK(actor.IsVisible() == true); + + // Check the actor performed an action to hide itself + DALI_TEST_CHECK(actorObject.DoAction("hide", attributes) == true); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + // Check that the actor is now invisible + DALI_TEST_CHECK(actor.IsVisible() == false); + + // Check the actor performed an action to show itself + DALI_TEST_CHECK(actorObject.DoAction("show", attributes) == true); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + // Check that the actor is now visible + DALI_TEST_CHECK(actor.IsVisible() == true); + + Stage::GetCurrent().Add(actor); + + // Build an animation with initial duration of 1 second + float durationSeconds(1.0f); + Animation animation = Animation::New(durationSeconds); + BaseHandle animationObject = animation; + + DALI_TEST_CHECK(animationObject); + + // Check the current animation duration is 1 second + DALI_TEST_EQUALS(animation.GetDuration(), durationSeconds, TEST_LOCATION); + + Vector3 targetPosition(100.0f, 100.0f, 100.0f); + animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR); + + // Set the new duration to be 2 seconds + float newDurationSeconds(2.0f); + Property::Value newDurationSecondsValue = Property::Value( newDurationSeconds ); + attributes["duration"] = newDurationSecondsValue; + + // Check the animation performed an action to play itself with the specified duration of 2 seconds + animationObject.DoAction("play", attributes); + + bool signalReceived(false); + AnimationFinishCheck finishCheck(signalReceived); + animation.FinishedSignal().Connect(&application, finishCheck); + + application.SendNotification(); + application.Render(static_cast(newDurationSeconds * 1000.0f) + 1u/*just beyond the animation duration*/); + + // We expect the animation to finish + application.SendNotification(); + finishCheck.CheckSignalReceived(); + DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION ); + + // Check the new animation duration is 2 seconds + DALI_TEST_EQUALS(animation.GetDuration(), newDurationSeconds, TEST_LOCATION); + END_TEST; +} + + +int UtcDaliBaseHandleConnectSignal(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle::ConnectSignal"); + + gTouchCallBackCalled = false; + + // get the root layer + Actor actor = Actor::New(); + actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + actor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + actor.SetPosition( 240, 400 ); + actor.SetSize( 100, 100 ); + + Stage::GetCurrent().Add( actor ); + + DALI_TEST_CHECK( gTouchCallBackCalled == false ); + + // connect to its touch signal + actor.ConnectSignal( &application, "touched", TestCallback() ); + + application.SendNotification(); + application.Render(1000); + application.SendNotification(); + application.Render(1000); + + // simulate a touch event + Dali::TouchPoint point( 0, TouchPoint::Down, 240, 400 ); + Dali::Integration::TouchEvent event; + event.AddPoint( point ); + application.ProcessEvent( event ); + + application.SendNotification(); + application.Render(1000); + application.SendNotification(); + application.Render(1000); + + DALI_TEST_CHECK( application.GetConnectionCount() > 0 ); + DALI_TEST_CHECK( gTouchCallBackCalled == true ); + + gTouchCallBackCalled = false; + application.DisconnectAll(); + + // simulate another touch event + application.ProcessEvent( event ); + + DALI_TEST_CHECK( gTouchCallBackCalled == false ); + END_TEST; +} + +int UtcDaliBaseHandleGetTypeNameP(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle::GetTypeName"); + + // get the root layer + Actor actor = Actor::New(); + + std::string typeName = actor.GetTypeName(); + + DALI_TEST_CHECK( typeName.size() ); + DALI_TEST_CHECK( typeName == std::string("Actor") ); + END_TEST; +} + +int UtcDaliBaseHandleGetTypeNameN(void) +{ + + TestApplication application; + tet_infoline("Testing Dali::BaseObject::GetTypeName"); + FakeObject object; + std::string typeName = object.GetTypeName(); + + DALI_TEST_CHECK( typeName.empty() ); + END_TEST; +} + +int UtcDaliBaseHandleGetTypeInfoP(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle::GetTypeInfo"); + + Dali::TypeInfo info; + Actor actor = Actor::New(); + + bool ok = actor.GetTypeInfo( info ); + DALI_TEST_CHECK( ok ); + END_TEST; +} + +int UtcDaliBaseHandleThisIsSaferThanReturningVoidStar(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle::GetTypeInfo"); + FakeHandle handle; + handle.RunTest(); + tet_result(TET_PASS); + END_TEST; + +} + +int UtcDaliBaseHandleGetTypeInfoN(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle::GetTypeInfo"); + + Dali::TypeInfo info; + FakeObject object; + + bool ok = object.GetTypeInfo( info ); + DALI_TEST_CHECK( !ok ); + END_TEST; +} + +int UtcDaliBaseHandleGetObjectPtr(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle::GetObjectPtr"); + + // get the root layer + Actor actor = Actor::New(); + + Dali::RefObject* p = actor.GetObjectPtr(); + + DALI_TEST_CHECK( p != NULL ); + END_TEST; +} + +int UtcDaliBaseHandleBooleanCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BaseHandle::BooleanType"); + + // get the root layer + BaseHandle handle = Actor::New(); + + DALI_TEST_CHECK( static_cast( handle ) ); + END_TEST; +} + +int UtcDaliBaseHandleCompareOperatorN(void) +{ + TestApplication application; + BaseHandle handle1 = Actor::New(); + BaseHandle handle2 = handle1; + + DALI_TEST_CHECK( (handle1 < handle2) == false ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-BufferImage.cpp b/automated-tests/src/dali/utc-Dali-BufferImage.cpp new file mode 100644 index 0000000..bd3a05c --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-BufferImage.cpp @@ -0,0 +1,515 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include + +using std::max; +using namespace Dali; + +void utc_dali_buffer_image_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_buffer_image_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliBufferImageNew01(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageNew01 - BufferImage::New(unsigned int, unsigned int, Pixel::Format)"); + + // invoke default handle constructor + BufferImage image; + + // initialise handle + image = BufferImage::New(16, 16); + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK( image.GetWidth() == 16); + END_TEST; +} + +int UtcDaliBufferImageNew02(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageNew02 - BufferImage::New(PixelBuffer*, unsigned int, unsigned int, Pixel::Format, unsigned int)"); + + PixelBuffer* buffer = new PixelBuffer[16 * 16]; + BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8); + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK( image.GetWidth() == 16); + + delete [] buffer; + END_TEST; +} + +int UtcDaliBufferImageNewWithPolicy01(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageNewWithPolicy01 - BufferImage::New(unsigned int, unsigned int, Pixel::Format, LoadPolicy, ReleasePolicy)"); + + // Force texture id's + std::vector ids; + ids.push_back( 23 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + + // invoke default handle constructor + BufferImage image; + + // initialise handle + image = BufferImage::New(16, 16, Pixel::A8, Image::UNUSED); + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK( image.GetWidth() == 16); + ImageActor actor = ImageActor::New(image); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + // testing ReleasePolicy::Unused + // fake loading image + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) ); + + // discard texture when actor comes off stage + Stage::GetCurrent().Remove(actor); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + DALI_TEST_CHECK ( application.GetGlAbstraction().CheckTextureDeleted(23) ); + END_TEST; +} + +int UtcDaliBufferImageNewWithPolicy02(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageNewWithPolicy02 - BufferImage::New(PixelBuffer*, unsigned int, unsigned int, Pixel::Format, unsigned int, ReleasePolicy)"); + + // Force texture id's + std::vector ids; + ids.push_back( 23 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + + PixelBuffer* buffer = new PixelBuffer[16 * 16]; + BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8, 16, Image::UNUSED); + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK( image.GetWidth() == 16); + ImageActor actor = ImageActor::New(image); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + // testing ReleasePolicy::Unused + // fake loading image + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) ); + + // discard texture when actor comes off stage + Stage::GetCurrent().Remove(actor); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + DALI_TEST_CHECK ( application.GetGlAbstraction().CheckTextureDeleted(23) ); + END_TEST; +} + +int UtcDaliBufferImageDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BufferImage::DownCast()"); + + BufferImage bitmap = BufferImage::New(1, 1, Dali::Pixel::BGRA8888); + ImageActor imageActor = ImageActor::New(bitmap); + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + Image image = imageActor.GetImage(); + BufferImage bufferImage = BufferImage::DownCast( image ); + + DALI_TEST_CHECK(bufferImage); + END_TEST; +} + +int UtcDaliBufferImageDownCast2(void) +{ + TestApplication application; + tet_infoline("Testing Dali::BufferImage::DownCast()"); + + Image image = ResourceImage::New("IncorrectImageName"); + ImageActor imageActor = ImageActor::New(image); + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + Image image1 = imageActor.GetImage(); + + BufferImage bufferImage = BufferImage::DownCast( image1 ); + DALI_TEST_CHECK(!bufferImage); + + Actor unInitialzedActor; + bufferImage = BufferImage::DownCast( unInitialzedActor ); + DALI_TEST_CHECK(!bufferImage); + END_TEST; +} + +int UtcDaliBufferImageWHITE(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageWHITE - BufferImage::WHITE()"); + + BufferImage image = BufferImage::WHITE(); // creates a 1x1 RGBA white pixel + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + PixelBuffer* buffer = image.GetBuffer(); + + DALI_TEST_CHECK( image.GetWidth() == 1 && // 1 pixel wide + buffer != NULL && // valid buffer + *buffer == 0xff); // r component is 255 + END_TEST; +} + +int UtcDaliBufferImageGetBuffer(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageGetBuffer"); + + BufferImage image = BufferImage::WHITE(); // creates a 1x1 RGBA white pixel + + PixelBuffer* buffer = image.GetBuffer(); + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + DALI_TEST_CHECK( image.GetWidth() == 1 && // 1 pixel wide + buffer != NULL && // valid buffer + *((unsigned int*)buffer) == 0xffffffff); // all component are 255 + END_TEST; +} + +int UtcDaliBufferImageGetBufferSize(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageGetBufferSize"); + + BufferImage image = BufferImage::WHITE(); // creates a 1x1 RGBA white pixel + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + PixelBuffer* buffer = image.GetBuffer(); + unsigned int bufferSize = image.GetBufferSize(); + unsigned int pixelSize = Pixel::GetBytesPerPixel(image.GetPixelFormat()); + + DALI_TEST_CHECK( image.GetWidth() == 1 && // 1 pixel wide + buffer != NULL && // valid buffer + bufferSize == pixelSize); // r component is 255 + END_TEST; +} + +int UtcDaliBufferImageGetBufferStride(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageGetBufferStride"); + + BufferImage image = BufferImage::WHITE(); // creates a 1x1 RGBA white pixel + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + unsigned int pixelSize = Pixel::GetBytesPerPixel(image.GetPixelFormat()); + unsigned int bufferStride = image.GetBufferStride(); + DALI_TEST_CHECK( bufferStride == pixelSize ); + DALI_TEST_CHECK( !image.IsDataExternal() ); + + PixelBuffer* buffer = new PixelBuffer[20 * 16]; + image = BufferImage::New(buffer, 16, 16, Pixel::A8, 20); + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + bufferStride = image.GetBufferStride(); + + DALI_TEST_CHECK( bufferStride == 20); + DALI_TEST_CHECK( image.IsDataExternal() ); + + delete [] buffer; + END_TEST; +} + +int UtcDaliBufferImageGetPixelFormat(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageGetPixelFormat"); + + // Set pixel format to a non-default + BufferImage image = BufferImage::New( 16, 16, Pixel::A8 ); + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK( image.GetPixelFormat() == Pixel::A8 ); + END_TEST; +} + + +int UtcDaliBufferImageIsDataExternal(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageIsDataExternal - BufferImage::IsDataExternal()"); + + PixelBuffer* buffer = new PixelBuffer[16 * 16]; + BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8); + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + DALI_TEST_CHECK( image.IsDataExternal() ); + END_TEST; +} + +namespace +{ + +static bool SignalReceived; +static void ImageUploaded(Image image) +{ + tet_infoline("Received image uploaded signal"); + SignalReceived = true; +} +} + +int UtcDaliBufferImageUpdate01(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageUpdate01 - single empty rect"); + + PixelBuffer* buffer = new PixelBuffer[16 * 16]; + + BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8); + ImageActor actor = ImageActor::New(image); + Stage::GetCurrent().Add(actor); + actor.SetVisible(true); + + SignalReceived = false; + image.UploadedSignal().Connect( ImageUploaded ); + + std::vector ids; + ids.push_back(200); + ids.push_back(201); + ids.push_back(202); + application.GetGlAbstraction().SetNextTextureIds(ids); + + // Allow actor to be staged and rendered + application.SendNotification(); + application.Render(0); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK( image.IsDataExternal() ); + application.GetGlAbstraction().EnableTextureCallTrace(true); + + image.Update();//(RectArea()); // notify Core that the image has been updated + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + + const TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace(); + DALI_TEST_EQUALS( callStack.TestMethodAndParams(0, "TexSubImage2D", "0, 0, 16, 16"), true, TEST_LOCATION); + + DALI_TEST_CHECK( SignalReceived == true ); + SignalReceived = false; + END_TEST; +} + +int UtcDaliBufferImageUpdate02(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageUpdate02 - Multiple rects"); + + PixelBuffer* buffer = new PixelBuffer[16 * 16]; + BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8); + ImageActor actor = ImageActor::New(image); + Stage::GetCurrent().Add(actor); + actor.SetVisible(true); + + SignalReceived = false; + image.UploadedSignal().Connect( ImageUploaded ); + + std::vector ids; + ids.push_back(200); + ids.push_back(201); + ids.push_back(202); + application.GetGlAbstraction().SetNextTextureIds(ids); + + application.SendNotification(); + application.Render(0); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK( image.IsDataExternal() ); + application.GetGlAbstraction().EnableTextureCallTrace(true); + + image.Update(RectArea(9,9,5,5)); // notify Core that the image has been updated + + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + + const TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace(); + DALI_TEST_EQUALS( callStack.TestMethodAndParams(0, "TexSubImage2D", "9, 9, 5, 1"), true, TEST_LOCATION); + DALI_TEST_EQUALS( callStack.TestMethodAndParams(1, "TexSubImage2D", "9, 10, 5, 1"), true, TEST_LOCATION); + DALI_TEST_EQUALS( callStack.TestMethodAndParams(2, "TexSubImage2D", "9, 11, 5, 1"), true, TEST_LOCATION); + DALI_TEST_EQUALS( callStack.TestMethodAndParams(3, "TexSubImage2D", "9, 12, 5, 1"), true, TEST_LOCATION); + DALI_TEST_EQUALS( callStack.TestMethodAndParams(4, "TexSubImage2D", "9, 13, 5, 1"), true, TEST_LOCATION); + + DALI_TEST_CHECK( SignalReceived == true ); + SignalReceived = false; + END_TEST; +} + +int UtcDaliBufferImageUploadedSignal01(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageUploadedSignal - Test that Uploaded signal is sent when image is staged"); + + PixelBuffer* buffer = new PixelBuffer[16 * 16]; + BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8); + SignalReceived = false; + image.UploadedSignal().Connect( ImageUploaded ); + + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + Dali::ImageActor imageActor = ImageActor::New(image); + Stage::GetCurrent().Add(imageActor); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK( SignalReceived == true ); + END_TEST; +} + +int UtcDaliBufferImageUploadedSignal02(void) +{ + TestApplication application; + + tet_infoline("UtcDaliBufferImageUploadedSignal - Test that Uploaded signal is sent after Update"); + + PixelBuffer* buffer = new PixelBuffer[16 * 16]; + BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8); + SignalReceived = false; + //ScopedConnection connection = + image.UploadedSignal().Connect( ImageUploaded ); + + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + Dali::ImageActor imageActor = ImageActor::New(image); + Stage::GetCurrent().Add(imageActor); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + DALI_TEST_CHECK( SignalReceived == true ); + SignalReceived = false; + + image.Update(RectArea()); // notify Core that the whole image has been updated + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + DALI_TEST_CHECK( SignalReceived == true ); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-CameraActor.cpp b/automated-tests/src/dali/utc-Dali-CameraActor.cpp new file mode 100644 index 0000000..15e86c4 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-CameraActor.cpp @@ -0,0 +1,1552 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +#include "dali-test-suite-utils/dali-test-suite-utils.h" + +using namespace Dali; + +void camera_actor_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void camera_actor_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +const float FLOAT_EPSILON = 0.001f; +const float TEST_ASPECT_RATIO = 0.123f; +const float TEST_FIELD_OF_VIEW = Radian(Degree(40.0f)); +const float TEST_NEAR_PLANE_DISTANCE = 0.23f; +const float TEST_FAR_PLANE_DISTANCE = 0.973f; + +const std::string SHADER_LIGHT_CAMERA_PROJECTION_MATRIX_PROPERTY_NAME( "uLightCameraProjectionMatrix" ); +const std::string SHADER_LIGHT_CAMERA_VIEW_MATRIX_PROPERTY_NAME( "uLightCameraViewMatrix" ); +const char* const RENDER_SHADOW_VERTEX_SOURCE = + " uniform mediump mat4 uLightCameraProjectionMatrix;\n" + " uniform mediump mat4 uLightCameraViewMatrix;\n" + "\n" + "void main()\n" + "{\n" + " gl_Position = uProjection * uModelView * vec4(aPosition,1.0);\n" + " vec4 textureCoords = uLightCameraProjectionMatrix * uLightCameraViewMatrix * uModelMatrix * vec4(aPosition,1.0);\n" + " vTexCoord = 0.5 + 0.5 * (textureCoords.xy/textureCoords.w);\n" + "}\n"; + +const char* const RENDER_SHADOW_FRAGMENT_SOURCE = + "uniform lowp vec4 uShadowColor;\n" + "void main()\n" + "{\n" + " lowp float alpha;\n" + " alpha = texture2D(sTexture, vec2(vTexCoord.x, vTexCoord.y)).a;\n" + " gl_FragColor = vec4(uShadowColor.rgb, uShadowColor.a * alpha);\n" + "}\n"; + +} // Anonymous namespace + + +int UtcDaliCameraActorConstructorP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::CameraActor()" ); + + CameraActor actor; + + DALI_TEST_CHECK( !actor ); + END_TEST; +} + +// Note: No negative test for UtcDaliCameraActorConstructor. + +int UtcDaliCameraActorDestructorP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::~CameraActor (P)" ); + CameraActor* actor = new CameraActor(); + delete actor; + actor = NULL; + + DALI_TEST_CHECK( true ); + END_TEST; +} + +// Note: No negative test for UtcDaliCameraActorDestructor. + +int UtcDaliCameraActorCopyConstructorP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Copy Constructor (P)" ); + CameraActor actor = CameraActor::New(); + + CameraActor copyActor( actor ); + + DALI_TEST_CHECK( copyActor ); + DALI_TEST_CHECK( copyActor == actor ); + + END_TEST; +} + +int UtcDaliCameraActorCopyConstructorN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Copy Constructor (N)" ); + CameraActor actor; + + CameraActor copyActor( actor ); + + DALI_TEST_CHECK( !copyActor ); + + END_TEST; +} + +int UtcDaliCameraActorAssignmentOperatorP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Assignment Operator (P)" ); + const CameraActor actor = CameraActor::New(); + + CameraActor copyActor = actor; + + DALI_TEST_CHECK( copyActor ); + DALI_TEST_CHECK( copyActor == actor ); + + END_TEST; +} + +int UtcDaliCameraActorAssignmentOperatorN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor = (N)" ); + CameraActor actor; + + CameraActor copyActor = actor; + + DALI_TEST_CHECK( !copyActor ); + + END_TEST; +} + +int UtcDaliCameraActorNewP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::New (P)" ); + + CameraActor actor = CameraActor::New(); + + DALI_TEST_CHECK( actor ); + + actor.Reset(); + + DALI_TEST_CHECK( !actor ); + END_TEST; +} + +// Note: No negative test for UtcDaliCameraActorNew. + +int UtcDaliCameraActorDownCastP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::DownCast (P)" ); + + CameraActor camera = CameraActor::New(); + Actor anActor = Actor::New(); + anActor.Add( camera ); + + Actor child = anActor.GetChildAt( 0 ); + CameraActor cameraActor = CameraActor::DownCast( child ); + DALI_TEST_CHECK( cameraActor ); + + cameraActor.Reset(); + DALI_TEST_CHECK( !cameraActor ); + + cameraActor = DownCast< CameraActor >( child ); + DALI_TEST_CHECK( cameraActor ); + END_TEST; +} + +int UtcDaliCameraActorDownCastN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::DownCast (N)" ); + + Actor actor1 = Actor::New(); + Actor anActor = Actor::New(); + anActor.Add( actor1 ); + + Actor child = anActor.GetChildAt( 0 ); + CameraActor cameraActor = CameraActor::DownCast( child ); + DALI_TEST_CHECK( !cameraActor ); + + Actor unInitialzedActor; + cameraActor = CameraActor::DownCast( unInitialzedActor ); + DALI_TEST_CHECK( !cameraActor ); + + cameraActor = DownCast< CameraActor >( unInitialzedActor ); + DALI_TEST_CHECK( !cameraActor ); + END_TEST; +} + +// Note: SetType and GetType are tested within the same test cases. + +int UtcDaliCameraActorSetGetTypeP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor GetType (P)" ); + + CameraActor actor = CameraActor::New(); + DALI_TEST_EQUALS( actor.GetType(), Dali::Camera::FREE_LOOK, TEST_LOCATION ); + + actor.SetType( Dali::Camera::LOOK_AT_TARGET ); + DALI_TEST_EQUALS( actor.GetType(), Dali::Camera::LOOK_AT_TARGET, TEST_LOCATION ); + + std::string sValue; + actor.GetProperty( CameraActor::Property::TYPE ).Get( sValue ); + std::string result( "LOOK_AT_TARGET"); + DALI_TEST_EQUALS( result, sValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorSetGetTypeN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor GetType (N)" ); + + CameraActor actor; + + Dali::Camera::Type cameraType = Dali::Camera::FREE_LOOK; + try + { + cameraType = actor.GetType(); + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera", TEST_LOCATION ); + } + + const CameraActor aConstActor; + + try + { + cameraType = aConstActor.GetType(); + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera", TEST_LOCATION ); + } + + DALI_TEST_EQUALS( (int)cameraType, (int)Dali::Camera::FREE_LOOK, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorSetFieldOfViewP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Set Field of view (P)" ); + + CameraActor defaultCamera = CameraActor::New( Size( TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT ) ); + const float defaultFieldOfView = defaultCamera.GetFieldOfView(); + + CameraActor actor = CameraActor::New(); + DALI_TEST_EQUALS( actor.GetFieldOfView(), defaultFieldOfView, TEST_LOCATION ); + + float fieldOfView = Math::PI / 3.0f; + actor.SetFieldOfView( fieldOfView ); + DALI_TEST_EQUALS( actor.GetFieldOfView(), fieldOfView, TEST_LOCATION ); + + float value; + actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value ); + DALI_TEST_EQUALS( fieldOfView, value, FLOAT_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorSetFieldOfViewN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Set Field of view (N)" ); + + CameraActor defaultCamera = CameraActor::New( Size( TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT ) ); + const float defaultFieldOfView = defaultCamera.GetFieldOfView(); + + CameraActor actor = CameraActor::New(); + DALI_TEST_EQUALS( actor.GetFieldOfView(), defaultFieldOfView, TEST_LOCATION ); + + float fieldOfView = Math::PI / 3.0f; + actor.SetFieldOfView( fieldOfView ); + DALI_TEST_EQUALS( actor.GetFieldOfView(), fieldOfView, TEST_LOCATION ); + + float value; + actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value ); + DALI_TEST_EQUALS( fieldOfView, value, FLOAT_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorGetFieldOfViewP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Get Field of view (P)" ); + const Vector2 size( TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT ); + + CameraActor defaultCamera = CameraActor::New( size ); + + const float cameraZ = 2.0f * std::max( size.width, size.height ); + const float expectedFieldOfView = 2.0f * std::atan( size.height * 0.5f / cameraZ ); + + CameraActor actor = CameraActor::New(); + DALI_TEST_EQUALS( actor.GetFieldOfView(), expectedFieldOfView, TEST_LOCATION ); + + float value; + actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value ); + DALI_TEST_EQUALS( expectedFieldOfView, value, FLOAT_EPSILON, TEST_LOCATION); + END_TEST; +} + +int UtcDaliCameraActorGetFieldOfViewN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Get Field of view (N)" ); + + CameraActor defaultCamera = CameraActor::New(); + + bool asserted = true; + try + { + defaultCamera.GetFieldOfView(); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +//todor +int UtcDaliCameraActorSetAspectRatioP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Set Aspect Ratio (P)" ); + + CameraActor actor = CameraActor::New(); + DALI_TEST_EQUALS( actor.GetAspectRatio(), static_cast( TestApplication::DEFAULT_SURFACE_WIDTH ) / static_cast( TestApplication::DEFAULT_SURFACE_HEIGHT ), TEST_LOCATION ); + + // Set an initial value to confirm a further set changes it. + float aspect = 4.0f / 3.0f; + actor.SetAspectRatio( aspect ); + DALI_TEST_EQUALS( actor.GetAspectRatio(), aspect, TEST_LOCATION ); + + aspect = 16.0f / 9.0f; + actor.SetAspectRatio( aspect ); + DALI_TEST_EQUALS( actor.GetAspectRatio(), aspect, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliCameraActorSetAspectRatioN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Set Aspect Ratio (N)" ); + + CameraActor actor; + + bool asserted = true; + try + { + actor.SetAspectRatio( 16.0f / 9.0f ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliCameraActorGetAspectRatioP(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CameraActor Get Aspect Ratio"); + + CameraActor actor = CameraActor::New(); + float defaultAspect = static_cast( TestApplication::DEFAULT_SURFACE_WIDTH ) / static_cast( TestApplication::DEFAULT_SURFACE_HEIGHT ); + + DALI_TEST_EQUALS( actor.GetAspectRatio(), defaultAspect, TEST_LOCATION ); + + float value = 0.0f; + actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( value ); + DALI_TEST_EQUALS( defaultAspect, value, FLOAT_EPSILON, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliCameraActorGetAspectRatioN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Get Aspect Ratio (N)" ); + + CameraActor actor; + + bool asserted = true; + try + { + actor.GetAspectRatio(); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliCameraActorSetNearClippingPlaneP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Set Near clipping plane (P)" ); + + CameraActor actor = CameraActor::New(); + + // Set a value so we are not relying on a particular default for this test case. + actor.SetNearClippingPlane( 200.0f ); + DALI_TEST_EQUALS( actor.GetNearClippingPlane(), 200.0f, TEST_LOCATION ); + + actor.SetNearClippingPlane( 400.0f ); + DALI_TEST_EQUALS( actor.GetNearClippingPlane(), 400.0f, TEST_LOCATION ); + + // Check setting the property. + actor.SetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE, Property::Value( 300.0f ) ); + DALI_TEST_EQUALS( actor.GetNearClippingPlane(), 300.0f, FLOAT_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorSetNearClippingPlaneN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Set Near clipping plane (N)" ); + + CameraActor actor; + + bool asserted = true; + try + { + actor.SetNearClippingPlane( 200.0f ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliCameraActorGetNearClippingPlaneP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Get Near clipping plane (P)" ); + + // Check the default value. + CameraActor actor = CameraActor::New(); + float defaultValue = 800.0f; + DALI_TEST_EQUALS( actor.GetNearClippingPlane(), defaultValue, TEST_LOCATION ); + + // Check getting the property. + float value; + actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( defaultValue, value, FLOAT_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorGetNearClippingPlaneN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Get Near clipping plane (N)" ); + + CameraActor actor; + bool asserted = true; + try + { + actor.GetNearClippingPlane(); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliCameraActorSetFarClippingPlaneP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Set Far clipping plane (P)" ); + + CameraActor actor = CameraActor::New(); + + // Set a value so we are not relying on a particular default for this test case. + actor.SetFarClippingPlane( 2000.0f ); + DALI_TEST_EQUALS( actor.GetFarClippingPlane(), 2000.0f, TEST_LOCATION ); + + actor.SetFarClippingPlane( 4000.0f ); + DALI_TEST_EQUALS( actor.GetFarClippingPlane(), 4000.0f, TEST_LOCATION ); + + // Check setting the property. + actor.SetProperty( CameraActor::Property::FAR_PLANE_DISTANCE, 2000.0f ); + DALI_TEST_EQUALS( actor.GetFarClippingPlane(), 2000.0f, FLOAT_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorSetFarClippingPlaneN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Set Far clipping plane (N)" ); + + CameraActor actor; + + bool asserted = true; + try + { + actor.SetFarClippingPlane( 2000.0f ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliCameraActorGetFarClippingPlaneP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Get Far clipping plane (P)" ); + + CameraActor actor = CameraActor::New(); + float defaultValue = 800.0f + ( 0xFFFF >> 4 ); + DALI_TEST_EQUALS( actor.GetFarClippingPlane(), defaultValue, TEST_LOCATION ); + + // Check getting the property. + float value; + actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( defaultValue, value, FLOAT_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorGetFarClippingPlaneN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Get Far clipping plane (N)" ); + + CameraActor actor; + + bool asserted = true; + try + { + actor.GetFarClippingPlane(); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliCameraActorSetTargetPositionP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Set Target Position (P)" ); + + CameraActor actor = CameraActor::New(); + + Vector3 target1( 10.0f, 20.0f, 30.0f ); + Vector3 target2( 15.0f, 25.0f, 35.0f ); + + // Set a value so we are not relying on a particular default for this test case. + actor.SetTargetPosition( target1 ); + DALI_TEST_EQUALS( actor.GetTargetPosition(), target1, TEST_LOCATION ); + + actor.SetTargetPosition( target2 ); + DALI_TEST_EQUALS( actor.GetTargetPosition(), target2, TEST_LOCATION ); + + // Check setting the property. + actor.SetProperty( CameraActor::Property::TARGET_POSITION, target1 ); + DALI_TEST_EQUALS( actor.GetTargetPosition(), target1, FLOAT_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorSetTargetPositionN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Set Target Position (N)" ); + + CameraActor actor; + + bool asserted = true; + try + { + actor.SetTargetPosition( Vector3( 10.0f, 20.0f, 30.0f ) ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliCameraActorGetTargetPositionP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Get Target Position (P)" ); + + CameraActor actor = CameraActor::New(); + Vector3 defaultValue( Vector3::ZERO ); + DALI_TEST_EQUALS( actor.GetTargetPosition(), defaultValue, TEST_LOCATION ); + + // Check getting the property. + Vector3 value; + actor.GetProperty( CameraActor::Property::TARGET_POSITION ).Get( value ); + DALI_TEST_EQUALS( defaultValue, value, FLOAT_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorGetTargetPositionN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Get Target Position (N)" ); + + CameraActor actor; + + bool asserted = true; + try + { + actor.GetTargetPosition(); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliCameraActorSetInvertYAxisP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Set InvertYAxis (P)" ); + + CameraActor actor = CameraActor::New(); + + // Set a value so we are not relying on a particular default for this test case. + actor.SetInvertYAxis( false ); + DALI_TEST_EQUALS( actor.GetInvertYAxis(), false, TEST_LOCATION ); + + actor.SetInvertYAxis( true ); + DALI_TEST_EQUALS( actor.GetInvertYAxis(), true, TEST_LOCATION ); + + actor.SetProperty( CameraActor::Property::INVERT_Y_AXIS, false ); + DALI_TEST_EQUALS( actor.GetInvertYAxis(), false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorSetInvertYAxisN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Set InvertYAxis (N)" ); + + CameraActor actor; + + bool asserted = true; + try + { + actor.SetInvertYAxis( false ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + END_TEST; +} + +int UtcDaliCameraActorGetInvertYAxisP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Get InvertYAxis (P)" ); + + // Check the default value. + CameraActor actor = CameraActor::New(); + DALI_TEST_EQUALS( actor.GetInvertYAxis(), false, TEST_LOCATION ); + + // Check getting the property. + bool bValue; + actor.GetProperty( CameraActor::Property::INVERT_Y_AXIS ).Get( bValue ); + DALI_TEST_EQUALS( false, bValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorGetInvertYAxisN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Get InvertYAxis (N)" ); + + CameraActor actor; + + bool asserted = true; + try + { + actor.GetInvertYAxis(); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + END_TEST; +} + +int UtcDaliCameraActorSetPerspectiveProjectionP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::SetPerspectiveProjection (P)" ); + + CameraActor actor = CameraActor::New(); + actor.SetPerspectiveProjection( Size( 100.f, 150.f ) ); + + DALI_TEST_CHECK( actor ); + + float value; + actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( value ); + DALI_TEST_EQUALS( 0.666666f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value ); + DALI_TEST_EQUALS( 0.489957f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( 150.f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( 4245.f, value, FLOAT_EPSILON, TEST_LOCATION ); + + DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::PERSPECTIVE_PROJECTION, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliCameraActorSetPerspectiveProjectionN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::SetPerspectiveProjection (N)" ); + + Stage stage = Stage::GetCurrent(); + Vector2 stageSize = stage.GetSize(); + + CameraActor actor = CameraActor::New(); + + // Check that setting perspective projection without a size (using zero size) uses the stages size. + actor.SetPerspectiveProjection( Size::ZERO ); + + float nearClippingPlane = std::max( stageSize.width, stageSize.height ); + float farClippingPlane = nearClippingPlane + static_cast( 0xFFFF >> 4 ); + + DALI_TEST_EQUALS( nearClippingPlane, actor.GetNearClippingPlane(), FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( farClippingPlane, actor.GetFarClippingPlane(), FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetProjectionMode(), (int)Dali::Camera::PERSPECTIVE_PROJECTION, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliCameraActorSetOrthographicProjectionP1(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::SetOrthographicProjection (P,1)" ); + + CameraActor actor = CameraActor::New( Size( 1080.0f, 1920.0f ) ); + DALI_TEST_CHECK( actor ); + + Stage::GetCurrent().Add( actor ); + + actor.SetOrthographicProjection( Size( 1080.0f, 1920.0f ) ); + application.SendNotification(); + application.Render( 0 ); + application.Render(); + application.SendNotification(); + + float defaultAspectRatio; + float defaultFieldOfView; + float defaultNearPlaneDistance; + float defaultFarPlaneDistance; + actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( defaultAspectRatio ); + actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( defaultFieldOfView ); + actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( defaultNearPlaneDistance ); + actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( defaultFarPlaneDistance ); + Vector3 defaultPos = actor.GetCurrentPosition(); + + actor.SetOrthographicProjection( Size( 1080.0f, 1920.0f ) ); + + application.SendNotification(); + application.Render( 0 ); + application.Render(); + application.SendNotification(); + + float value; + actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( value ); + DALI_TEST_EQUALS( defaultAspectRatio, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value ); + DALI_TEST_EQUALS( defaultFieldOfView, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( defaultNearPlaneDistance, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( defaultFarPlaneDistance, value, FLOAT_EPSILON, TEST_LOCATION ); + + actor.GetProperty( CameraActor::Property::LEFT_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( -540.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::RIGHT_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( 540.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::TOP_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( 960.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::BOTTOM_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( -960.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + + Vector3 pos = actor.GetCurrentPosition(); + DALI_TEST_EQUALS( defaultPos.z, pos.z, 0.001f, TEST_LOCATION ); + + DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::ORTHOGRAPHIC_PROJECTION, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorSetOrthographicProjectionN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::SetOrthographicProjection (N)" ); + + CameraActor actor; + bool asserted = true; + try + { + actor.GetProjectionMode(); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + END_TEST; +} + +int UtcDaliCameraActorSetOrthographicProjectionP2(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::SetOrthographicProjection (P,2)" ); + + CameraActor actor = CameraActor::New(); + DALI_TEST_CHECK( actor ); + + float defaultAspectRatio; + float defaultFieldOfView; + float defaultNearPlaneDistance; + float defaultFarPlaneDistance; + actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( defaultAspectRatio ); + actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( defaultFieldOfView ); + actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( defaultNearPlaneDistance ); + actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( defaultFarPlaneDistance ); + + // Check setting with specific near and far plane distances. + actor.SetOrthographicProjection( -100.0f, 200.0f, -300.0f, 500.0f, 400.0f, 4000.0f ); + + float value; + actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( value ); + DALI_TEST_EQUALS( defaultAspectRatio, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value ); + DALI_TEST_EQUALS( defaultFieldOfView, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( 400.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( 4000.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + + actor.GetProperty( CameraActor::Property::LEFT_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( -100.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::RIGHT_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( 200.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::TOP_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( -300.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::BOTTOM_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( 500.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + + DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::ORTHOGRAPHIC_PROJECTION, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliCameraActorSetOrthographicProjectionP3(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::SetOrthographicProjection (P,3)" ); + + CameraActor actor = CameraActor::New(); + DALI_TEST_CHECK( actor ); + + float defaultAspectRatio; + float defaultFieldOfView; + float defaultNearPlaneDistance; + float defaultFarPlaneDistance; + actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( defaultAspectRatio ); + actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( defaultFieldOfView ); + actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( defaultNearPlaneDistance ); + actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( defaultFarPlaneDistance ); + + actor.SetProjectionMode( Dali::Camera::ORTHOGRAPHIC_PROJECTION ); + + actor.SetProperty( CameraActor::Property::LEFT_PLANE_DISTANCE, -100.0f ); + actor.SetProperty( CameraActor::Property::RIGHT_PLANE_DISTANCE, 200.0f ); + actor.SetProperty( CameraActor::Property::TOP_PLANE_DISTANCE, -300.0f ); + actor.SetProperty( CameraActor::Property::BOTTOM_PLANE_DISTANCE, 500.0f ); + actor.SetNearClippingPlane( 400.0f ); + actor.SetFarClippingPlane( 4000.0f ); + + float value; + actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( value ); + DALI_TEST_EQUALS( defaultAspectRatio, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value ); + DALI_TEST_EQUALS( defaultFieldOfView, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( 400.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( 4000.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + + actor.GetProperty( CameraActor::Property::LEFT_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( -100.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::RIGHT_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( 200.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::TOP_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( -300.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::BOTTOM_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( 500.0f, value, FLOAT_EPSILON, TEST_LOCATION ); + + DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::ORTHOGRAPHIC_PROJECTION, TEST_LOCATION ); + std::string stringValue; + actor.GetProperty( CameraActor::Property::PROJECTION_MODE ).Get( stringValue ); + DALI_TEST_EQUALS( stringValue, "ORTHOGRAPHIC_PROJECTION", TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorSetProjectionModeP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::SetProjectionModeP (P)" ); + + CameraActor actor = CameraActor::New(); + + // Check that changing the projection mode alone does not alter other presets. + actor.SetNearClippingPlane( 200.0f ); + actor.SetFarClippingPlane( 400.0f ); + + actor.SetProjectionMode( Dali::Camera::PERSPECTIVE_PROJECTION ); + + DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::PERSPECTIVE_PROJECTION, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetNearClippingPlane(), 200.0f, FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetFarClippingPlane(), 400.0f, FLOAT_EPSILON, TEST_LOCATION ); + + actor.SetProjectionMode( Dali::Camera::ORTHOGRAPHIC_PROJECTION ); + + DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::ORTHOGRAPHIC_PROJECTION, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetNearClippingPlane(), 200.0f, FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( actor.GetFarClippingPlane(), 400.0f, FLOAT_EPSILON, TEST_LOCATION ); + + // Check setting the property. + Property::Value setValue = "PERSPECTIVE_PROJECTION"; + actor.SetProperty( CameraActor::Property::PROJECTION_MODE, setValue ); + DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::PERSPECTIVE_PROJECTION, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorSetProjectionModeN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::SetProjectionModeP (N)" ); + + CameraActor actor; + + bool asserted = true; + try + { + actor.SetProjectionMode( Dali::Camera::PERSPECTIVE_PROJECTION ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + END_TEST; +} + +int UtcDaliCameraActorGetProjectionModeP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::GetPerspectiveProjection (P)" ); + + CameraActor actor = CameraActor::New(); + + actor.SetOrthographicProjection( Size::ONE ); + DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::ORTHOGRAPHIC_PROJECTION, TEST_LOCATION ); + + actor.SetPerspectiveProjection( Size( 100.f, 150.f ) ); + DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::PERSPECTIVE_PROJECTION, TEST_LOCATION ); + + // Check getting the property. + std::string stringValue; + actor.GetProperty( CameraActor::Property::PROJECTION_MODE ).Get( stringValue ); + DALI_TEST_EQUALS( stringValue, "PERSPECTIVE_PROJECTION", TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorGetProjectionModeN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::GetProjectionMode (N)" ); + + CameraActor actor; + + bool asserted = true; + try + { + actor.GetProjectionMode(); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + END_TEST; +} + +int UtcDaliCameraActorSetCameraOffStage(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::SetCamera()" ); + + CameraActor actor = CameraActor::New(); + + actor.SetType( Camera::FREE_LOOK ); + actor.SetFieldOfView( TEST_FIELD_OF_VIEW ); + actor.SetAspectRatio( TEST_ASPECT_RATIO ); + actor.SetNearClippingPlane( TEST_NEAR_PLANE_DISTANCE ); + actor.SetFarClippingPlane( TEST_FAR_PLANE_DISTANCE ); + actor.SetProjectionMode( Camera::PERSPECTIVE_PROJECTION ); + + actor.SetInvertYAxis( false ); + + DALI_TEST_EQUALS( TEST_ASPECT_RATIO, actor.GetAspectRatio(), FLOAT_EPSILON, TEST_LOCATION );//change to machine epsilon + DALI_TEST_EQUALS( TEST_FIELD_OF_VIEW, actor.GetFieldOfView(), FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( TEST_NEAR_PLANE_DISTANCE, actor.GetNearClippingPlane(), FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( TEST_FAR_PLANE_DISTANCE, actor.GetFarClippingPlane(), FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( Camera::PERSPECTIVE_PROJECTION, actor.GetProjectionMode(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, actor.GetInvertYAxis(), TEST_LOCATION ); + + float value; + std::string sValue; + actor.GetProperty( CameraActor::Property::ASPECT_RATIO).Get( value ); + DALI_TEST_EQUALS( TEST_ASPECT_RATIO, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW).Get( value ); + DALI_TEST_EQUALS( TEST_FIELD_OF_VIEW, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE).Get( value ); + DALI_TEST_EQUALS( TEST_NEAR_PLANE_DISTANCE, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE).Get( value ); + DALI_TEST_EQUALS( TEST_FAR_PLANE_DISTANCE, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::PROJECTION_MODE).Get( sValue ); + DALI_TEST_EQUALS( "PERSPECTIVE_PROJECTION", sValue, TEST_LOCATION ); + bool bValue; + actor.GetProperty( CameraActor::Property::INVERT_Y_AXIS).Get( bValue ); + DALI_TEST_EQUALS( false, bValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorSetCameraOnStage(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::SetCamera()" ); + + CameraActor actor = CameraActor::New(); + Stage::GetCurrent().Add( actor ); + application.Render( 0 ); + application.SendNotification(); + + actor.SetType( Camera::LOOK_AT_TARGET ); + actor.SetFieldOfView( TEST_FIELD_OF_VIEW ); + actor.SetAspectRatio( TEST_ASPECT_RATIO ); + actor.SetNearClippingPlane( TEST_NEAR_PLANE_DISTANCE ); + actor.SetFarClippingPlane( TEST_FAR_PLANE_DISTANCE ); + actor.SetInvertYAxis( false ); + + DALI_TEST_EQUALS( false, actor.GetInvertYAxis(), TEST_LOCATION ); + + // Will need 2 frames to ensure both buffers are set to same values: + application.Render(); + application.SendNotification(); + application.Render(); + application.SendNotification(); + + DALI_TEST_EQUALS( TEST_ASPECT_RATIO, actor.GetAspectRatio(), FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( TEST_FIELD_OF_VIEW, actor.GetFieldOfView(), FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( TEST_NEAR_PLANE_DISTANCE, actor.GetNearClippingPlane(), FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( TEST_FAR_PLANE_DISTANCE, actor.GetFarClippingPlane(), FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( false, actor.GetInvertYAxis(), TEST_LOCATION ); + + std::string sValue; + actor.GetProperty( CameraActor::Property::TYPE ).Get( sValue ); + DALI_TEST_EQUALS( sValue, "LOOK_AT_TARGET", TEST_LOCATION ); + + float value; + actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( value ); + DALI_TEST_EQUALS( TEST_ASPECT_RATIO, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value ); + DALI_TEST_EQUALS( TEST_FIELD_OF_VIEW, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( value ); + DALI_TEST_EQUALS( TEST_NEAR_PLANE_DISTANCE, value, FLOAT_EPSILON, TEST_LOCATION ); + actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( value); + DALI_TEST_EQUALS( TEST_FAR_PLANE_DISTANCE, value, FLOAT_EPSILON, TEST_LOCATION ); + + bool bValue; + actor.GetProperty( CameraActor::Property::INVERT_Y_AXIS ).Get( bValue ); + DALI_TEST_EQUALS( false, bValue, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorGetCamera(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::GetCamera()" ); + + CameraActor actor = CameraActor::New(); + + actor.SetAspectRatio( TEST_ASPECT_RATIO ); + + DALI_TEST_EQUALS( actor.GetAspectRatio(), TEST_ASPECT_RATIO, FLOAT_EPSILON, TEST_LOCATION ); + + actor.SetProperty( CameraActor::Property::TYPE, "FREE_LOOK" ); + actor.SetProperty( CameraActor::Property::ASPECT_RATIO, TEST_ASPECT_RATIO ); + actor.SetProperty( CameraActor::Property::FIELD_OF_VIEW, TEST_FIELD_OF_VIEW ); + actor.SetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE, TEST_NEAR_PLANE_DISTANCE ); + actor.SetProperty( CameraActor::Property::FAR_PLANE_DISTANCE, TEST_FAR_PLANE_DISTANCE ); + + DALI_TEST_EQUALS( Camera::FREE_LOOK, actor.GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS( TEST_ASPECT_RATIO, actor.GetAspectRatio(), FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( TEST_FIELD_OF_VIEW, actor.GetFieldOfView(), FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( TEST_NEAR_PLANE_DISTANCE, actor.GetNearClippingPlane(), FLOAT_EPSILON, TEST_LOCATION ); + DALI_TEST_EQUALS( TEST_FAR_PLANE_DISTANCE, actor.GetFarClippingPlane(), FLOAT_EPSILON, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorDefaultProperties(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor DefaultProperties" ); + + CameraActor actor = CameraActor::New(); + + actor.SetAspectRatio( TEST_ASPECT_RATIO ); + Stage::GetCurrent().Add( actor ); + application.Render( 0 ); + application.SendNotification(); + bool bValue; + actor.GetProperty( CameraActor::Property::INVERT_Y_AXIS ).Get( bValue ); + DALI_TEST_EQUALS( false, bValue, TEST_LOCATION ); + + std::vector indices ; + indices.push_back( CameraActor::Property::TYPE ); + indices.push_back( CameraActor::Property::PROJECTION_MODE ); + indices.push_back( CameraActor::Property::FIELD_OF_VIEW ); + indices.push_back( CameraActor::Property::ASPECT_RATIO ); + indices.push_back( CameraActor::Property::NEAR_PLANE_DISTANCE ); + indices.push_back( CameraActor::Property::FAR_PLANE_DISTANCE ); + indices.push_back( CameraActor::Property::LEFT_PLANE_DISTANCE ); + indices.push_back( CameraActor::Property::RIGHT_PLANE_DISTANCE ); + indices.push_back( CameraActor::Property::TOP_PLANE_DISTANCE ); + indices.push_back( CameraActor::Property::BOTTOM_PLANE_DISTANCE ); + indices.push_back( CameraActor::Property::TARGET_POSITION ); + indices.push_back( CameraActor::Property::PROJECTION_MATRIX ); + indices.push_back( CameraActor::Property::VIEW_MATRIX ); + indices.push_back( CameraActor::Property::INVERT_Y_AXIS ); + + DALI_TEST_CHECK( actor.GetPropertyCount() == ( Actor::New().GetPropertyCount() + indices.size() ) ); + + for( std::vector::iterator iter = indices.begin(); iter != indices.end(); ++iter ) + { + DALI_TEST_EQUALS( *iter, actor.GetPropertyIndex( actor.GetPropertyName( *iter ) ), TEST_LOCATION); + DALI_TEST_CHECK( !actor.IsPropertyAnimatable( *iter ) ); + + if ( ( *iter == CameraActor::Property::PROJECTION_MATRIX ) || + ( *iter == CameraActor::Property::VIEW_MATRIX ) ) + { + DALI_TEST_CHECK( !actor.IsPropertyWritable( *iter ) ); + } + else + { + DALI_TEST_CHECK( actor.IsPropertyWritable( *iter ) ); + } + + DALI_TEST_CHECK( actor.GetPropertyType( *iter ) == actor.GetPropertyType( *iter ) ); // just checking call succeeds + } + + // Set/Get one of them. + const float newAspect = TEST_ASPECT_RATIO * 2.0f; + + actor.SetProperty( CameraActor::Property::ASPECT_RATIO, Property::Value( newAspect ) ); + application.Render(); + application.SendNotification(); + application.Render(); + application.SendNotification(); + + DALI_TEST_EQUALS( actor.GetAspectRatio(), newAspect, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorModelView(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor Test view application" ); + + BufferImage image = CreateBufferImage(); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetPosition( 20.0f, 30.0f, 40.0f ); + actor.SetParentOrigin( ParentOrigin::CENTER ); + Stage::GetCurrent().Add( actor ); + + application.SendNotification(); + application.Render( 0 ); + application.Render(); + application.SendNotification(); + + Matrix resultMatrix( true ); + resultMatrix.SetTransformComponents( Vector3::ONE, Quaternion::IDENTITY, actor.GetCurrentPosition() ); + + RenderTask task = Stage::GetCurrent().GetRenderTaskList().GetTask( 0 ); + CameraActor cameraActor = task.GetCameraActor(); + + Matrix viewMatrix( false ); + cameraActor.GetProperty( CameraActor::Property::VIEW_MATRIX ).Get( viewMatrix ); + Matrix::Multiply( resultMatrix, resultMatrix, viewMatrix ); + + DALI_TEST_CHECK( application.GetGlAbstraction().CheckUniformValue( "uModelView", resultMatrix ) ); + END_TEST; +} + +int UtcDaliCameraActorReadProjectionMatrix(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::CameraActor::ReadProjectionMatrix()" ); + + CameraActor camera = Stage::GetCurrent().GetRenderTaskList().GetTask( 0u ).GetCameraActor(); + application.SendNotification(); + application.Render( 0 ); + application.Render(); + application.SendNotification(); + Image image = CreateBufferImage(); + ImageActor imageActor = ImageActor::New( image ); + imageActor.SetSize( 100.0f, 100.0f ); + Stage::GetCurrent().Add( imageActor ); + + Matrix projectionMatrix; + Matrix viewMatrix; + + camera.GetProperty( CameraActor::CameraActor::Property::PROJECTION_MATRIX ).Get( projectionMatrix ); + camera.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( viewMatrix ); + + ShaderEffect shaderEffect = ShaderEffect::New( RENDER_SHADOW_VERTEX_SOURCE, RENDER_SHADOW_FRAGMENT_SOURCE ); + imageActor.SetShaderEffect( shaderEffect ); + + shaderEffect.SetUniform( SHADER_LIGHT_CAMERA_PROJECTION_MATRIX_PROPERTY_NAME, Matrix::IDENTITY ); + shaderEffect.SetUniform( SHADER_LIGHT_CAMERA_VIEW_MATRIX_PROPERTY_NAME, Matrix::IDENTITY ); + + Property::Index projectionMatrixPropertyIndex = shaderEffect.GetPropertyIndex( SHADER_LIGHT_CAMERA_PROJECTION_MATRIX_PROPERTY_NAME ); + Property::Index viewMatrixPropertyIndex = shaderEffect.GetPropertyIndex( SHADER_LIGHT_CAMERA_VIEW_MATRIX_PROPERTY_NAME ); + + Constraint projectionMatrixConstraint = Constraint::New( shaderEffect, projectionMatrixPropertyIndex, EqualToConstraint() ); + projectionMatrixConstraint.AddSource( Source( camera, CameraActor::Property::PROJECTION_MATRIX ) ); + Constraint viewMatrixConstraint = Constraint::New( shaderEffect, viewMatrixPropertyIndex, EqualToConstraint() ); + viewMatrixConstraint.AddSource( Source( camera, CameraActor::Property::VIEW_MATRIX ) ); + + projectionMatrixConstraint.Apply(); + viewMatrixConstraint.Apply(); + + application.SendNotification(); + application.Render(); + + // Test effects of Constraint. + DALI_TEST_CHECK( application.GetGlAbstraction().CheckUniformValue( SHADER_LIGHT_CAMERA_PROJECTION_MATRIX_PROPERTY_NAME.c_str(), projectionMatrix) ); + + DALI_TEST_CHECK( application.GetGlAbstraction().CheckUniformValue( SHADER_LIGHT_CAMERA_VIEW_MATRIX_PROPERTY_NAME.c_str(), viewMatrix ) ); + END_TEST; +} + +int UtcDaliCameraActorAnimatedProperties(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::Internal::CameraActor::GetSceneObjectAnimatableProperty()" ); + + CameraActor camera = Stage::GetCurrent().GetRenderTaskList().GetTask( 0u ).GetCameraActor(); + Actor actor = Actor::New(); + actor.SetSize( 100.0f, 100.0f ); + Stage::GetCurrent().Add( actor ); + + Constraint constraint = Constraint::New( actor, Actor::Property::POSITION, EqualToConstraint() ); + constraint.AddSource( Source( camera, Actor::Property::POSITION ) ); + constraint.Apply(); + + camera.SetPosition( 100.0f, 200.0f, 300.0f ); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3( 100.0f, 200.0f, 300.0f ), TEST_LOCATION); + END_TEST; +} + +int UtcDaliCameraActorPropertyIndices(void) +{ + TestApplication application; + CameraActor camera = Stage::GetCurrent().GetRenderTaskList().GetTask( 0u ).GetCameraActor(); + + Actor basicActor = Actor::New(); + Property::IndexContainer indices; + camera.GetPropertyIndices( indices ); + DALI_TEST_CHECK( indices.Size() > basicActor.GetPropertyCount() ); + DALI_TEST_EQUALS( indices.Size(), camera.GetPropertyCount(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCameraActorCheckLookAtAndFreeLookViews01(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + Vector2 stageSize = stage.GetSize(); + + CameraActor freeLookCameraActor = CameraActor::New( stageSize ); + freeLookCameraActor.SetParentOrigin( ParentOrigin::CENTER ); + freeLookCameraActor.SetType( Camera::FREE_LOOK ); + + Vector3 targetPosition( 30.0f, 240.0f, -256.0f ); + Actor target = Actor::New(); + target.SetParentOrigin( ParentOrigin::CENTER ); + target.SetPosition( targetPosition ); + + Constraint cameraOrientationConstraint = Constraint::New ( freeLookCameraActor, Actor::Property::ORIENTATION, &LookAt ); + cameraOrientationConstraint.AddSource( Source( target, Actor::Property::WORLD_POSITION ) ); + cameraOrientationConstraint.AddSource( Source( freeLookCameraActor, Actor::Property::WORLD_POSITION ) ); + cameraOrientationConstraint.AddSource( Source( target, Actor::Property::WORLD_ORIENTATION ) ); + cameraOrientationConstraint.Apply(); + + CameraActor lookAtCameraActor = CameraActor::New( stageSize ); + lookAtCameraActor.SetType( Camera::LOOK_AT_TARGET ); + lookAtCameraActor.SetTargetPosition( targetPosition ); + lookAtCameraActor.SetParentOrigin( ParentOrigin::CENTER ); + + stage.Add( target ); + stage.Add( freeLookCameraActor ); + stage.Add( lookAtCameraActor ); + + // Create an arbitrary vector + for( float x=-1.0f; x<=1.0f; x+=0.1f ) + { + for( float y=-1.0f; y<1.0f; y+=0.1f ) + { + for( float z=-1.0f; z<1.0f; z+=0.1f ) + { + Vector3 position( x, y, z ); + position.Normalize(); + position *= 200.0f; + + freeLookCameraActor.SetPosition( position ); + lookAtCameraActor.SetPosition( position ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + Matrix freeLookViewMatrix; + Matrix lookAtViewMatrix; + freeLookCameraActor.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( freeLookViewMatrix ); + lookAtCameraActor.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( lookAtViewMatrix ); + + DALI_TEST_EQUALS( freeLookViewMatrix, lookAtViewMatrix, 0.01, TEST_LOCATION ); + } + } + } + END_TEST; +} + +int UtcDaliCameraActorCheckLookAtAndFreeLookViews02(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + Vector2 stageSize = stage.GetSize(); + + CameraActor freeLookCameraActor = CameraActor::New( stageSize ); + freeLookCameraActor.SetParentOrigin( ParentOrigin::CENTER ); + freeLookCameraActor.SetType( Camera::FREE_LOOK ); + + Vector3 targetPosition( 30.0f, 240.0f, -256.0f ); + Actor target = Actor::New(); + target.SetParentOrigin( ParentOrigin::CENTER ); + target.SetPosition( targetPosition ); + + Constraint cameraOrientationConstraint = Constraint::New ( freeLookCameraActor, Actor::Property::ORIENTATION, &LookAt ); + cameraOrientationConstraint.AddSource( Source( target, Actor::Property::WORLD_POSITION ) ); + cameraOrientationConstraint.AddSource( Source( freeLookCameraActor, Actor::Property::WORLD_POSITION ) ); + cameraOrientationConstraint.AddSource( Source( target, Actor::Property::WORLD_ORIENTATION ) ); + cameraOrientationConstraint.Apply(); + + CameraActor lookAtCameraActor = CameraActor::New( stageSize ); + lookAtCameraActor.SetType( Camera::LOOK_AT_TARGET ); + lookAtCameraActor.SetTargetPosition( targetPosition ); + lookAtCameraActor.SetParentOrigin( ParentOrigin::CENTER ); + + stage.Add( target ); + stage.Add( freeLookCameraActor ); + stage.Add( lookAtCameraActor ); + + // Create an arbitrary vector + for( float x=-1.0f; x<=1.0f; x+=0.1f ) + { + for( float y=-1.0f; y<1.0f; y+=0.1f ) + { + for( float z=-1.0f; z<1.0f; z+=0.1f ) + { + Vector3 position( x, y, z ); + position.Normalize(); + position *= 200.0f; + + freeLookCameraActor.SetPosition( position ); + lookAtCameraActor.SetPosition( position ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + Matrix freeLookViewMatrix; + Matrix lookAtViewMatrix; + freeLookCameraActor.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( freeLookViewMatrix ); + lookAtCameraActor.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( lookAtViewMatrix ); + + Matrix freeLookWorld = freeLookCameraActor.GetCurrentWorldMatrix(); + + Matrix freeLookTest( false ); + Matrix::Multiply( freeLookTest, freeLookViewMatrix, freeLookWorld ); + DALI_TEST_EQUALS( freeLookTest, Matrix::IDENTITY, 0.01f, TEST_LOCATION ); + + DALI_TEST_EQUALS( freeLookViewMatrix, lookAtViewMatrix, 0.01, TEST_LOCATION ); + } + } + } + END_TEST; +} + +int UtcDaliCameraActorCheckLookAtAndFreeLookViews03(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + Vector2 stageSize = stage.GetSize(); + + Vector3 targetPosition( Vector3::ZERO ); + Vector3 cameraOffset( 0.0f, 0.0f, 100.0f ); + + CameraActor freeLookCameraActor = CameraActor::New( stageSize ); + freeLookCameraActor.SetType( Camera::FREE_LOOK ); + freeLookCameraActor.SetParentOrigin( ParentOrigin::CENTER ); + + Quaternion cameraOrientation( Radian( Degree( 180.0f ) ), Vector3::YAXIS ); + freeLookCameraActor.SetPosition( cameraOffset ); + freeLookCameraActor.SetOrientation( cameraOrientation ); + + Actor cameraAnchor = Actor::New(); + cameraAnchor.Add( freeLookCameraActor ); + stage.Add( cameraAnchor ); + + for( float angle = 1.0f; angle <= 180.0f; angle += 1.0f ) + { + Quaternion rotation( Radian( Degree( angle ) ), Vector3::YAXIS ); + + freeLookCameraActor.SetPosition( rotation.Rotate( cameraOffset ) ); + cameraAnchor.SetOrientation( rotation ); + + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + Matrix freeLookViewMatrix; + freeLookCameraActor.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( freeLookViewMatrix ); + + Matrix freeLookWorld = freeLookCameraActor.GetCurrentWorldMatrix(); + + Matrix freeLookTest( false ); + Matrix::Multiply( freeLookTest, freeLookViewMatrix, freeLookWorld ); + DALI_TEST_EQUALS( freeLookTest, Matrix::IDENTITY, 0.01f, TEST_LOCATION ); + } + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-ConnectionTracker.cpp b/automated-tests/src/dali/utc-Dali-ConnectionTracker.cpp new file mode 100644 index 0000000..a246746 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-ConnectionTracker.cpp @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include + + +using namespace Dali; + +void utc_dali_conenction_tracker_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_conenction_tracker_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace { + + +} // anon namespace + + +/******************************************* + * + * Start of Utc test cases. + * Test cases performed in order of API listed in dali-signal.h + * UtcDaliSignal + FunctionName + P=positive test, N = Negative test + * + */ + +int UtcConnectionTrackerConstructorP(void) +{ + TestApplication app; // Create core for debug logging + + ConnectionTracker tracker; + + DALI_TEST_CHECK( tracker.GetConnectionCount() == 0 ); + + END_TEST; +} + +int UtcConnectionTrackerDestructorP(void) +{ + TestApplication app; // Create core for debug logging + // make sure the ConnectionTracker disconnects form a signal when it + // gets deleted. + TestButton* button = new TestButton(1); + { + TestApp testApp; + button->DownSignal().Connect(&testApp,&TestApp::OnButtonPress); + DALI_TEST_CHECK( testApp.GetConnectionCount() == 1 ); + DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( )== 1 ); + } + // testApp out of scope it should have been disconnected + DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 0 ); + + END_TEST; +} + +int UtcConnectionTrackerDisconnectAllP(void) +{ + TestApplication app; // Create core for debug logging + + TestButton* button = new TestButton(1); + TestApp testApp; + button->DownSignal().Connect(&testApp,&TestApp::OnButtonPress); + + DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 1 ); + + testApp.DisconnectAll(); + + DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 0 ); + + END_TEST; +} + +int UtcConnectionTrackerDisconnectAllN(void) +{ + TestApplication app; // Create core for debug logging + TestApp testApp; + TestButton* button = new TestButton(1); + + DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 0 ); + testApp.DisconnectAll(); + DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 0 ); + + END_TEST; +} + +int UtcConnectionTrackerSignalConnectedP(void) +{ + TestApplication app; // Create core for debug logging + + TestButton* button = new TestButton(1); + TestApp testApp; + button->DownSignal().Connect(&testApp,&TestApp::OnButtonPress); + + DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 1 ); + + END_TEST; + +} +int UtcConnectionTrackerSignalConnectedN(void) +{ + TestApplication app; // Create core for debug logging + + TestButton* button = new TestButton(1); + TestApp* testApp( NULL ); + + try + { + // connect to a null connection tracker + button->DownSignal().Connect( testApp, &TestApp::OnButtonPress); + } + catch (Dali::DaliException& e) + { + // Tests that a negative test of an assertion succeeds + DALI_TEST_PRINT_ASSERT( e ); + tet_result(TET_PASS); + } + + END_TEST; +} + + +int UtcConnectionTrackerSignalDisconnectP(void) +{ + TestApplication app; // Create core for debug logging + + TestButton* button = new TestButton(1); + TestApp testApp; + button->DownSignal().Connect(&testApp,&TestApp::OnButtonPress); + + DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 1 ); + + button->DownSignal().Disconnect(&testApp,&TestApp::OnButtonPress); + DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 0 ); + + END_TEST; + +} + + +int UtcConnectionTrackerSignalDisconnectN(void) +{ + TestApplication app; // Create core for debug logging + + TestButton* button = new TestButton(1); + TestApp testApp; + button->DownSignal().Connect(&testApp,&TestApp::OnButtonPress); + + DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 1 ); + + try + { + app.SignalDisconnected( NULL, NULL ); + tet_result( TET_FAIL ); + } + catch (Dali::DaliException& e) + { + tet_result( TET_PASS ); + } + + END_TEST; + +} + + +int UtcConnectionTrackerGetConnectionCountP(void) +{ + TestApplication app; // Create core for debug logging + + TestButton* button = new TestButton(1); + TestApp testApp; + button->DownSignal().Connect(&testApp,&TestApp::OnButtonPress); + DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 1 ); + END_TEST; +} + +int UtcConnectionTrackerGetConnectionCountN(void) +{ + TestApplication app; // Create core for debug logging + + TestButton* button = new TestButton(1); + DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 0 ); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Constrainer.cpp b/automated-tests/src/dali/utc-Dali-Constrainer.cpp new file mode 100644 index 0000000..3398341 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Constrainer.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include + +using namespace Dali; +using namespace Dali::Internal; + +namespace +{ +static void SetupLinearConstrainerUniformProgress( Dali::LinearConstrainer& linearConstrainer) +{ + Dali::Property::Array points; + points.Resize(3); + points[0] = 0.0f; + points[1] = 1.0f; + points[2] = 0.0f; + linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::VALUE, points ); +} + +static void SetupLinearConstrainerNonUniformProgress( Dali::LinearConstrainer& linearConstrainer) +{ + Dali::Property::Array points; + points.Resize(3); + points[0] = 0.0f; + points[1] = 1.0f; + points[2] = 0.0f; + linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::VALUE, points ); + + points[0] = 0.0f; + points[1] = 0.25f; + points[2] = 1.0f; + linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::PROGRESS, points ); +} + +} // anonymous namespace + +int UtcLinearConstrainerApply(void) +{ + TestApplication application; + + Dali::Actor actor = Dali::Actor::New(); + + // Register a float property + Property::Index index = actor.RegisterProperty( "t", 0.0f ); + + Dali::Stage::GetCurrent().Add(actor); + + + //Create a LinearConstrainer without specifying progress for values + Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New(); + SetupLinearConstrainerUniformProgress( linearConstrainer ); + + //Apply the linear constraint to the actor's position. The source property for the constraint will be the custom property "t" + Vector2 range( 0.0f, 1.0f ); + linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range ); + + //Create an animation to animate the custom property + float durationSeconds(1.0f); + Dali::Animation animation = Dali::Animation::New(durationSeconds); + animation.AnimateTo(Dali::Property(actor,index),1.0f); + animation.Play(); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 100% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* beyond the animation duration*/); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION ); + + //Setup a LinearConstrainer specifying the progress for each value + linearConstrainer.Remove(actor); + SetupLinearConstrainerNonUniformProgress( linearConstrainer ); + linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range ); + + actor.SetProperty(index,0.0f); + animation.Play(); + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 25% progress */); + + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 50% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 2.0f/3.0f, Math::MACHINE_EPSILON_1, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 75% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f/3.0f, Math::MACHINE_EPSILON_1, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* 100% progress */); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION ); + + application.SendNotification(); + application.Render(static_cast(durationSeconds*250.0f)/* beyond the animation duration*/); + DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION ); + + END_TEST; +} + diff --git a/automated-tests/src/dali/utc-Dali-Constraint.cpp b/automated-tests/src/dali/utc-Dali-Constraint.cpp new file mode 100644 index 0000000..84af54d --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Constraint.cpp @@ -0,0 +1,1206 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +/////////////////////////////////////////////////////////////////////////////// +void utc_dali_constraint_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_constraint_cleanup(void) +{ + test_return_value = TET_PASS; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +namespace +{ + +/** + * A function to use for a constraint, no data collected. + */ +template< typename T > +void BasicFunction( T& /* current */, const PropertyInputContainer& /* inputs */ ) +{ +} + +/** + * A functor which sets a given boolean when the functor is called. + */ +template< typename T > +struct BasicCalledFunctor +{ + BasicCalledFunctor( bool& functorCalled ) : mCalled( functorCalled ) { } + + void operator()( T& /* current */, const PropertyInputContainer& /* inputs */ ) + { + mCalled = true; + } + + bool& mCalled; +}; + +/** + * A functor which increments a given integer when the functor is called. + */ +template< typename T > +struct CalledCountFunctor +{ + CalledCountFunctor( int& callCount ) : mCallCount( callCount ) { } + + void operator()( T& /* current */, const PropertyInputContainer& /* inputs */ ) + { + ++mCallCount; + } + + int& mCallCount; +}; + +/** + * A functor which sets the given value as the value required when the functor is called. + */ +template< typename T > +struct SetValueFunctor +{ + SetValueFunctor( const T& value ) : mValue( value ) { } + + void operator()( T& current, const PropertyInputContainer& /* inputs */ ) + { + current = mValue; + } + + T mValue; +}; + +} // unnamed namespace +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::New( +// Handle, +// Property::Index, +// void( *function )( T&, const PropertyInputContainer& ) ) +/////////////////////////////////////////////////////////////////////////////// +namespace UtcDaliConstraintNewFunction +{ +bool gConstraintFunctionCalled = false; +void ConstraintFunction( Vector3& /* current */, const PropertyInputContainer& /* inputs */ ) +{ + gConstraintFunctionCalled = true; +} +} // namespace UtcDaliConstraintNewFunction + +int UtcDaliConstraintNewFunctionP(void) +{ + // Ensure that we can create a constraint using a C function and that it is called. + + TestApplication application; + UtcDaliConstraintNewFunction::gConstraintFunctionCalled = false; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( UtcDaliConstraintNewFunction::gConstraintFunctionCalled, false, TEST_LOCATION ); + + // Add a constraint + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &UtcDaliConstraintNewFunction::ConstraintFunction ); + DALI_TEST_CHECK( constraint ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( UtcDaliConstraintNewFunction::gConstraintFunctionCalled, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintNewFunctionN(void) +{ + // Create a constraint with an uninitialised handle + + TestApplication application; + + // Add a constraint with an uninitialised handle + try + { + Constraint constraint = Constraint::New< Vector3 >( Actor(), Actor::Property::POSITION, &UtcDaliConstraintNewFunction::ConstraintFunction ); + DALI_TEST_CHECK( false ); // Should not reach here + } + catch ( ... ) + { + DALI_TEST_CHECK( true ); // Should assert! + } + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::New( +// Handle, +// Property::Index, +// const T& object ) +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintNewFunctorP(void) +{ + // Ensure that we can create a constraint using a functor and that it is called. + + TestApplication application; + bool functorCalled = false; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION ); + + // Add a constraint + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, BasicCalledFunctor< Vector3 >( functorCalled ) ); + DALI_TEST_CHECK( constraint ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintNewFunctorN(void) +{ + // Create a constraint with an uninitialised handle + + TestApplication application; + bool functorCalled = false; + + // Add a constraint with an uninitialised handle + try + { + Constraint constraint = Constraint::New< Vector3 >( Actor(), Actor::Property::POSITION, BasicCalledFunctor< Vector3 >( functorCalled ) ); + DALI_TEST_CHECK( false ); // Should not reach here + } + catch ( ... ) + { + DALI_TEST_CHECK( true ); // Should assert! + } + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::New( +// Handle, +// Property::Index, +// const T& object, +// void ( T::*memberFunction ) ( P&, const PropertyInputContainer& ) ) +/////////////////////////////////////////////////////////////////////////////// +namespace UtcDaliConstraintNewFunctorMember +{ +struct Functor +{ + Functor( bool& positionCalled, bool& scaleCalled ) + : mPositionCalled( positionCalled ), + mScaleCalled( scaleCalled ) + { + } + + void Position( Vector3& /* current */, const PropertyInputContainer& /* inputs */ ) + { + mPositionCalled = true; + } + + void Scale( Vector3& /* current */, const PropertyInputContainer& /* inputs */ ) + { + mScaleCalled = true; + } + + bool& mPositionCalled; + bool& mScaleCalled; +}; +} // namespace UtcDaliConstraintNewFunctorMember + +int UtcDaliConstraintNewFunctorMemberP(void) +{ + // Ensure that we can create a constraint using a functor and that it is called. + + TestApplication application; + bool positionFunctorCalled = false; + bool sizeFunctorCalled = false; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( positionFunctorCalled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( sizeFunctorCalled, false, TEST_LOCATION ); + + // Add a constraint that calls Functor::Position + Constraint constraint = Constraint::New< Vector3 >( + actor, + Actor::Property::POSITION, + UtcDaliConstraintNewFunctorMember::Functor( positionFunctorCalled, sizeFunctorCalled ), + &UtcDaliConstraintNewFunctorMember::Functor::Position ); + DALI_TEST_CHECK( constraint ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( positionFunctorCalled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( sizeFunctorCalled, false, TEST_LOCATION ); + + // Add another constraint that calls Functor::Size + Constraint constraint2 = Constraint::New< Vector3 >( + actor, + Actor::Property::SCALE, + UtcDaliConstraintNewFunctorMember::Functor( positionFunctorCalled, sizeFunctorCalled ), + &UtcDaliConstraintNewFunctorMember::Functor::Scale ); + DALI_TEST_CHECK( constraint2 ); + constraint2.Apply(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( positionFunctorCalled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( sizeFunctorCalled, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintNewFunctorMemberN(void) +{ + // Create a constraint with an uninitialised handle + + TestApplication application; + bool positionFunctorCalled = false; + bool sizeFunctorCalled = false; + + // Add a constraint with an uninitialised handle + try + { + Constraint constraint = Constraint::New< Vector3 >( + Actor(), + Actor::Property::POSITION, + UtcDaliConstraintNewFunctorMember::Functor( positionFunctorCalled, sizeFunctorCalled ), + &UtcDaliConstraintNewFunctorMember::Functor::Position ); + DALI_TEST_CHECK( false ); // Should not reach here + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_CHECK( true ); // Should assert! + } + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::Clone +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintCloneP(void) +{ + // Ensure we can clone for another actor and it's called appropriately + + TestApplication application; + int calledCount = 0; + + Actor actor = Actor::New(); + Actor clone = Actor::New(); + + Stage stage = Stage::GetCurrent(); + stage.Add( actor ); + stage.Add( clone ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( calledCount, 0, TEST_LOCATION ); + + // Add a constraint to actor + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, CalledCountFunctor< Vector3 >( calledCount ) ); + DALI_TEST_CHECK( constraint ); + constraint.Apply(); + + // Create a clone but don't apply + Constraint constraintClone = constraint.Clone( clone ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( calledCount, 1, TEST_LOCATION ); + + // Reset + calledCount = 0; + + // Ensure constraint isn't called again if scene doesn't change + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( calledCount, 0, TEST_LOCATION ); + + // Apply the clone constraint + constraintClone.Apply(); + + application.SendNotification(); + application.Render(); + + // Should only be called once for the new constraint clone ONLY + DALI_TEST_EQUALS( calledCount, 1, TEST_LOCATION ); + + // Reset + calledCount = 0; + + // Change the position of both actors + actor.SetPosition( 100.0f, 100.0f ); + clone.SetPosition( 100.0f, 100.0f ); + + application.SendNotification(); + application.Render(); + + // Functor should have been called twice + DALI_TEST_EQUALS( calledCount, 2, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintCloneN(void) +{ + // Attempt to clone an uninitialised constraint should cause an assert + + TestApplication application; + + Constraint constraint; + + try + { + Actor actor = Actor::New(); + Constraint clone = constraint.Clone( actor ); + DALI_TEST_CHECK( false ); + } + catch ( ... ) + { + DALI_TEST_CHECK( true ); + } + + END_TEST; +} + +namespace UtcDaliConstraintClone +{ +void Function( Vector3& /* current */, const PropertyInputContainer& inputs ) +{ + DALI_TEST_EQUALS( inputs[0]->GetType(), Property::VECTOR3, TEST_LOCATION ); + DALI_TEST_EQUALS( inputs[1]->GetType(), Property::ROTATION, TEST_LOCATION ); + DALI_TEST_EQUALS( inputs[2]->GetType(), Property::VECTOR4, TEST_LOCATION ); + DALI_TEST_EQUALS( inputs[3]->GetType(), Property::BOOLEAN, TEST_LOCATION ); +} +} // namespace UtcDaliConstraintClone + +int UtcDaliConstraintCloneCheckSourcesAndSetters(void) +{ + // Ensure all sources, the tag and remove-action are cloned appropriately + + TestApplication application; + + Actor actor = Actor::New(); + Actor clone = Actor::New(); + + Stage stage = Stage::GetCurrent(); + stage.Add( actor ); + stage.Add( clone ); + + application.SendNotification(); + application.Render(); + + // Create a constraint, DON'T Apply it though + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &UtcDaliConstraintClone::Function ); + constraint.AddSource( LocalSource( Actor::Property::SIZE ) ); + constraint.AddSource( LocalSource( Actor::Property::ORIENTATION ) ); + constraint.AddSource( LocalSource( Actor::Property::COLOR ) ); + constraint.AddSource( LocalSource( Actor::Property::VISIBLE ) ); + constraint.SetRemoveAction( Constraint::Discard ); + constraint.SetTag( 123 ); + + // Clone the constraint & apply the clone + Constraint constraintClone = constraint.Clone( clone ); + constraintClone.Apply(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( constraint.GetRemoveAction(), constraintClone.GetRemoveAction(), TEST_LOCATION ); + DALI_TEST_EQUALS( constraint.GetTag(), constraintClone.GetTag(), TEST_LOCATION ); + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::Constraint( const Constraint& ) +// Constraint::operator= +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintCopyAndAssignment(void) +{ + // Ensure copy constructor & assignment operators work + + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &BasicFunction< Vector3 > ); + Constraint copied( constraint ); + Constraint assigned; + DALI_TEST_CHECK( constraint == copied ); + DALI_TEST_CHECK( copied != assigned ); + + assigned = constraint; + DALI_TEST_CHECK( constraint == assigned ); + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::DownCast +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintDownCast(void) +{ + // Ensure DownCast works as expected + + TestApplication application; + + Actor actor = Actor::New(); + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &BasicFunction< Vector3 > ); + + // Another BaseHandle type + Constraint downCast = Constraint::DownCast( actor ); + DALI_TEST_CHECK( ! downCast ); + + // A constraint + downCast = Constraint::DownCast( constraint ); + DALI_TEST_CHECK( downCast ); + + // An empty constraint + downCast = Constraint::DownCast( Constraint() ); + DALI_TEST_CHECK( ! downCast ); + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::GetTargetObject +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintGetTargetObjectP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &BasicFunction< Vector3 > ); + DALI_TEST_CHECK( constraint.GetTargetObject() == actor ); + + Actor actor2 = Actor::New(); + DALI_TEST_CHECK( constraint.GetTargetObject() != actor2 ); + + END_TEST; +} + +int UtcDaliConstraintGetTargetObjectN(void) +{ + // Attempt to retrieve from uninitialised constraint + + TestApplication application; + + Constraint constraint; + try + { + Handle handle = constraint.GetTargetObject(); + DALI_TEST_CHECK( false ); // Should not reach here! + } + catch( ... ) + { + DALI_TEST_CHECK( true ); + } + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::GetTargetProperty +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintGetTargetPropertyP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &BasicFunction< Vector3 > ); + DALI_TEST_EQUALS( constraint.GetTargetProperty(), Actor::Property::POSITION, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintGetTargetPropertyN(void) +{ + // Attempt to retrieve from uninitialised constraint + + TestApplication application; + + Constraint constraint; + try + { + Property::Index propertyIndex = constraint.GetTargetProperty(); + ( void )propertyIndex; + DALI_TEST_CHECK( false ); // Should not reach here! + } + catch( ... ) + { + DALI_TEST_CHECK( true ); + } + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::SetTag +// Constraint::GetTag +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintTagP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &BasicFunction< Vector3 > ); + DALI_TEST_EQUALS( constraint.GetTag(), 0u, TEST_LOCATION ); + + const unsigned int tag = 123; + constraint.SetTag( tag ); + DALI_TEST_EQUALS( constraint.GetTag(), tag, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintSetTagN(void) +{ + // Attempt to set from uninitialised constraint + + TestApplication application; + + Constraint constraint; + try + { + constraint.SetTag( 123 ); + DALI_TEST_CHECK( false ); // Should not reach here! + } + catch( ... ) + { + DALI_TEST_CHECK( true ); + } + + END_TEST; +} + +int UtcDaliConstraintGetTagN(void) +{ + // Attempt to retrieve from uninitialised constraint + + TestApplication application; + + Constraint constraint; + try + { + int tag = constraint.GetTag(); + ( void )tag; + DALI_TEST_CHECK( false ); // Should not reach here! + } + catch( ... ) + { + DALI_TEST_CHECK( true ); + } + + END_TEST; +} + +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::SetRemoveAction +// Constraint::GetRemoveAction +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintRemoveActionP(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &BasicFunction< Vector3 > ); + DALI_TEST_EQUALS( constraint.GetRemoveAction(), Constraint::DEFAULT_REMOVE_ACTION, TEST_LOCATION ); + + constraint.SetRemoveAction( Constraint::Discard ); + DALI_TEST_EQUALS( constraint.GetRemoveAction(), Constraint::Discard, TEST_LOCATION ); + + constraint.SetRemoveAction( Constraint::Bake ); + DALI_TEST_EQUALS( constraint.GetRemoveAction(), Constraint::Bake, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintSetRemoveActionN(void) +{ + // Attempt to set from uninitialised constraint + + TestApplication application; + + Constraint constraint; + try + { + constraint.SetRemoveAction( Constraint::Discard ); + DALI_TEST_CHECK( false ); // Should not reach here! + } + catch( ... ) + { + DALI_TEST_CHECK( true ); + } + + END_TEST; +} + +int UtcDaliConstraintGetRemoveActionN(void) +{ + // Attempt to retrieve from uninitialised constraint + + TestApplication application; + + Constraint constraint; + try + { + Constraint::RemoveAction removeAction = constraint.GetRemoveAction(); + ( void )removeAction; + DALI_TEST_CHECK( false ); // Should not reach here! + } + catch( ... ) + { + DALI_TEST_CHECK( true ); + } + + END_TEST; +} + +int UtcDaliConstraintBakeRemoveAction(void) +{ + // Ensure value is baked when constraint is removed + + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + application.SendNotification(); + application.Render(); + + // Should not equal position by default + Vector3 position( 10.0f, 20.0f, 30.0f ); + DALI_TEST_CHECK( actor.GetCurrentPosition() != position ); + + // Create a constraint that constrains to position + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, SetValueFunctor< Vector3 >( position ) ); + constraint.SetRemoveAction( Constraint::Bake ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + // Remove the constraint, it should still be at position + constraint.Remove(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintDiscardRemoveAction(void) +{ + // Ensure value is baked when constraint is removed + + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + application.SendNotification(); + application.Render(); + + // Get and store current position + Vector3 originalPosition = actor.GetCurrentPosition(); + + // Should not equal position by default + Vector3 position( 10.0f, 20.0f, 30.0f ); + DALI_TEST_CHECK( actor.GetCurrentPosition() != position ); + + // Create a constraint that constrains to position + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, SetValueFunctor< Vector3 >( position ) ); + constraint.SetRemoveAction( Constraint::Discard ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION ); + + // Remove the constraint, it should still be at position + constraint.Remove(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( actor.GetCurrentPosition(), originalPosition, TEST_LOCATION ); + DALI_TEST_CHECK( actor.GetCurrentPosition() != position ); + + END_TEST; +} + +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::Apply +// Constraint::Remove +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintApplyRemove(void) +{ + // Ensure constraint functors are called appropriately + + TestApplication application; + bool functorCalled = false; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION ); + + // Create a constraint and apply, functor should be called + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, BasicCalledFunctor< Vector3 >( functorCalled ) ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION ); + + // Reset + functorCalled = false; + + // Remove the constraint, functor should not be called + constraint.Remove(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION ); + + // Re-apply the constraint, functor should be called again + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintApplyBeforeAddedToStage(void) +{ + // Constraint gets applied to an off-stage actor. + // Constraint should be automatically applied when the actor is added to the stage and not before + + TestApplication application; + bool functorCalled = false; + + // Create an actor and a constraint and apply, DON'T add to stage just yet + Actor actor = Actor::New(); + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, BasicCalledFunctor< Vector3 >( functorCalled ) ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + // Should NOT be called + DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION ); + + // Add actor to stage + Stage::GetCurrent().Add( actor ); + + application.SendNotification(); + application.Render(); + + // Should now be called + DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintApplyAndRemoveBeforeAddedToStage(void) +{ + // Constraint gets applied to an off-stage actor, then gets removed before it's added to the stage + // Constraint should NOT be called at all + + TestApplication application; + bool functorCalled = false; + + // Create an actor and a constraint and apply, DON'T add to stage just yet + Actor actor = Actor::New(); + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, BasicCalledFunctor< Vector3 >( functorCalled ) ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + // Should NOT be called + DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION ); + + // Remove the constraint + constraint.Remove(); + + // Add actor to stage + Stage::GetCurrent().Add( actor ); + + application.SendNotification(); + application.Render(); + + // Still should NOT be called + DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintApplyActorStagedUnstaged(void) +{ + // Apply a constraint to an actor which is staged and unstaged. + // Functor should only be called while the actor is staged. + + TestApplication application; + bool functorCalled = false; + + // Create an actor and add to stage + Actor actor = Actor::New(); + Stage stage = Stage::GetCurrent(); + stage.Add( actor ); + + // Create a constraint and apply + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, BasicCalledFunctor< Vector3 >( functorCalled ) ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + // Constraint should be called + DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION ); + + // Reset + functorCalled = false; + + // Remove actor from stage + stage.Remove( actor ); + + application.SendNotification(); + application.Render(); + + // Constraint should NOT be called + DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION ); + + // Re-add to stage + stage.Add( actor ); + + application.SendNotification(); + application.Render(); + + // Constraint should be called + DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintApplySeveralTimes(void) +{ + // Apply the same constraint several times. + // Should not cause any problems (subsequent attempts should be no-ops) + + TestApplication application; + int count = 0; + + // Create an actor and add to stage + Actor actor = Actor::New(); + Stage stage = Stage::GetCurrent(); + stage.Add( actor ); + + // Create a constraint and apply + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, CalledCountFunctor< Vector3 >( count ) ); + constraint.Apply(); + + // Apply again + constraint.Apply(); // no-op + + application.SendNotification(); + application.Render(); + + // Should only have been called once + DALI_TEST_EQUALS( count, 1, TEST_LOCATION ); + + // Reset + count = 0; + + // Apply again + constraint.Apply(); // no-op + + application.SendNotification(); + application.Render(); + + // Constraint should not have been called as the input-properties (none) have not changed for the constraint + DALI_TEST_EQUALS( count, 0, TEST_LOCATION ); + + // Reset + count = 0; + + // Change the position property, apply again + actor.SetPosition( 10.0f, 10.0f ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + // Constraint should have been called once + DALI_TEST_EQUALS( count, 1, TEST_LOCATION ); + + END_TEST; +} + +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::AddSource +/////////////////////////////////////////////////////////////////////////////// +namespace UtcDaliConstraintAddSource +{ +void Function( Vector3& /* current */, const PropertyInputContainer& inputs ) +{ + DALI_TEST_EQUALS( inputs.Size(), 4u, TEST_LOCATION ); + DALI_TEST_EQUALS( inputs[0]->GetType(), Property::VECTOR3, TEST_LOCATION ); + DALI_TEST_EQUALS( inputs[1]->GetType(), Property::ROTATION, TEST_LOCATION ); + DALI_TEST_EQUALS( inputs[2]->GetType(), Property::VECTOR4, TEST_LOCATION ); + DALI_TEST_EQUALS( inputs[3]->GetType(), Property::BOOLEAN, TEST_LOCATION ); +} +} // namespace UtcDaliConstraintAddSource + +int UtcDaliConstraintAddSourceP(void) +{ + // Ensure all sources are in the correct order in the functor + + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + // Create a constraint, add sources + Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &UtcDaliConstraintAddSource::Function ); + constraint.AddSource( LocalSource( Actor::Property::SIZE ) ); + constraint.AddSource( LocalSource( Actor::Property::ORIENTATION ) ); + constraint.AddSource( LocalSource( Actor::Property::COLOR ) ); + constraint.AddSource( LocalSource( Actor::Property::VISIBLE ) ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + END_TEST; +} + +int UtcDaliConstraintAddSourceN(void) +{ + // Attempt to set from uninitialised constraint + + TestApplication application; + + Constraint constraint; + try + { + constraint.AddSource( LocalSource( Actor::Property::POSITION ) ); + DALI_TEST_CHECK( false ); // Should not reach here! + } + catch( ... ) + { + DALI_TEST_CHECK( true ); + } + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +namespace TestChaining +{ + +const Vector3 gFunction1Output( Vector3::ONE ); +void Function1( Vector3& current, const PropertyInputContainer& /* inputs */ ) +{ + // current is original position + DALI_TEST_EQUALS( current, Vector3::ZERO, TEST_LOCATION ); + current = gFunction1Output; +} + +const Vector3 gFunction2Output( 10.0f, 20.0f, 30.0f ); +void Function2( Vector3& current, const PropertyInputContainer& /* inputs */ ) +{ + // current is output from Function1 + DALI_TEST_EQUALS( current, gFunction1Output, TEST_LOCATION ); + + current = gFunction2Output; +} + +const Vector3 gFunction3Output( 10.0f, 20.0f, 30.0f ); +void Function3( Vector3& current, const PropertyInputContainer& /* inputs */ ) +{ + // current is output from Function2 + DALI_TEST_EQUALS( current, gFunction2Output, TEST_LOCATION ); + + current = gFunction3Output; +} + +const Vector3 gFunction4Output( 10.0f, 20.0f, 30.0f ); +void Function4( Vector3& current, const PropertyInputContainer& /* inputs */ ) +{ + // current is output from Function3 + DALI_TEST_EQUALS( current, gFunction3Output, TEST_LOCATION ); + + current = gFunction4Output; +} + +void Function5( Vector3& current, const PropertyInputContainer& /* inputs */ ) +{ + // current is output from Function4 + DALI_TEST_EQUALS( current, gFunction4Output, TEST_LOCATION ); + + current = Vector3::ZERO; +} + +} // namespace TestChaining + +int UtcDaliConstraintChaining(void) +{ + // Apply several constraints to the same property and ensure the functors are called in the correct order. + + TestApplication application; + + Actor actor = Actor::New(); + Stage::GetCurrent().Add( actor ); + + Constraint constraint1 = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &TestChaining::Function1 ); + Constraint constraint2 = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &TestChaining::Function2 ); + Constraint constraint3 = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &TestChaining::Function3 ); + Constraint constraint4 = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &TestChaining::Function4 ); + Constraint constraint5 = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &TestChaining::Function5 ); + + constraint1.Apply(); + constraint2.Apply(); + constraint3.Apply(); + constraint4.Apply(); + constraint5.Apply(); + + application.SendNotification(); + application.Render(); + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +namespace TestPropertyTypes +{ +template< typename T > +void Execute( T value ) +{ + TestApplication application; + bool functorCalled = false; + + Actor actor = Actor::New(); + Property::Index index = actor.RegisterProperty( "TEMP_PROPERTY_NAME", value ); + + Stage::GetCurrent().Add( actor ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION ); + + // Add a constraint + Constraint constraint = Constraint::New< T >( actor, index, BasicCalledFunctor< T >( functorCalled ) ); + DALI_TEST_CHECK( constraint ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION ); +} +} // namespace UtcDaliConstraintNewFunctor + +int UtcDaliConstraintTestPropertyTypesP(void) +{ + // Ensure we can use a constraint functor with all supported property types + + TestPropertyTypes::Execute< bool >( false ); + TestPropertyTypes::Execute< int >( 0 ); + TestPropertyTypes::Execute< float >( 0.0f ); + TestPropertyTypes::Execute< Vector2 >( Vector2::ZERO ); + TestPropertyTypes::Execute< Vector3 >( Vector3::ZERO ); + TestPropertyTypes::Execute< Vector4 >( Vector4::ZERO ); + TestPropertyTypes::Execute< Quaternion >( Quaternion::IDENTITY ); + TestPropertyTypes::Execute< Matrix >( Matrix::IDENTITY ); + TestPropertyTypes::Execute< Matrix3 >( Matrix3::IDENTITY ); + + END_TEST; +} + +/////////////////////////////////////////////////////////////////////////////// + diff --git a/automated-tests/src/dali/utc-Dali-ConstraintFunction.cpp b/automated-tests/src/dali/utc-Dali-ConstraintFunction.cpp new file mode 100644 index 0000000..d7ad79b --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-ConstraintFunction.cpp @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +/////////////////////////////////////////////////////////////////////////////// +void utc_dali_constraint_function_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_constraint_function_cleanup(void) +{ + test_return_value = TET_PASS; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +namespace +{ +bool gFunctionCalled = false; + +template< typename T > +void TestCallbackFunction( T& /* current*/ , const PropertyInputContainer& /* inputs */ ) +{ + gFunctionCalled = true; +} + +template< typename T > +struct TestCallbackFunctor +{ + TestCallbackFunctor( bool& functorCalled ) : mFunctorCalled( functorCalled ) { } + + void operator()( T& /* current*/ , const PropertyInputContainer& /* inputs */ ) + { + mFunctorCalled = true; + } + + bool& mFunctorCalled; +}; + +template< typename T > +struct TestFunctorMethod +{ + TestFunctorMethod( bool& functorCalled ) : mFunctorCalled( functorCalled ) { } + + void Method( T& /* current*/ , const PropertyInputContainer& /* inputs */ ) + { + mFunctorCalled = true; + } + + bool& mFunctorCalled; +}; + +} // unnamed namespace +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::Function::Function( void( *function )( P&, const PropertyInputContainer& ) ) +/////////////////////////////////////////////////////////////////////////////// +namespace +{ +template< typename T > +void TestFunctionConstructor() +{ + gFunctionCalled = false; + Constraint::Function< T > function( &TestCallbackFunction< T > ); + T current; + PropertyInputContainer inputs; + + DALI_TEST_EQUALS( gFunctionCalled, false, TEST_LOCATION ); + CallbackBase::Execute< T&, const PropertyInputContainer& >( function, current, inputs ); + DALI_TEST_EQUALS( gFunctionCalled, true, TEST_LOCATION ); +} +} // unnamed namespace + +int UtcDaliConstraintFunctionWithFunction(void) +{ + TestFunctionConstructor< bool >(); + TestFunctionConstructor< int >(); + TestFunctionConstructor< unsigned int >(); + TestFunctionConstructor< float >(); + TestFunctionConstructor< Vector2 >(); + TestFunctionConstructor< Vector3 >(); + TestFunctionConstructor< Vector4 >(); + TestFunctionConstructor< Quaternion >(); + TestFunctionConstructor< Matrix >(); + TestFunctionConstructor< Matrix3 >(); + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::Function::Function( const T& object ) +/////////////////////////////////////////////////////////////////////////////// +namespace +{ +template< typename T > +void TestFunctorConstructor() +{ + bool called = false; + TestCallbackFunctor< T > functor( called ); + Constraint::Function< T > callback( functor ); + T current; + PropertyInputContainer inputs; + + DALI_TEST_EQUALS( called, false, TEST_LOCATION ); + CallbackBase::Execute< T&, const PropertyInputContainer& >( callback, current, inputs ); + DALI_TEST_EQUALS( called, true, TEST_LOCATION ); +} +} // unnamed namespace + +int UtcDaliConstraintFunctionWithFunctor(void) +{ + TestFunctorConstructor< bool >(); + TestFunctorConstructor< int >(); + TestFunctorConstructor< unsigned int >(); + TestFunctorConstructor< float >(); + TestFunctorConstructor< Vector2 >(); + TestFunctorConstructor< Vector3 >(); + TestFunctorConstructor< Vector4 >(); + TestFunctorConstructor< Quaternion >(); + TestFunctorConstructor< Matrix >(); + TestFunctorConstructor< Matrix3 >(); + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::Function::Function( const T& object, void ( T::*memberFunction ) ( P&, const PropertyInputContainer& ) ) +/////////////////////////////////////////////////////////////////////////////// +namespace +{ +template< typename T > +void TestFunctorMethodConstructor() +{ + bool called = false; + TestFunctorMethod< T > functor( called ); + Constraint::Function< T > callback( functor, &TestFunctorMethod< T >::Method ); + T current; + PropertyInputContainer inputs; + + DALI_TEST_EQUALS( called, false, TEST_LOCATION ); + CallbackBase::Execute< T&, const PropertyInputContainer& >( callback, current, inputs ); + DALI_TEST_EQUALS( called, true, TEST_LOCATION ); +} +} // unnamed namespace + +int UtcDaliConstraintFunctionWithMethodFunctor(void) +{ + TestFunctorMethodConstructor< bool >(); + TestFunctorMethodConstructor< int >(); + TestFunctorMethodConstructor< unsigned int >(); + TestFunctorMethodConstructor< float >(); + TestFunctorMethodConstructor< Vector2 >(); + TestFunctorMethodConstructor< Vector3 >(); + TestFunctorMethodConstructor< Vector4 >(); + TestFunctorMethodConstructor< Quaternion >(); + TestFunctorMethodConstructor< Matrix >(); + TestFunctorMethodConstructor< Matrix3 >(); + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Constraint::Function::Clone +/////////////////////////////////////////////////////////////////////////////// +namespace +{ +template< typename T > +void TestFunctionClone() +{ + gFunctionCalled = false; + Constraint::Function< T > callback( &TestCallbackFunction< T > ); + CallbackBase* clone = callback.Clone(); + + T current; + PropertyInputContainer inputs; + + DALI_TEST_EQUALS( gFunctionCalled, false, TEST_LOCATION ); + CallbackBase::Execute< T&, const PropertyInputContainer& >( *clone, current, inputs ); + DALI_TEST_EQUALS( gFunctionCalled, true, TEST_LOCATION ); + delete clone; +} + +template< typename T > +void TestFunctorClone() +{ + bool called = false; + TestCallbackFunctor< T > functor( called ); + Constraint::Function< T > callback( functor ); + CallbackBase* clone = callback.Clone(); + + T current; + PropertyInputContainer inputs; + + DALI_TEST_EQUALS( called, false, TEST_LOCATION ); + CallbackBase::Execute< T&, const PropertyInputContainer& >( *clone, current, inputs ); + DALI_TEST_EQUALS( called, true, TEST_LOCATION ); + delete clone; +} + +template< typename T > +void TestMethodFunctorClone() +{ + bool called = false; + TestFunctorMethod< T > functor( called ); + Constraint::Function< T > callback( functor, &TestFunctorMethod< T >::Method ); + CallbackBase* clone = callback.Clone(); + + T current; + PropertyInputContainer inputs; + + DALI_TEST_EQUALS( called, false, TEST_LOCATION ); + CallbackBase::Execute< T&, const PropertyInputContainer& >( *clone, current, inputs ); + DALI_TEST_EQUALS( called, true, TEST_LOCATION ); + delete clone; +} + +} // unnamed namespace + +int UtcDaliConstraintFunctionFunctionClone(void) +{ + TestFunctionClone< bool >(); + TestFunctionClone< int >(); + TestFunctionClone< unsigned int >(); + TestFunctionClone< float >(); + TestFunctionClone< Vector2 >(); + TestFunctionClone< Vector3 >(); + TestFunctionClone< Vector4 >(); + TestFunctionClone< Quaternion >(); + TestFunctionClone< Matrix >(); + TestFunctionClone< Matrix3 >(); + END_TEST; +} + +int UtcDaliConstraintFunctionFunctorClone(void) +{ + TestFunctorClone< bool >(); + TestFunctorClone< int >(); + TestFunctorClone< unsigned int >(); + TestFunctorClone< float >(); + TestFunctorClone< Vector2 >(); + TestFunctorClone< Vector3 >(); + TestFunctorClone< Vector4 >(); + TestFunctorClone< Quaternion >(); + TestFunctorClone< Matrix >(); + TestFunctorClone< Matrix3 >(); + END_TEST; +} + +int UtcDaliConstraintFunctionMethodFunctorClone(void) +{ + TestMethodFunctorClone< bool >(); + TestMethodFunctorClone< int >(); + TestMethodFunctorClone< unsigned int >(); + TestMethodFunctorClone< float >(); + TestMethodFunctorClone< Vector2 >(); + TestMethodFunctorClone< Vector3 >(); + TestMethodFunctorClone< Vector4 >(); + TestMethodFunctorClone< Quaternion >(); + TestMethodFunctorClone< Matrix >(); + TestMethodFunctorClone< Matrix3 >(); + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +namespace +{ +struct CountFunctor +{ + CountFunctor( int& count ) + : mCount( count ) + { + ++mCount; + } + + CountFunctor( const CountFunctor& other ) + : mCount( other.mCount ) + { + ++mCount; + } + + CountFunctor& operator=( const CountFunctor& other ) + { + return *this; + } + + ~CountFunctor() + { + --mCount; + } + + void operator()( bool& /* current*/ , const PropertyInputContainer& /* inputs */ ) + { + } + + int& mCount; +}; +} // unnamed namespace + +int UtcDaliConstraintFunctionEnsureMemoryCleanup(void) +{ + // Functors are new'd in Constraint::Function, so check that all memory is released at the end + + int count = 0; + + { + CountFunctor functor( count ); + Constraint::Function< bool > callback1( functor ); + Constraint::Function< bool > callback2( functor ); + Constraint::Function< bool > callback3( functor ); + Constraint::Function< bool > callback4( functor ); + Constraint::Function< bool > callback5( functor ); + Constraint::Function< bool > callback6( functor ); + Constraint::Function< bool > callback7( functor ); + Constraint::Function< bool > callback8( functor ); + Constraint::Function< bool > callback9( functor ); + DALI_TEST_EQUALS( count, 10, TEST_LOCATION ); + } + + DALI_TEST_EQUALS( count, 0, TEST_LOCATION ); + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// diff --git a/automated-tests/src/dali/utc-Dali-ConstraintSource.cpp b/automated-tests/src/dali/utc-Dali-ConstraintSource.cpp new file mode 100644 index 0000000..7c69e21 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-ConstraintSource.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +/////////////////////////////////////////////////////////////////////////////// +void utc_dali_constraint_source_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_constraint_source_cleanup(void) +{ + test_return_value = TET_PASS; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// LocalSource +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliLocalSource(void) +{ + LocalSource source( Actor::Property::POSITION ); + + DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::POSITION, TEST_LOCATION ); + + END_TEST; +} + +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// ParentSource +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliParentSource(void) +{ + ParentSource source( Actor::Property::POSITION ); + + DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::POSITION, TEST_LOCATION ); + + END_TEST; +} + +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// Source +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliSource1(void) +{ + Actor actor; + Source source( actor, Actor::Property::SIZE ); + + DALI_TEST_CHECK( ! source.object ); + DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::SIZE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliSource2(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + Source source( actor, Actor::Property::SIZE ); + DALI_TEST_EQUALS( source.object, actor, TEST_LOCATION ); + DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::SIZE, TEST_LOCATION ); + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// ConstraintSource +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintSourceWithSource1(void) +{ + Actor actor; + + ConstraintSource source( Source( actor, Actor::Property::PARENT_ORIGIN ) ); + DALI_TEST_CHECK( ! source.object ); + DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::PARENT_ORIGIN, TEST_LOCATION ); + DALI_TEST_EQUALS( source.sourceType, OBJECT_PROPERTY, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintSourceWithSource2(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + ConstraintSource source( Source( actor, Actor::Property::PARENT_ORIGIN ) ); + DALI_TEST_EQUALS( source.object, actor, TEST_LOCATION ); + DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::PARENT_ORIGIN, TEST_LOCATION ); + DALI_TEST_EQUALS( source.sourceType, OBJECT_PROPERTY, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintSourceWithLocalSource(void) +{ + Actor actor; + + ConstraintSource source( LocalSource( Actor::Property::PARENT_ORIGIN ) ); + DALI_TEST_CHECK( ! source.object ); + DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::PARENT_ORIGIN, TEST_LOCATION ); + DALI_TEST_EQUALS( source.sourceType, LOCAL_PROPERTY, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintSourceWithParentSource(void) +{ + Actor actor; + + ConstraintSource source( ParentSource( Actor::Property::PARENT_ORIGIN ) ); + DALI_TEST_CHECK( ! source.object ); + DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::PARENT_ORIGIN, TEST_LOCATION ); + DALI_TEST_EQUALS( source.sourceType, PARENT_PROPERTY, TEST_LOCATION ); + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// diff --git a/automated-tests/src/dali/utc-Dali-Constraints.cpp b/automated-tests/src/dali/utc-Dali-Constraints.cpp new file mode 100644 index 0000000..06c8a2e --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Constraints.cpp @@ -0,0 +1,402 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +/////////////////////////////////////////////////////////////////////////////// +void utc_dali_constraints_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_constraints_cleanup(void) +{ + test_return_value = TET_PASS; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +namespace +{ + +struct PropertyInputImpl : public PropertyInput +{ +public: + + // Constants + static const bool BOOLEAN_VALUE; + static const float FLOAT_VALUE; + static const int INTEGER_VALUE; + static const Vector2 VECTOR2_VALUE; + static const Vector3 VECTOR3_VALUE; + static const Vector4 VECTOR4_VALUE; + static const Matrix3 MATRIX3_VALUE; + static const Matrix MATRIX_VALUE; + static const Quaternion QUATERNION_VALUE; + + // Construction & Destruction + PropertyInputImpl( Property::Type type ) : mType( type ) { } + virtual ~PropertyInputImpl() { } + + // Methods + Property::Type GetType() const { return mType; } + + // Virtual Methods + virtual const bool& GetBoolean() const { return BOOLEAN_VALUE; } + virtual const float& GetFloat() const { return FLOAT_VALUE; } + virtual const int& GetInteger() const { return INTEGER_VALUE; } + virtual const Vector2& GetVector2() const { return VECTOR2_VALUE; } + virtual const Vector3& GetVector3() const { return VECTOR3_VALUE; } + virtual const Vector4& GetVector4() const { return VECTOR4_VALUE; } + virtual const Matrix3& GetMatrix3() const { return MATRIX3_VALUE; } + virtual const Matrix& GetMatrix() const { return MATRIX_VALUE; } + virtual const Quaternion& GetQuaternion() const { return QUATERNION_VALUE; } + + // Data + Property::Type mType; +}; + +const bool PropertyInputImpl::BOOLEAN_VALUE = true; +const float PropertyInputImpl::FLOAT_VALUE = 123.0f; +const int PropertyInputImpl::INTEGER_VALUE = 456; +const Vector2 PropertyInputImpl::VECTOR2_VALUE = Vector2( 10.0f, 20.0f ); +const Vector3 PropertyInputImpl::VECTOR3_VALUE = Vector3( 30.0f, 40.0f, 50.0f ); +const Vector4 PropertyInputImpl::VECTOR4_VALUE = Vector4( 60.0f, 70.0f, 80.0f, 90.0f ); +const Matrix3 PropertyInputImpl::MATRIX3_VALUE ( 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f, + 7.0f, 8.0f, 9.0f ); +const Matrix PropertyInputImpl::MATRIX_VALUE = Matrix::IDENTITY; +const Quaternion PropertyInputImpl::QUATERNION_VALUE ( 1.0f, 2.0f, 3.0f, 4.0f ); + +struct Vector3PropertyInput : public PropertyInputImpl +{ +public: + + // Construction & Destruction + Vector3PropertyInput( Vector3& value ) + : PropertyInputImpl( Property::VECTOR3 ), + mValue( value ) + { + } + + ~Vector3PropertyInput() + { + } + + const Vector3& GetVector3() const + { + return mValue; + } + + // Data + Vector3& mValue; +}; + +struct QuaternionPropertyInput : public PropertyInputImpl +{ +public: + + // Construction & Destruction + QuaternionPropertyInput( Quaternion& value ) + : PropertyInputImpl( Property::ROTATION ), + mValue( value ) + { + } + + ~QuaternionPropertyInput() + { + } + + const Quaternion& GetQuaternion() const + { + return mValue; + } + + // Data + Quaternion& mValue; +}; + +} // unnamed namespace +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// EqualToConstraint +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintsEqualToConstraintFloat(void) +{ + PropertyInputContainer inputs; + PropertyInputImpl input( Property::FLOAT ); + inputs.PushBack( &input ); + + float value = 0.0f; + DALI_TEST_CHECK( value != PropertyInputImpl::FLOAT_VALUE ); + + EqualToConstraint constraint; + constraint( value, inputs ); + + DALI_TEST_EQUALS( value, PropertyInputImpl::FLOAT_VALUE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintsEqualToConstraintVector2(void) +{ + PropertyInputContainer inputs; + PropertyInputImpl input( Property::VECTOR2 ); + inputs.PushBack( &input ); + + Vector2 value; + DALI_TEST_CHECK( value != PropertyInputImpl::VECTOR2_VALUE ); + + EqualToConstraint constraint; + constraint( value, inputs ); + + DALI_TEST_EQUALS( value, PropertyInputImpl::VECTOR2_VALUE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintsEqualToConstraintVector3(void) +{ + PropertyInputContainer inputs; + PropertyInputImpl input( Property::VECTOR3 ); + inputs.PushBack( &input ); + + Vector3 value; + DALI_TEST_CHECK( value != PropertyInputImpl::VECTOR3_VALUE ); + + EqualToConstraint constraint; + constraint( value, inputs ); + + DALI_TEST_EQUALS( value, PropertyInputImpl::VECTOR3_VALUE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintsEqualToConstraintVector4(void) +{ + PropertyInputContainer inputs; + PropertyInputImpl input( Property::VECTOR4 ); + inputs.PushBack( &input ); + + Vector4 value; + DALI_TEST_CHECK( value != PropertyInputImpl::VECTOR4_VALUE ); + + EqualToConstraint constraint; + constraint( value, inputs ); + + DALI_TEST_EQUALS( value, PropertyInputImpl::VECTOR4_VALUE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintsEqualToConstraintQuaternion(void) +{ + PropertyInputContainer inputs; + PropertyInputImpl input( Property::ROTATION ); + inputs.PushBack( &input ); + + Quaternion value; + DALI_TEST_CHECK( value != PropertyInputImpl::QUATERNION_VALUE ); + + EqualToConstraint constraint; + constraint( value, inputs ); + + DALI_TEST_EQUALS( value, PropertyInputImpl::QUATERNION_VALUE, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintsEqualToConstraintMatrix3(void) +{ + PropertyInputContainer inputs; + PropertyInputImpl input( Property::MATRIX3 ); + inputs.PushBack( &input ); + + Matrix3 value; + DALI_TEST_CHECK( value != PropertyInputImpl::MATRIX3_VALUE ); + + EqualToConstraint constraint; + constraint( value, inputs ); + + DALI_TEST_EQUALS( value, PropertyInputImpl::MATRIX3_VALUE, 0.1f, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliConstraintsEqualToConstraintMatrix(void) +{ + PropertyInputContainer inputs; + PropertyInputImpl input( Property::MATRIX ); + inputs.PushBack( &input ); + + Matrix value; + DALI_TEST_CHECK( value != PropertyInputImpl::MATRIX_VALUE ); + + EqualToConstraint constraint; + constraint( value, inputs ); + + DALI_TEST_EQUALS( value, PropertyInputImpl::MATRIX_VALUE, TEST_LOCATION ); + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// RelativeToConstraint +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintsRelativeToConstraintUsingFloat(void) +{ + PropertyInputContainer inputs; + PropertyInputImpl input( Property::VECTOR3 ); + inputs.PushBack( &input ); + + Vector3 value; + DALI_TEST_EQUALS( value, Vector3::ZERO, TEST_LOCATION ); + + const float scale( 4.0f ); + RelativeToConstraint constraint( scale ); + constraint( value, inputs ); + + DALI_TEST_EQUALS( value, PropertyInputImpl::VECTOR3_VALUE * scale, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliConstraintsRelativeToConstraintUsingVector3(void) +{ + PropertyInputContainer inputs; + PropertyInputImpl input( Property::VECTOR3 ); + inputs.PushBack( &input ); + + Vector3 value; + DALI_TEST_EQUALS( value, Vector3::ZERO, TEST_LOCATION ); + + const Vector3 scale( 4.0f, 5.0f, 6.0f ); + RelativeToConstraint constraint( scale ); + constraint( value, inputs ); + + DALI_TEST_EQUALS( value, PropertyInputImpl::VECTOR3_VALUE * scale, TEST_LOCATION ); + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// RelativeToConstraintFloat +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintsRelativeToConstraintFloat(void) +{ + PropertyInputContainer inputs; + PropertyInputImpl input( Property::VECTOR3 ); + inputs.PushBack( &input ); + + const float scale( 4.0f ); + + float value = 0.0f; + DALI_TEST_CHECK( value != PropertyInputImpl::FLOAT_VALUE * scale ); + + RelativeToConstraintFloat constraint( scale ); + constraint( value, inputs ); + + DALI_TEST_EQUALS( value, PropertyInputImpl::FLOAT_VALUE * scale, TEST_LOCATION ); + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////// +// LookAt +/////////////////////////////////////////////////////////////////////////////// +int UtcDaliConstraintsLookAt(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_EQUALS( actor.GetCurrentWorldOrientation(), Quaternion::IDENTITY, TEST_LOCATION ); + + Vector3 targetPosition; + Vector3 cameraPosition; + Quaternion targetOrientation; + + Vector3PropertyInput targetPositionProperty( targetPosition ); + Vector3PropertyInput cameraPositionProperty( cameraPosition ); + QuaternionPropertyInput targetOrientationProperty( targetOrientation ); + + PropertyInputContainer inputs; + inputs.PushBack( &targetPositionProperty ); + inputs.PushBack( &cameraPositionProperty ); + inputs.PushBack( &targetOrientationProperty ); + + Quaternion current; + + // 180 degrees round y + targetPosition = Vector3::ZERO; + cameraPosition = Vector3( 0.0f, 0.0f, 1.0f ); + targetOrientation = Quaternion::IDENTITY; + Quaternion lookAtOrientation( Quaternion( Radian( Math::PI ), Vector3::YAXIS ) ); + LookAt( current, inputs ); + DALI_TEST_EQUALS( current, lookAtOrientation, TEST_LOCATION ); + + // 180 degrees round y * -45 degrees round x + targetPosition = Vector3::ZERO; + cameraPosition = Vector3( 0.0f, -1.0f, 1.0f ); + targetOrientation = Quaternion::IDENTITY; + lookAtOrientation = Quaternion( Radian( Math::PI ), Vector3::YAXIS ) * Quaternion( Radian( Math::PI * 0.25f ), -Vector3::XAXIS ); + LookAt( current, inputs ); + DALI_TEST_EQUALS( current, lookAtOrientation, Math::MACHINE_EPSILON_10, TEST_LOCATION ); + + // 180 degrees round y * -45 degrees round x at different points + targetPosition = Vector3( 0.0f, 1.0f, -1.0f ); + cameraPosition = Vector3::ZERO; + targetOrientation = Quaternion::IDENTITY; + lookAtOrientation = Quaternion( Radian( Math::PI ), Vector3::YAXIS ) * Quaternion( Radian( Math::PI * 0.25f ), -Vector3::XAXIS ); + LookAt( current, inputs ); + DALI_TEST_EQUALS( current, lookAtOrientation, Math::MACHINE_EPSILON_10, TEST_LOCATION ); + + // 225 degrees round y + targetPosition = Vector3( -1.0f, 0.0f, 0.0f ); + cameraPosition = Vector3( 0.0f, 0.0f, 1.0f ); + targetOrientation = Quaternion::IDENTITY; + lookAtOrientation = Quaternion( Radian( Math::PI * 1.25), Vector3::YAXIS ); + LookAt( current, inputs ); + DALI_TEST_EQUALS( current, lookAtOrientation, Math::MACHINE_EPSILON_10, TEST_LOCATION ); + + // 180 degrees round y * -45 degrees round x, Up Vector: 180 degrees + targetPosition = Vector3::ZERO; + cameraPosition = Vector3( 0.0f, -1.0f, 1.0f ); + targetOrientation = Quaternion( Radian( Math::PI ), Vector3::ZAXIS ); + lookAtOrientation = Quaternion( Radian( Math::PI ), Vector3::YAXIS ) * Quaternion( Radian( Math::PI * 0.25f ), -Vector3::XAXIS ) * Quaternion( Radian( Math::PI ), -Vector3::ZAXIS ); + LookAt( current, inputs ); + DALI_TEST_EQUALS( current, lookAtOrientation, Math::MACHINE_EPSILON_10, TEST_LOCATION ); + + END_TEST; +} +/////////////////////////////////////////////////////////////////////////////// + +int UtcDaliPropertyInputGetExtension(void) +{ + PropertyInputImpl input( Property::BOOLEAN ); + DALI_TEST_CHECK( input.GetExtension() == NULL ); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-CustomActor.cpp b/automated-tests/src/dali/utc-Dali-CustomActor.cpp new file mode 100644 index 0000000..aca2c62 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-CustomActor.cpp @@ -0,0 +1,2011 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "dali-test-suite-utils/dali-test-suite-utils.h" + +using namespace Dali; + + +void custom_actor_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void custom_actor_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +std::vector< std::string > MasterCallStack; +bool gOnRelayout = false; + +} // anon namespace + +// TypeRegistry needs custom actor Implementations to have the same name (namespaces are ignored so we use one here) +namespace Impl +{ + +struct TestCustomActor : public CustomActorImpl +{ + /** + * Constructor + */ + TestCustomActor() + : CustomActorImpl( ActorFlags( REQUIRES_TOUCH_EVENTS | REQUIRES_WHEEL_EVENTS | REQUIRES_HOVER_EVENTS | DISABLE_SIZE_NEGOTIATION ) ), + mDaliProperty( Property::INVALID_INDEX ), + mSizeSet( Vector3::ZERO ), + mTargetSize( Vector3::ZERO ), + mNego( false ), + mDepth(0u) + { + } + + TestCustomActor(bool nego) + : CustomActorImpl( ActorFlags( REQUIRES_TOUCH_EVENTS | REQUIRES_WHEEL_EVENTS | REQUIRES_HOVER_EVENTS ) ), + mDaliProperty( Property::INVALID_INDEX ), + mSizeSet( Vector3::ZERO ), + mTargetSize( Vector3::ZERO ), + mNego( nego ) + { + } + /** + * Destructor + */ + virtual ~TestCustomActor() + { + } + + void Initialize( const char* name = NULL ) + { + mDaliProperty = Self().RegisterProperty( "Dali", std::string("no"), Property::READ_WRITE); + + OnInitialize( name ); + } + + virtual void OnInitialize( const char* name ) {} + + /** + * Resets the call stack + */ + void ResetCallStack() + { + mSizeSet = Vector3(); + mTargetSize = Vector3(); + mMethodsCalled.clear(); + } + + void AddToCallStacks( const char* method ) + { + mMethodsCalled.push_back( method ); + + // Combine Actor name with method string + std::string nameAndMethod( Self().GetName() ); + if ( 0 == nameAndMethod.size() ) + { + nameAndMethod = "Unknown: "; + } + else + { + nameAndMethod += ": "; + } + nameAndMethod += method; + + MasterCallStack.push_back( nameAndMethod ); + } + + // From CustomActorImpl + virtual void OnStageConnection( int depth ) + { + AddToCallStacks("OnStageConnection"); + mDepth = depth; + } + virtual void OnStageDisconnection() + { + AddToCallStacks("OnStageDisconnection"); + } + virtual void OnChildAdd(Actor& child) + { + AddToCallStacks("OnChildAdd"); + } + virtual void OnChildRemove(Actor& child) + { + AddToCallStacks("OnChildRemove"); + } + virtual void OnPropertySet( Property::Index index, Property::Value propertyValue ) + { + AddToCallStacks("OnPropertySet"); + } + virtual void OnSizeSet(const Vector3& targetSize) + { + mSizeSet = targetSize; + AddToCallStacks("OnSizeSet"); + } + virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize) + { + mTargetSize = targetSize; + AddToCallStacks("OnSizeAnimation"); + } + virtual bool OnTouchEvent(const TouchEvent& event) + { + AddToCallStacks("OnTouchEvent"); + return true; + } + virtual bool OnHoverEvent(const HoverEvent& event) + { + AddToCallStacks("OnHoverEvent"); + return true; + } + virtual bool OnWheelEvent(const WheelEvent& event) + { + AddToCallStacks("OnWheelEvent"); + return true; + } + virtual bool OnKeyEvent(const KeyEvent& event) + { + AddToCallStacks("OnKeyEvent"); + return true; + } + virtual void OnKeyInputFocusGained() + { + AddToCallStacks("OnKeyInputFocusGained"); + } + virtual void OnKeyInputFocusLost() + { + AddToCallStacks("OnKeyInputFocusLost"); + } + virtual Vector3 GetNaturalSize() + { + return Vector3( 0.0f, 0.0f, 0.0f ); + } + + virtual float GetHeightForWidth( float width ) + { + return 0.0f; + } + + virtual float GetWidthForHeight( float height ) + { + return 0.0f; + } + + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ) + { + gOnRelayout = true; + } + + virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) + { + } + + virtual void OnCalculateRelayoutSize( Dimension::Type dimension ) + { + } + + virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension ) + { + return 0.0f; + } + + virtual void OnLayoutNegotiated( float size, Dimension::Type dimension ) + { + } + + virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) + { + return false; + } + + void SetDaliProperty(std::string s) + { + Self().SetProperty(mDaliProperty, s); + } + void TestRelayoutRequest() + { + RelayoutRequest(); + } + + float TestGetHeightForWidthBase( float width ) + { + return GetHeightForWidthBase( width ); + } + + float TestGetWidthForHeightBase( float height ) + { + return GetWidthForHeightBase( height ); + } + + float TestCalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension ) + { + return CalculateChildSizeBase( child, dimension ); + } + + bool TestRelayoutDependentOnChildrenBase( Dimension::Type dimension ) + { + return RelayoutDependentOnChildrenBase( dimension ); + } + + Property::Index mDaliProperty; + std::vector< std::string > mMethodsCalled; + Vector3 mSizeSet; + Vector3 mTargetSize; + bool mNego; + unsigned int mDepth; +}; + +/** + * Variant which adds a new child during OnStageConnection + */ +struct TestCustomActorVariant1 : public TestCustomActor +{ + /** + * Constructor + */ + TestCustomActorVariant1( Actor childToAdd ) + : mChildToAdd( childToAdd ) + { + } + + // From CustomActorImpl + virtual void OnStageConnection( int depth ) + { + // Chain up first + TestCustomActor::OnStageConnection( depth ); + + // Add the child + Self().Add( mChildToAdd ); + } + + Actor mChildToAdd; +}; + +/** + * Variant which removes children during OnStageConnection + */ +struct TestCustomActorVariant2 : public TestCustomActor +{ + /** + * Constructor + */ + TestCustomActorVariant2() + { + } + + // From CustomActorImpl + virtual void OnStageConnection( int depth ) + { + // Chain up first + TestCustomActor::OnStageConnection( depth ); + + // Remove all the children + for( unsigned int i=0, num=Self().GetChildCount(); iInitialize(); + + return custom; + } + + static TestCustomActor NewNegoSize() + { + Impl::TestCustomActor* impl = new Impl::TestCustomActor( true ); + TestCustomActor custom( *impl ); // takes ownership + custom.SetName( "SizeNegotiationActor" ); + + impl->Initialize(); + + return custom; + } + + static TestCustomActor NewVariant1( Actor childToAdd ) + { + Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant1( childToAdd ); + TestCustomActor custom( *impl ); // takes ownership + + impl->Initialize(); + + return custom; + } + + static TestCustomActor NewVariant2() + { + Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant2(); + TestCustomActor custom( *impl ); // takes ownership + + impl->Initialize(); + + return custom; + } + + static TestCustomActor NewVariant3( Actor childToAdd ) + { + Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant3( childToAdd ); + TestCustomActor custom( *impl ); // takes ownership + + impl->Initialize(); + + return custom; + } + + static TestCustomActor NewVariant4() + { + Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant4(); + TestCustomActor custom( *impl ); // takes ownership + + impl->Initialize(); + + return custom; + } + + static TestCustomActor NewVariant5() + { + Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant5(); + TestCustomActor custom( *impl ); // takes ownership + + impl->Initialize(); + + return custom; + } + + static TestCustomActor NewVariant6() + { + Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant6(); + TestCustomActor custom( *impl ); // takes ownership + + impl->Initialize(); + + return custom; + } + + static TestCustomActor NewVariant7( const char* name ) + { + Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant7(); + TestCustomActor custom( *impl ); // takes ownership + + impl->Initialize( name ); + + return custom; + } + + static TestCustomActor NewVariant8( Actor rival ) + { + Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant8( rival ); + TestCustomActor custom( *impl ); // takes ownership + + impl->Initialize(); + + return custom; + } + + virtual ~TestCustomActor() + { + } + + Impl::TestCustomActor& GetImpl() + { + return static_cast(GetImplementation()); + } + + std::vector< std::string >& GetMethodsCalled() + { + return GetImpl().mMethodsCalled; + } + + void ResetCallStack() + { + GetImpl().ResetCallStack(); + } + + void SetDaliProperty(std::string s) + { + GetImpl().SetDaliProperty(s); + } + + Vector3 GetSize() + { + return GetImpl().mSizeSet; + } + + Vector3 GetTargetSize() + { + return GetImpl().mTargetSize; + } + + virtual Vector3 GetNaturalSize() + { + return Vector3( 0.0f, 0.0f, 0.0f ); + } + + virtual float GetHeightForWidth( float width ) + { + return 0.0f; + } + + virtual float GetWidthForHeight( float height ) + { + return 0.0f; + } + + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ) + { + } + + virtual void OnLayoutNegotiated( float size, Dimension::Type dimension ) + { + } + + virtual void OnCalculateRelayoutSize( Dimension::Type dimension ) + { + } + + void TestRelayoutRequest() + { + GetImpl().TestRelayoutRequest(); + } + + float TestGetHeightForWidthBase( float width ) + { + return GetImpl().TestGetHeightForWidthBase( width ); + } + + float TestGetWidthForHeightBase( float height ) + { + return GetImpl().TestGetWidthForHeightBase( height ); + } + + float TestCalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension ) + { + return GetImpl().TestCalculateChildSizeBase( child, dimension ); + } + + bool TestRelayoutDependentOnChildrenBase( Dimension::Type dimension ) + { + return GetImpl().TestRelayoutDependentOnChildrenBase( dimension ); + } + + unsigned int GetDepth() + { + return GetImpl().mDepth; + } +private: + + TestCustomActor( Impl::TestCustomActor& impl ) : CustomActor( impl ) + { + } +}; + + + +using namespace Dali; + +BaseHandle CreateActor() +{ + return TestCustomActor::New(); +} + +Dali::TypeRegistration mType( typeid(TestCustomActor), typeid(Dali::CustomActor), CreateActor ); + +} // anon namespace + + +int UtcDaliCustomActorDestructor(void) +{ + TestApplication application; + + CustomActor* actor = new CustomActor(); + delete actor; + + DALI_TEST_CHECK( true ); + END_TEST; +} + +int UtcDaliCustomActorImplDestructor(void) +{ + TestApplication application; + CustomActorImpl* actor = new Impl::TestCustomActor(); + delete actor; + + DALI_TEST_CHECK( true ); + END_TEST; +} + +// Positive test case for a method +int UtcDaliCustomActorDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::DownCast()"); + + TestCustomActor custom = TestCustomActor::New(); + + Actor anActor = Actor::New(); + anActor.Add( custom ); + + Actor child = anActor.GetChildAt(0); + CustomActor customActor = CustomActor::DownCast( child ); + DALI_TEST_CHECK( customActor ); + + customActor = NULL; + DALI_TEST_CHECK( !customActor ); + + customActor = DownCast< CustomActor >( child ); + DALI_TEST_CHECK( customActor ); + END_TEST; +} + +// Negative test case for a method +int UtcDaliCustomActorDownCastNegative(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::DownCast()"); + + Actor actor1 = Actor::New(); + Actor anActor = Actor::New(); + anActor.Add(actor1); + + Actor child = anActor.GetChildAt(0); + CustomActor customActor = CustomActor::DownCast( child ); + DALI_TEST_CHECK( !customActor ); + + Actor unInitialzedActor; + customActor = CustomActor::DownCast( unInitialzedActor ); + DALI_TEST_CHECK( !customActor ); + + customActor = DownCast< CustomActor >( unInitialzedActor ); + DALI_TEST_CHECK( !customActor ); + END_TEST; +} + +int UtcDaliCustomActorOnStageConnectionDisconnection(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::OnStageConnection() & OnStageDisconnection"); + + TestCustomActor custom = TestCustomActor::New(); + DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + + // add the custom actor to stage + Stage::GetCurrent().Add( custom ); + + DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + Stage::GetCurrent().Remove( custom ); + + DALI_TEST_EQUALS( 2, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", custom.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + END_TEST; +} + +int UtcDaliCustomActorOnStageConnectionOrder(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::OnStageConnection() order"); + + MasterCallStack.clear(); + + /* Build tree of actors: + * + * A (parent) + * / \ + * B C + * / \ \ + * D E F + * + * OnStageConnection should be received for A, B, D, E, C, and finally F + */ + + TestCustomActor actorA = TestCustomActor::New(); + actorA.SetName( "ActorA" ); + + TestCustomActor actorB = TestCustomActor::New(); + actorB.SetName( "ActorB" ); + actorA.Add( actorB ); + + TestCustomActor actorC = TestCustomActor::New(); + actorC.SetName( "ActorC" ); + actorA.Add( actorC ); + + TestCustomActor actorD = TestCustomActor::New(); + actorD.SetName( "ActorD" ); + actorB.Add( actorD ); + + TestCustomActor actorE = TestCustomActor::New(); + actorE.SetName( "ActorE" ); + actorB.Add( actorE ); + + TestCustomActor actorF = TestCustomActor::New(); + actorF.SetName( "ActorF" ); + actorC.Add( actorF ); + + // add the custom actor to stage + Stage::GetCurrent().Add( actorA ); + + DALI_TEST_EQUALS( 3, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorA.GetMethodsCalled()[ 2 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 3, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorB.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorB.GetMethodsCalled()[ 2 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 2, (int)(actorC.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorC.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorC.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 1, (int)(actorD.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorD.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 1, (int)(actorE.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorE.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 1, (int)(actorF.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorF.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + // Check sequence is correct in MasterCallStack + + DALI_TEST_EQUALS( 3+3+2+1+1+1, (int)(MasterCallStack.size()), TEST_LOCATION ); + + DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorB: OnChildAdd", MasterCallStack[ 2 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorB: OnChildAdd", MasterCallStack[ 3 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorC: OnChildAdd", MasterCallStack[ 4 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( "ActorA: OnStageConnection", MasterCallStack[ 5 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorB: OnStageConnection", MasterCallStack[ 6 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorD: OnStageConnection", MasterCallStack[ 7 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorE: OnStageConnection", MasterCallStack[ 8 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorC: OnStageConnection", MasterCallStack[ 9 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorF: OnStageConnection", MasterCallStack[ 10 ], TEST_LOCATION ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + END_TEST; +} + +int UtcDaliCustomActorOnStageDisconnectionOrder(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::OnStageDisconnection() order"); + + Stage stage = Stage::GetCurrent(); + + /* Build tree of actors: + * + * A (parent) + * / \ + * B C + * / \ \ + * D E F + * + * OnStageDisconnection should be received for D, E, B, F, C, and finally A. + */ + + TestCustomActor actorA = TestCustomActor::New(); + actorA.SetName( "ActorA" ); + stage.Add( actorA ); + + TestCustomActor actorB = TestCustomActor::New(); + actorB.SetName( "ActorB" ); + actorA.Add( actorB ); + + TestCustomActor actorC = TestCustomActor::New(); + actorC.SetName( "ActorC" ); + actorA.Add( actorC ); + + TestCustomActor actorD = TestCustomActor::New(); + actorD.SetName( "ActorD" ); + actorB.Add( actorD ); + + TestCustomActor actorE = TestCustomActor::New(); + actorE.SetName( "ActorE" ); + actorB.Add( actorE ); + + TestCustomActor actorF = TestCustomActor::New(); + actorF.SetName( "ActorF" ); + actorC.Add( actorF ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + + // Clear call stacks before disconnection + actorA.ResetCallStack(); + actorB.ResetCallStack(); + actorC.ResetCallStack(); + actorD.ResetCallStack(); + actorE.ResetCallStack(); + actorF.ResetCallStack(); + MasterCallStack.clear(); + + stage.Remove( actorA ); + + DALI_TEST_EQUALS( 1, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 1, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 1, (int)(actorC.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", actorC.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 1, (int)(actorD.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", actorD.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 1, (int)(actorE.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", actorE.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 1, (int)(actorF.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", actorF.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + // Check sequence is correct in MasterCallStack + + DALI_TEST_EQUALS( 6, (int)(MasterCallStack.size()), TEST_LOCATION ); + + DALI_TEST_EQUALS( "ActorD: OnStageDisconnection", MasterCallStack[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorE: OnStageDisconnection", MasterCallStack[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorB: OnStageDisconnection", MasterCallStack[ 2 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorF: OnStageDisconnection", MasterCallStack[ 3 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorC: OnStageDisconnection", MasterCallStack[ 4 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnStageDisconnection", MasterCallStack[ 5 ], TEST_LOCATION ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + END_TEST; +} + +int UtcDaliCustomActorAddDuringOnStageConnection(void) +{ + TestApplication application; + tet_infoline("Testing Actor::Add behaviour during Dali::CustomActor::OnStageConnection() callback"); + + Stage stage = Stage::GetCurrent(); + + MasterCallStack.clear(); + + /* The actorA is a special variant which adds a child to itself during OnStageConnection() + * The actorB is provided as the child + */ + + TestCustomActor actorB = TestCustomActor::New(); + actorB.SetName( "ActorB" ); + + TestCustomActor actorA = TestCustomActor::NewVariant1( actorB ); + actorA.SetName( "ActorA" ); + stage.Add( actorA ); + + // Check callback sequence + + DALI_TEST_EQUALS( 2, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION ); // Called from within OnStageConnection() + + DALI_TEST_EQUALS( 2, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 3, (int)(MasterCallStack.size()), TEST_LOCATION ); + + DALI_TEST_EQUALS( "ActorA: OnStageConnection", MasterCallStack[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorB: OnStageConnection", MasterCallStack[ 1 ], TEST_LOCATION ); // Occurs during Actor::Add from within from within OnStageConnection() + DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 2 ], TEST_LOCATION ); // Occurs after Actor::Add from within from within OnStageConnection() + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + + // Check everything is ok after Actors are removed + + stage.Remove( actorA ); + application.SendNotification(); + application.Render(); + application.Render(); + END_TEST; +} + +int UtcDaliCustomActorRemoveDuringOnStageConnection(void) +{ + TestApplication application; + tet_infoline("Testing Actor::Remove behaviour during Dali::CustomActor::OnStageConnection() callback"); + + Stage stage = Stage::GetCurrent(); + + MasterCallStack.clear(); + + /* The actorA is a special variant which removes its children during OnStageConnection() + * Actors B & C are provided as the children + */ + + TestCustomActor actorA = TestCustomActor::NewVariant2(); + actorA.SetName( "ActorA" ); + + TestCustomActor actorB = TestCustomActor::New(); + actorB.SetName( "ActorB" ); + actorA.Add( actorB ); + + TestCustomActor actorC = TestCustomActor::New(); + actorC.SetName( "ActorC" ); + actorA.Add( actorC ); + + stage.Add( actorA ); + + // Check callback sequence + + DALI_TEST_EQUALS( 5, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorA.GetMethodsCalled()[ 2 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildRemove", actorA.GetMethodsCalled()[ 3 ], TEST_LOCATION ); // Called from within OnStageConnection() + DALI_TEST_EQUALS( "OnChildRemove", actorA.GetMethodsCalled()[ 4 ], TEST_LOCATION ); // Called from within OnStageConnection() + + DALI_TEST_EQUALS( 5, (int)(MasterCallStack.size()), TEST_LOCATION ); + + DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnStageConnection", MasterCallStack[ 2 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnChildRemove", MasterCallStack[ 3 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnChildRemove", MasterCallStack[ 4 ], TEST_LOCATION ); + + /* Actors B & C should be removed before the point where they could receive an OnStageConnection callback + * Therefore they shouldn't receive either OnStageConnection or OnStageDisconnection + */ + DALI_TEST_EQUALS( 0, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( 0, (int)(actorC.GetMethodsCalled().size()), TEST_LOCATION ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + + // Check everything is ok after last actor is removed + + stage.Remove( actorA ); + application.SendNotification(); + application.Render(); + application.Render(); + END_TEST; +} + +int UtcDaliCustomActorAddDuringOnStageDisconnection(void) +{ + TestApplication application; + tet_infoline("Testing Actor::Add behaviour during Dali::CustomActor::OnStageDisonnection() callback"); + + Stage stage = Stage::GetCurrent(); + + /* The actorA is a special variant which adds a child to itself during OnStageDisconnection() + * The actorB is provided as the child + */ + + TestCustomActor actorB = TestCustomActor::New(); + actorB.SetName( "ActorB" ); + + TestCustomActor actorA = TestCustomActor::NewVariant3( actorB ); + actorA.SetName( "ActorA" ); + stage.Add( actorA ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + + // Clear call stacks before disconnection + actorA.ResetCallStack(); + actorB.ResetCallStack(); + MasterCallStack.clear(); + + stage.Remove( actorA ); + + // Check callback sequence + + DALI_TEST_EQUALS( 2, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + + // Child was added after parent disconnection, so should not receive OnStageConnection() + DALI_TEST_EQUALS( 0, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION ); + + DALI_TEST_EQUALS( 2, (int)(MasterCallStack.size()), TEST_LOCATION ); + + DALI_TEST_EQUALS( "ActorA: OnStageDisconnection", MasterCallStack[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 1 ], TEST_LOCATION ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + END_TEST; +} + +int UtcDaliCustomActorRemoveDuringOnStageDisconnection(void) +{ + TestApplication application; + tet_infoline("Testing Actor::Remove behaviour during Dali::CustomActor::OnStageDisconnection() callback"); + + Stage stage = Stage::GetCurrent(); + + /* The actorA is a special variant which removes its children during OnStageDisconnection() + * The actorB is provided as the child + */ + + TestCustomActor actorA = TestCustomActor::NewVariant4(); + actorA.SetName( "ActorA" ); + stage.Add( actorA ); + + TestCustomActor actorB = TestCustomActor::New(); + actorB.SetName( "ActorB" ); + actorA.Add( actorB ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + + // Clear call stacks before disconnection + actorA.ResetCallStack(); + actorB.ResetCallStack(); + MasterCallStack.clear(); + + stage.Remove( actorA ); + + // Check callback sequence + + DALI_TEST_EQUALS( 2, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildRemove", actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 1, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 3, (int)(MasterCallStack.size()), TEST_LOCATION ); + + DALI_TEST_EQUALS( "ActorB: OnStageDisconnection", MasterCallStack[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnStageDisconnection", MasterCallStack[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnChildRemove", MasterCallStack[ 2 ], TEST_LOCATION ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + END_TEST; +} + +int UtcDaliCustomActorRemoveParentDuringOnStageConnection(void) +{ + TestApplication application; + tet_infoline("Weird test where child removes its own parent from Stage during Dali::CustomActor::OnStageConnection() callback"); + + Stage stage = Stage::GetCurrent(); + + MasterCallStack.clear(); + + /* The actorA is the parent of actorB + * The actorB is a special variant which removes its own parent during OnStageConnection() + * The child actor is interrupting the parent's connection to stage, therefore the parent should not get an OnStageDisconnection() + */ + + TestCustomActor actorA = TestCustomActor::New(); + actorA.SetName( "ActorA" ); + + TestCustomActor actorB = TestCustomActor::NewVariant5(); + actorB.SetName( "ActorB" ); + actorA.Add( actorB ); + + stage.Add( actorA ); + + // Check callback sequence + + DALI_TEST_EQUALS( 3, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", actorA.GetMethodsCalled()[ 2 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 1, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 4, (int)(MasterCallStack.size()), TEST_LOCATION ); + + DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnStageConnection", MasterCallStack[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorB: OnStageConnection", MasterCallStack[ 2 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnStageDisconnection", MasterCallStack[ 3 ], TEST_LOCATION ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + END_TEST; +} + +int UtcDaliCustomActorAddParentDuringOnStageDisconnection(void) +{ + TestApplication application; + tet_infoline("Weird test where child adds its own parent to Stage during Dali::CustomActor::OnStageDisconnection() callback"); + + Stage stage = Stage::GetCurrent(); + + MasterCallStack.clear(); + + /* The actorA is the parent of actorB + * The actorB is a special variant which (weirdly) adds its own parent during OnStageDisconnection() + * The child actor is interrupting the disconnection, such that parent should not get a OnStageDisconnection() + */ + + TestCustomActor actorA = TestCustomActor::New(); + actorA.SetName( "ActorA" ); + stage.Add( actorA ); + + TestCustomActor actorB = TestCustomActor::NewVariant6(); + actorB.SetName( "ActorB" ); + actorA.Add( actorB ); + + stage.Remove( actorA ); + + // Check callback sequence + + DALI_TEST_EQUALS( 2, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 2, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", actorB.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + // Disconnect was interrupted, so we should only get one OnStageConnection() for actorB + + DALI_TEST_EQUALS( 4, (int)(MasterCallStack.size()), TEST_LOCATION ); + + DALI_TEST_EQUALS( "ActorA: OnStageConnection", MasterCallStack[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorB: OnStageConnection", MasterCallStack[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 2 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorB: OnStageDisconnection", MasterCallStack[ 3 ], TEST_LOCATION ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + END_TEST; +} + +int UtcDaliCustomActorOnChildAddRemove(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::OnChildAdd() & OnChildRemove()"); + + TestCustomActor custom = TestCustomActor::New(); + DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + + Actor aChild = Actor::New(); + custom.Add( aChild ); + + DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + + custom.Remove( aChild ); + + DALI_TEST_EQUALS( 2, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildRemove", custom.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCustomActorReparentDuringOnChildAdd(void) +{ + TestApplication application; + tet_infoline("Testing Actor:Add (reparenting) behaviour during Dali::CustomActor::OnChildAdd() callback"); + + Stage stage = Stage::GetCurrent(); + + MasterCallStack.clear(); + + /* The actorA is a special variant which reparents children added into a separate container child + * The actorB is the child of actorA + */ + + TestCustomActor actorA = TestCustomActor::NewVariant7( "ActorA" ); + stage.Add( actorA ); + + TestCustomActor actorB = TestCustomActor::New(); + actorB.SetName( "ActorB" ); + actorA.Add( actorB ); + + // Check hierarchy is as follows: + // A + // | + // Container + // | + // B + + DALI_TEST_EQUALS( 1, (int)(actorA.GetChildCount()), TEST_LOCATION ); + + Actor container = actorA.GetChildAt(0); + Actor containerChild; + + DALI_TEST_CHECK( container ); + if ( container ) + { + DALI_TEST_EQUALS( "Container", container.GetName(), TEST_LOCATION ); + DALI_TEST_EQUALS( 1, (int)(container.GetChildCount()), TEST_LOCATION ); + containerChild = container.GetChildAt(0); + } + + DALI_TEST_CHECK( containerChild ); + if ( containerChild ) + { + DALI_TEST_EQUALS( "ActorB", containerChild.GetName(), TEST_LOCATION ); + DALI_TEST_EQUALS( 0, (int)(containerChild.GetChildCount()), TEST_LOCATION ); + } + + // Check callback sequence + + DALI_TEST_EQUALS( 4, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); // The mContainer added to actorA + DALI_TEST_EQUALS( "OnStageConnection", actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorA.GetMethodsCalled()[ 2 ], TEST_LOCATION ); // The actorB added to actorA + DALI_TEST_EQUALS( "OnChildRemove", actorA.GetMethodsCalled()[ 3 ], TEST_LOCATION ); + // mContainer will then receive OnChildAdd + + DALI_TEST_EQUALS( 3, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageDisconnection", actorB.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorB.GetMethodsCalled()[ 2 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 7, (int)(MasterCallStack.size()), TEST_LOCATION ); + + DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnStageConnection", MasterCallStack[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorB: OnStageConnection", MasterCallStack[ 2 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 3 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorB: OnStageDisconnection", MasterCallStack[ 4 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnChildRemove", MasterCallStack[ 5 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorB: OnStageConnection", MasterCallStack[ 6 ], TEST_LOCATION ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + END_TEST; +} + +/** + * Test that Remove can be called (a NOOP) during the OnChildRemove + * triggered when reparenting an actor + */ +int UtcDaliCustomActorRemoveDuringOnChildRemove(void) +{ + TestApplication application; + tet_infoline("Testing Actor:Remove behaviour during OnChildRemove() callback triggered when reparenting"); + + Stage stage = Stage::GetCurrent(); + + MasterCallStack.clear(); + + /* The childActor will be reparented from actorA to actorB + * The actorA is a special variant which attempts to remove a child from actorB, during the OnChildRemove callback() + * This should be a NOOP since the reparenting has not occured yet + */ + + TestCustomActor actorB = TestCustomActor::New(); + actorB.SetName( "ActorB" ); + stage.Add( actorB ); + + TestCustomActor actorA = TestCustomActor::NewVariant8( actorB ); + actorA.SetName( "ActorA" ); + stage.Add( actorA ); + + Actor childActor = Actor::New(); + childActor.SetName( "Child" ); + // Reparent from actorA to actorB + actorA.Add( childActor ); + actorB.Add( childActor ); + + // Check hierarchy is as follows: + // A B + // | + // Child + + DALI_TEST_EQUALS( 0, (int)(actorA.GetChildCount()), TEST_LOCATION ); + DALI_TEST_EQUALS( 1, (int)(actorB.GetChildCount()), TEST_LOCATION ); + DALI_TEST_EQUALS( 0, (int)(childActor.GetChildCount()), TEST_LOCATION ); + + Actor child = actorB.GetChildAt(0); + + DALI_TEST_CHECK( child ); + if ( child ) + { + DALI_TEST_EQUALS( "Child", child.GetName(), TEST_LOCATION ); + } + + // Check callback sequence + + DALI_TEST_EQUALS( 3, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); // The mContainer added to actorA + DALI_TEST_EQUALS( "OnChildAdd", actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildRemove", actorA.GetMethodsCalled()[ 2 ], TEST_LOCATION ); // The actorB added to actorA + // mContainer will then receive OnChildAdd + + DALI_TEST_EQUALS( 2, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnStageConnection", actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "OnChildAdd", actorB.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + + DALI_TEST_EQUALS( 5, (int)(MasterCallStack.size()), TEST_LOCATION ); + + DALI_TEST_EQUALS( "ActorB: OnStageConnection", MasterCallStack[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnStageConnection", MasterCallStack[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 2 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorA: OnChildRemove", MasterCallStack[ 3 ], TEST_LOCATION ); + DALI_TEST_EQUALS( "ActorB: OnChildAdd", MasterCallStack[ 4 ], TEST_LOCATION ); + + // Excercise the message passing to Update thread + + application.SendNotification(); + application.Render(); + application.Render(); + END_TEST; +} + +int UtcDaliCustomActorOnPropertySet(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::OnPropertySet()"); + + TestCustomActor custom = TestCustomActor::New(); + DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + + custom.SetDaliProperty("yes"); + + DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnPropertySet", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCustomActorOnSizeSet(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::OnSizeSet()"); + + TestCustomActor custom = TestCustomActor::New(); + DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + + custom.SetSize( Vector2( 9.0f, 10.0f ) ); + DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnSizeSet", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( 9.0f, custom.GetSize().width, TEST_LOCATION ); + DALI_TEST_EQUALS( 10.0f, custom.GetSize().height, TEST_LOCATION ); + + custom.SetSize( Vector3( 4.0f, 5.0f, 6.0f ) ); + DALI_TEST_EQUALS( 2, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnSizeSet", custom.GetMethodsCalled()[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( 4.0f, custom.GetSize().width, TEST_LOCATION ); + DALI_TEST_EQUALS( 5.0f, custom.GetSize().height, TEST_LOCATION ); + DALI_TEST_EQUALS( 6.0f, custom.GetSize().depth, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCustomActorOnSizeAnimation(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::OnSizeAnimation()"); + + TestCustomActor custom = TestCustomActor::New(); + DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + + Animation anim = Animation::New( 1.0f ); + anim.AnimateTo( Property( custom, Actor::Property::SIZE ), Vector3( 8.0f, 9.0f, 10.0f ) ); + DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnSizeAnimation", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( 8.0f, custom.GetTargetSize().width, TEST_LOCATION ); + DALI_TEST_EQUALS( 9.0f, custom.GetTargetSize().height, TEST_LOCATION ); + DALI_TEST_EQUALS( 10.0f, custom.GetTargetSize().depth, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCustomActorOnTouchEvent(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::OnTouchEvent()"); + + TestCustomActor custom = TestCustomActor::New(); + DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + + // set size for custom actor + custom.SetSize( 100, 100 ); + // add the custom actor to stage + Stage::GetCurrent().Add( custom ); + custom.ResetCallStack(); + + // Render and notify a couple of times + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + // simulate a touch event + Dali::TouchPoint point( 0, TouchPoint::Down, 1, 1 ); + Dali::Integration::TouchEvent event; + event.AddPoint( point ); + application.ProcessEvent( event ); + + DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnTouchEvent", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCustomActorOnHoverEvent(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::OnHoverEvent()"); + + TestCustomActor custom = TestCustomActor::New(); + DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + + // set size for custom actor + custom.SetSize( 100, 100 ); + // add the custom actor to stage + Stage::GetCurrent().Add( custom ); + custom.ResetCallStack(); + + // Render and notify a couple of times + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + // simulate a hover event + Dali::TouchPoint point( 0, TouchPoint::Motion, 1, 1 ); + Dali::Integration::HoverEvent event; + event.AddPoint( point ); + application.ProcessEvent( event ); + + DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnHoverEvent", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCustomActorOnWheelEvent(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::OnWheelEvent()"); + + TestCustomActor custom = TestCustomActor::New(); + DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + + // set size for custom actor + custom.SetSize( 100, 100 ); + // add the custom actor to stage + Stage::GetCurrent().Add( custom ); + custom.ResetCallStack(); + + // Render and notify a couple of times + application.SendNotification(); + application.Render(); + application.SendNotification(); + application.Render(); + + // simulate a wheel event + Vector2 screenCoordinates( 10.0f, 10.0f ); + Integration::WheelEvent event( Integration::WheelEvent::MOUSE_WHEEL, 0, 0u, screenCoordinates, 1, 1000u ); + application.ProcessEvent( event ); + + DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION ); + DALI_TEST_EQUALS( "OnWheelEvent", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION ); + END_TEST; +} + +int UtcDaliCustomActorImplOnPropertySet(void) +{ + TestApplication application; + CustomActorImpl* impl = new Impl::SimpleTestCustomActor(); + + impl->OnPropertySet( 0, 0 ); + + DALI_TEST_CHECK( true ); + + delete impl; + END_TEST; +} + +int UtcDaliCustomActorGetImplementation(void) +{ + TestApplication application; + + TestCustomActor custom = TestCustomActor::New(); + CustomActorImpl& impl = custom.GetImplementation(); + impl.GetOwner(); // Test + + const TestCustomActor constCustom = TestCustomActor::New(); + const CustomActorImpl& constImpl = constCustom.GetImplementation(); + constImpl.GetOwner(); // Test + + DALI_TEST_CHECK( true ); + END_TEST; +} + +int UtcDaliCustomActorDoAction(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::DoAction()"); + + TestCustomActor custom = TestCustomActor::New(); + + BaseHandle customActorObject = custom; + + DALI_TEST_CHECK(customActorObject); + + Property::Map attributes; + + // Check that an invalid command is not performed + DALI_TEST_CHECK(customActorObject.DoAction("invalidCommand", attributes) == false); + + // Check that the custom actor is visible + custom.SetVisible(true); + DALI_TEST_CHECK(custom.IsVisible() == true); + + // Check the custom actor performed an action to hide itself + DALI_TEST_CHECK(customActorObject.DoAction("hide", attributes) == true); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + // Check that the custom actor is now invisible + DALI_TEST_CHECK(custom.IsVisible() == false); + + // Check the custom actor performed an action to show itself + DALI_TEST_CHECK(customActorObject.DoAction("show", attributes) == true); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + // Check that the custom actor is now visible + DALI_TEST_CHECK(custom.IsVisible() == true); + END_TEST; +} + +int UtcDaliCustomActorCustomActor(void) +{ + Dali::CustomActor customA; + Dali::CustomActor customB( customA ); + + DALI_TEST_CHECK( customA == customB ); + + END_TEST; +} + +int UtcDaliCustomActorImplRelayoutRequest(void) +{ + TestApplication application; + + DALI_TEST_CHECK( gOnRelayout == false ); + + TestCustomActor custom = TestCustomActor::NewNegoSize(); + Stage::GetCurrent().Add(custom); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( gOnRelayout == true ); + gOnRelayout = false; + + custom.TestRelayoutRequest(); + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( gOnRelayout == true ); + + END_TEST; +} + +int UtcDaliCustomActorImplGetHeightForWidthBase(void) +{ + TestApplication application; + TestCustomActor custom = TestCustomActor::NewNegoSize(); + + float width = 300.0f; + float v = 0.0f; + + application.SendNotification(); + application.Render(); + + v = custom.TestGetHeightForWidthBase( width ); + + DALI_TEST_CHECK( v == width ); + + END_TEST; +} + +int UtcDaliCustomActorImplGetWidthForHeightBase(void) +{ + TestApplication application; + TestCustomActor custom = TestCustomActor::NewNegoSize(); + + float height = 300.0f; + float v = 0.0f; + + application.SendNotification(); + application.Render(); + + v = custom.TestGetWidthForHeightBase( height ); + + DALI_TEST_CHECK( v == height ); + + END_TEST; +} + +int UtcDaliCustomActorImplCalculateChildSizeBase(void) +{ + TestApplication application; + TestCustomActor custom = TestCustomActor::NewNegoSize(); + + Actor child = Actor::New(); + child.SetResizePolicy(Dali::ResizePolicy::FIXED, Dali::Dimension::ALL_DIMENSIONS); + child.SetSize(150, 150); + + application.SendNotification(); + application.Render(); + + float v = 9.99f; + v = custom.TestCalculateChildSizeBase( child, Dali::Dimension::ALL_DIMENSIONS ); + DALI_TEST_CHECK( v == 0.0f ); + + END_TEST; +} + +int UtcDaliCustomActorImplRelayoutDependentOnChildrenBase(void) +{ + TestApplication application; + TestCustomActor custom = TestCustomActor::NewNegoSize(); + custom.SetResizePolicy(Dali::ResizePolicy::FIT_TO_CHILDREN, Dali::Dimension::ALL_DIMENSIONS); + + bool v = false; + + v = custom.TestRelayoutDependentOnChildrenBase( Dali::Dimension::ALL_DIMENSIONS ); + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( v == true ); + + custom.SetResizePolicy(Dali::ResizePolicy::FIXED, Dali::Dimension::ALL_DIMENSIONS); + v = custom.TestRelayoutDependentOnChildrenBase( Dali::Dimension::WIDTH ); + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK( v == false ); + + END_TEST; +} + +int UtcDaliCustomActorTypeRegistry(void) +{ + TestApplication application; + + // Register Type + TypeInfo type; + type = TypeRegistry::Get().GetTypeInfo( "CustomActor" ); + DALI_TEST_CHECK( type ); + BaseHandle handle = type.CreateInstance(); + + std::string name; + std::string exception; + + try + { + name = handle.GetTypeName(); + tet_result(TET_FAIL); + } + catch( DaliException& e ) + { + exception = e.condition; + DALI_TEST_EQUALS( exception, "handle && \"BaseObject handle is empty\"", TEST_LOCATION ); + } + + END_TEST; +} + + +int UtcDaliCustomActorGetExtensionP(void) +{ + TestApplication application; + + TestCustomActor custom = TestCustomActor::NewVariant5(); + + DALI_TEST_CHECK( NULL == custom.GetImplementation().GetExtension() ); + + END_TEST; +} + +int UtcDaliCustomActorOnConnectionDepth(void) +{ + TestApplication application; + tet_infoline("Testing Dali::CustomActor::OnStageConnection() hierarchy depth"); + + Stage stage = Stage::GetCurrent(); + + /* Build tree of actors: + * + * Depth + * + * A (parent) 1 + * / \ + * B C 2 + * / \ \ + * D E F 3 + * + * OnStageConnection should return 1 for A, 2 for B and C, and 3 for D, E and F. + */ + + TestCustomActor actorA = TestCustomActor::New(); + stage.Add( actorA ); + + TestCustomActor actorB = TestCustomActor::New(); + actorA.Add( actorB ); + + TestCustomActor actorC = TestCustomActor::New(); + actorA.Add( actorC ); + + TestCustomActor actorD = TestCustomActor::New(); + actorB.Add( actorD ); + + TestCustomActor actorE = TestCustomActor::New(); + actorB.Add( actorE ); + + TestCustomActor actorF = TestCustomActor::New(); + actorC.Add( actorF ); + + // Excercise the message passing to Update thread + application.SendNotification(); + application.Render(); + application.Render(); + + DALI_TEST_EQUALS( 1u, actorA.GetDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( 2u, actorB.GetDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( 2u, actorC.GetDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( 3u, actorD.GetDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( 3u, actorE.GetDepth(), TEST_LOCATION ); + DALI_TEST_EQUALS( 3u, actorF.GetDepth(), TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Degree.cpp b/automated-tests/src/dali/utc-Dali-Degree.cpp new file mode 100644 index 0000000..5bf1f1e --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Degree.cpp @@ -0,0 +1,99 @@ +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_degree_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_degree_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +// Positive test case for constructors +int UtcDaliDegreeConstructors01(void) +{ + TestApplication application; + + // Default constructor, does not initialise the value + Degree degree0( 0.0f ); + + // Test assignment operator + degree0 = Degree(180.0f); + DALI_TEST_EQUALS( degree0.degree, 180.0f, 0.001f, TEST_LOCATION ); + + // Constructor from float value + Degree degree1( 180.0f ); + DALI_TEST_EQUALS( degree1.degree, 180.0f, 0.001f, TEST_LOCATION ); + + // Constructor from a Radian + Degree degree2( Radian( Math::PI ) ); + DALI_TEST_EQUALS( degree2.degree, 180.0f, 0.001f, TEST_LOCATION ); + + END_TEST; +} + +// Positive test case for comparison +int UtcDaliDegreeComparison01(void) +{ + TestApplication application; + + // Comparison between degrees + Degree degree0( 90.0f ); + Degree degree1( 90.0f ); + Degree degree2( 180.0f ); + + DALI_TEST_CHECK( degree0 == degree1 ); + DALI_TEST_CHECK( degree0 != degree2 ); + + // Comparison between radian to degree + Degree degree3( 180.0f ); + Degree degree4( 90.0f ); + Radian radian0( Math::PI ); + + DALI_TEST_CHECK( degree3 == Degree(radian0) ); + DALI_TEST_CHECK( degree4 != Degree(radian0) ); + + // Comparison with float + Degree degree5( 90.0f ); + + DALI_TEST_CHECK( degree5.degree == 90.0f ); + DALI_TEST_CHECK( degree5.degree != 180.0f ); + + END_TEST; +} + +int UtcDaliDegreeOperatorEquals(void) +{ + TestApplication application; + + Degree a(90.0f); + Degree b(90.0f); + Degree c(180.0f); + + DALI_TEST_EQUALS(a == a, true, TEST_LOCATION); + DALI_TEST_EQUALS(a == b, true, TEST_LOCATION); + DALI_TEST_EQUALS(a == c, false, TEST_LOCATION); + END_TEST; +} + +int UtcDaliDegreeOperatorNotEquals(void) +{ + TestApplication application; + + Degree a(90.0f); + Degree b(90.0f); + Degree c(180.0f); + + DALI_TEST_EQUALS(a != a, false, TEST_LOCATION); + DALI_TEST_EQUALS(a != b, false, TEST_LOCATION); + DALI_TEST_EQUALS(a != c, true, TEST_LOCATION); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-EncodedBufferImage.cpp b/automated-tests/src/dali/utc-Dali-EncodedBufferImage.cpp new file mode 100644 index 0000000..70e6c50 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-EncodedBufferImage.cpp @@ -0,0 +1,882 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include + + +namespace +{ +/** PNG image file converted to an array using standard linux commandline tool: + * xxd -i fractal.001.32x32.png | gvim - + * This is 720 wide x 1280 high. + */ +const unsigned char sEncodedBufferImageDataPNG[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, + 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x02, 0xd0, 0x00, 0x00, 0x05, 0x00, + 0x08, 0x02, 0x00, 0x00, 0x00, 0xe1, 0xac, 0xf2, 0x6a, 0x00, 0x00, 0x00, + 0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, + 0x20, 0x00, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0xd8, 0x5d, 0x8f, + 0x5c, 0x87, 0x7d, 0xdf, 0xf1, 0x39, 0x7b, 0xce, 0xec, 0xcc, 0xce, 0x72, + 0xc9, 0x5d, 0x92, 0x22, 0x45, 0x8a, 0x22, 0x45, 0x51, 0x22, 0x25, 0x45, + 0x96, 0x6d, 0x45, 0xb6, 0x23, 0x25, 0xb5, 0x93, 0x18, 0x49, 0x6c, 0x35, + 0x48, 0xe0, 0x38, 0x76, 0xdd, 0x34, 0x35, 0x82, 0x5e, 0x04, 0x01, 0xda, + 0xdb, 0x02, 0xed, 0x55, 0x8b, 0x02, 0x05, 0x7a, 0xd1, 0x14, 0xc8, 0x65, + 0x0b, 0x17, 0x45, 0x9a, 0x06, 0x70, 0x9b, 0xd6, 0x76, 0x6c, 0x07, 0xb6, + 0x13, 0xa7, 0x89, 0x6d, 0xd5, 0x71, 0x2c, 0x89, 0xb6, 0xf5, 0x4c, 0x49, + 0x94, 0xf8, 0x24, 0x3e, 0x53, 0xe4, 0xee, 0x92, 0x3b, 0x3b, 0x0f, 0xe7, + 0x9c, 0xbe, 0x01, 0xf7, 0x22, 0xc0, 0xfc, 0xd0, 0x4e, 0xfa, 0xf9, 0xbc, + 0x80, 0x1f, 0x0f, 0xfe, 0x9c, 0x87, 0xef, 0x4e, 0xf1, 0x9d, 0xf7, 0xfd, + 0x4e, 0x27, 0x66, 0x38, 0x2d, 0x3b, 0x49, 0xc3, 0x49, 0x70, 0xff, 0xb5, + 0xe9, 0xce, 0xdc, 0xf8, 0x1f, 0xef, 0x39, 0x14, 0xbd, 0xcc, 0x87, 0x2f, + 0x5e, 0xc9, 0x8d, 0x1f, 0x5d, 0xbc, 0x93, 0x1b, 0xdf, 0xdf, 0x1d, 0xe5, + 0xc6, 0x0f, 0xae, 0x6c, 0x45, 0xcf, 0x5e, 0x14, 0xc1, 0xf1, 0x41, 0x7f, + 0x9a, 0x1b, 0xef, 0x96, 0x4d, 0xf4, 0x32, 0xbd, 0x5e, 0x9d, 0x1b, 0xaf, + 0xaa, 0xe0, 0x78, 0xdb, 0x16, 0xd1, 0xcb, 0x74, 0xa3, 0x97, 0xe9, 0xce, + 0xeb, 0x65, 0x16, 0xca, 0x36, 0xfc, 0x56, 0x0d, 0xee, 0xd7, 0xd3, 0x85, + 0x39, 0x7d, 0xf2, 0x4e, 0xa7, 0xd3, 0xd4, 0xc1, 0x87, 0x5f, 0xe8, 0x00, + 0x00, 0x84, 0x09, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, + 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, + 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, + 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, + 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, + 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, + 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, + 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0xcc, 0x4a, + 0xb5, 0xb4, 0x38, 0xcd, 0xad, 0xb7, 0xe1, 0xa7, 0xdf, 0x9a, 0x54, 0xb9, + 0xf1, 0x72, 0x1a, 0x7c, 0xfc, 0x37, 0x7e, 0xe6, 0x9e, 0xe8, 0x65, 0x8a, + 0x1f, 0x05, 0x53, 0xf2, 0x03, 0xe7, 0x5e, 0x09, 0x3e, 0x79, 0x11, 0x3c, + 0xfb, 0x30, 0xf9, 0x82, 0xe9, 0x74, 0x3a, 0xcb, 0xbd, 0x49, 0xf0, 0xd5, + 0xbe, 0x1d, 0x7c, 0xf8, 0x5d, 0xcb, 0xe3, 0xe8, 0x65, 0xb6, 0xb7, 0xcb, + 0xe4, 0x6b, 0x26, 0xf8, 0x6a, 0xef, 0x76, 0x9b, 0xe8, 0x65, 0x9a, 0xa6, + 0x08, 0x8e, 0x4f, 0x83, 0x97, 0xa9, 0x16, 0xeb, 0xdc, 0x78, 0x9d, 0x3c, + 0x4b, 0x5a, 0xf4, 0xff, 0xb4, 0x9e, 0x66, 0x7f, 0x26, 0x68, 0xea, 0xe0, + 0xc3, 0xfb, 0x85, 0x03, 0x00, 0x88, 0x13, 0x1c, 0x00, 0x80, 0xe0, 0x00, + 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, + 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, + 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, + 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, + 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, + 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x98, 0x95, 0xaa, 0x6d, 0x8b, 0xdc, 0x7a, 0xaf, 0x6a, 0xa2, + 0x4f, 0x3f, 0x9c, 0x06, 0x83, 0xe9, 0xed, 0x87, 0x0f, 0xe5, 0xc6, 0xef, + 0x3d, 0x79, 0x25, 0x7a, 0x99, 0xa7, 0xdf, 0x3c, 0x9f, 0x1b, 0x6f, 0x06, + 0xc5, 0x9c, 0xbe, 0xdc, 0x9b, 0x36, 0xbb, 0x3f, 0xa9, 0x83, 0x2f, 0xc8, + 0x6e, 0x19, 0x7c, 0x37, 0x4d, 0xa6, 0xd9, 0xbf, 0x3d, 0xba, 0x55, 0x9d, + 0x9c, 0x0f, 0xbe, 0x20, 0xc7, 0xe3, 0x32, 0xfb, 0x9a, 0x6c, 0x82, 0x0f, + 0xbf, 0xbd, 0x1d, 0x7c, 0xf8, 0xa2, 0x17, 0x3c, 0xcb, 0xea, 0x60, 0x34, + 0xc7, 0x2f, 0xc8, 0xe4, 0x07, 0x64, 0xf4, 0x2b, 0xbb, 0xd3, 0xe9, 0x14, + 0xc9, 0x79, 0xbf, 0x70, 0x00, 0x00, 0x71, 0x82, 0x03, 0x00, 0x10, 0x1c, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, + 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, + 0x1c, 0x00, 0x00, 0xb3, 0x52, 0x15, 0x45, 0x70, 0xbd, 0x68, 0xdb, 0xe8, + 0xd3, 0xdf, 0xea, 0xf5, 0x72, 0xe3, 0x4b, 0x2f, 0x5e, 0xc9, 0x8d, 0xdf, + 0xfe, 0xc5, 0xf7, 0x64, 0xff, 0x63, 0xdf, 0x3a, 0x9b, 0xdb, 0x5e, 0x9f, + 0x56, 0xb9, 0xf1, 0xbd, 0xdd, 0x26, 0x37, 0x3e, 0x6d, 0xb2, 0x85, 0x3d, + 0x1c, 0x07, 0xdf, 0x4e, 0x75, 0x59, 0xe7, 0xc6, 0x9b, 0xb6, 0x88, 0x5e, + 0x66, 0x39, 0xfa, 0x67, 0xd3, 0x42, 0xf0, 0x73, 0xa6, 0xae, 0xb3, 0x97, + 0xd9, 0xdc, 0xee, 0xe6, 0xc6, 0xff, 0x60, 0xfb, 0x68, 0x6e, 0xfc, 0x93, + 0xe3, 0xf3, 0xb9, 0xf1, 0x7e, 0x39, 0x8d, 0x9e, 0x7d, 0x34, 0x2a, 0x83, + 0x5f, 0xab, 0x55, 0x33, 0xa7, 0xaf, 0xf6, 0x4e, 0xa7, 0x53, 0x55, 0xc1, + 0x7d, 0xbf, 0x70, 0x00, 0x00, 0x71, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, + 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, + 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, + 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, + 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, + 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, + 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, + 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, + 0x00, 0x00, 0xb3, 0x52, 0x45, 0xd7, 0xdb, 0x4e, 0x11, 0xdd, 0xbf, 0xb7, + 0xdd, 0xca, 0x8d, 0xf7, 0x7a, 0xd3, 0xdc, 0xf8, 0x9f, 0x9e, 0xb9, 0x15, + 0xbd, 0xcc, 0x46, 0x5d, 0xe6, 0xc6, 0x57, 0x16, 0x82, 0x2f, 0x9b, 0xcd, + 0xba, 0xc9, 0x8d, 0xd7, 0xe1, 0x17, 0xe4, 0x9e, 0xde, 0x28, 0x37, 0x3e, + 0x69, 0x82, 0x7f, 0x1e, 0x4c, 0x46, 0xd9, 0xbf, 0x3d, 0xd6, 0x87, 0x8b, + 0xb9, 0xf1, 0x22, 0xf9, 0xbf, 0x5a, 0x15, 0x4d, 0xf4, 0x32, 0x6d, 0x72, + 0xfc, 0x91, 0x8d, 0xe0, 0xe7, 0xcc, 0x1b, 0xfb, 0xd7, 0x72, 0xe3, 0x6b, + 0xc3, 0x71, 0xf4, 0xec, 0x3b, 0x06, 0xc1, 0xfd, 0xba, 0x5e, 0x48, 0x8e, + 0x47, 0x5f, 0x32, 0x9d, 0xf1, 0x38, 0xf8, 0x76, 0xf2, 0x0b, 0x07, 0x00, + 0x10, 0x27, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, + 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, + 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, + 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, + 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, + 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x30, 0x2b, 0x55, + 0xa7, 0xd3, 0xe6, 0xd6, 0x27, 0x75, 0x36, 0x68, 0xba, 0x0b, 0x4d, 0x6e, + 0x7c, 0x47, 0x55, 0xe7, 0xc6, 0x3f, 0x7e, 0xee, 0x9d, 0xe8, 0x65, 0xbe, + 0xfb, 0xf0, 0xa1, 0xdc, 0x78, 0x3d, 0x0d, 0x5e, 0xe6, 0xd7, 0xde, 0x3a, + 0x9b, 0x3c, 0x4c, 0x1b, 0x3d, 0xfb, 0xb0, 0x2e, 0x73, 0xe3, 0x2b, 0xd5, + 0x34, 0x37, 0x3e, 0x6d, 0x8a, 0xe8, 0x65, 0x5e, 0x9a, 0xee, 0xcc, 0x8d, + 0xef, 0x5b, 0x18, 0xe7, 0xc6, 0xf7, 0x2e, 0x8c, 0xa2, 0x97, 0xb9, 0x5c, + 0xf7, 0x73, 0xe3, 0x27, 0x97, 0x57, 0x73, 0xe3, 0xb7, 0x46, 0x8b, 0xc1, + 0x57, 0x7b, 0x67, 0x3b, 0x7a, 0xf6, 0x47, 0xcb, 0x9b, 0xb9, 0xf1, 0xc5, + 0x2a, 0xf8, 0xc5, 0xd4, 0x29, 0xb2, 0x6f, 0xd5, 0xf1, 0x34, 0xf8, 0xad, + 0xed, 0x17, 0x0e, 0x00, 0x20, 0x4e, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, + 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, + 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, + 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, + 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, + 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, + 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x60, 0x56, 0xaa, 0xb6, 0x2d, 0x72, 0xeb, 0xa3, 0x69, 0x19, 0x7e, + 0xfe, 0x36, 0x37, 0x5d, 0x26, 0xc7, 0xef, 0x6b, 0xef, 0x44, 0xef, 0xb2, + 0xf4, 0xfa, 0xf9, 0xdc, 0xf8, 0x37, 0x0e, 0x1f, 0xca, 0x8d, 0x7f, 0xf1, + 0xc0, 0xbd, 0xb9, 0xf1, 0x5b, 0x1f, 0xd8, 0x1f, 0x3d, 0xfb, 0x3f, 0xfa, + 0xca, 0x73, 0xb9, 0xf1, 0xa6, 0x4d, 0x3e, 0x7a, 0x91, 0x7d, 0xa3, 0x16, + 0x4d, 0x70, 0xfc, 0xf7, 0x1f, 0x3d, 0x9e, 0x1b, 0xff, 0xcc, 0x0b, 0x6f, + 0x46, 0x2f, 0x73, 0xb2, 0x5d, 0xc9, 0x8d, 0x7f, 0xfd, 0x9f, 0x7d, 0x24, + 0x37, 0xfe, 0x2f, 0xfe, 0xcd, 0x97, 0x72, 0xe3, 0x77, 0x2d, 0x6d, 0x47, + 0xcf, 0x7e, 0x6b, 0x6b, 0x31, 0x37, 0x3e, 0x58, 0x9c, 0xce, 0xef, 0x7b, + 0xb5, 0x28, 0x82, 0x1f, 0x34, 0x7e, 0xe1, 0x00, 0x00, 0xe2, 0x04, 0x07, + 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, + 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, + 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, + 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, + 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, + 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x66, 0xa5, 0xda, 0x1a, 0x57, 0xc1, + 0x9c, 0x29, 0xda, 0xe8, 0xd3, 0xb7, 0x6d, 0x30, 0x98, 0xb6, 0x9b, 0x32, + 0x37, 0xde, 0x2f, 0xea, 0xe8, 0x65, 0x16, 0x17, 0x9a, 0xdc, 0xf8, 0x63, + 0x17, 0xae, 0xe5, 0xc6, 0xbf, 0xf6, 0xe4, 0xb1, 0xdc, 0xf8, 0x87, 0x5e, + 0xbe, 0x11, 0x3d, 0xfb, 0x46, 0xd1, 0x0d, 0xbe, 0x57, 0x9b, 0xe0, 0xbb, + 0x69, 0xda, 0x16, 0xd1, 0xcb, 0x4c, 0x3a, 0xc1, 0xfd, 0xeb, 0x47, 0xf7, + 0xe7, 0xc6, 0x7f, 0xf8, 0xca, 0xf5, 0xe8, 0x65, 0x5e, 0xfe, 0xc8, 0x7d, + 0xb9, 0xf1, 0xf7, 0xfc, 0xde, 0xf7, 0x72, 0xe3, 0xa7, 0x06, 0x6b, 0xb9, + 0xf1, 0x87, 0xda, 0x8d, 0xe8, 0xd9, 0x9b, 0xe4, 0x0b, 0xfe, 0xf6, 0x68, + 0x31, 0xf8, 0xd9, 0x5e, 0x65, 0xbf, 0x3b, 0xaa, 0x85, 0xe0, 0xe7, 0x8c, + 0x5f, 0x38, 0x00, 0x80, 0x38, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, + 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, + 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, + 0x80, 0x59, 0xa9, 0xea, 0xa6, 0xc8, 0xad, 0xb7, 0xe1, 0xa7, 0xbf, 0x53, + 0x57, 0xb9, 0xf1, 0x69, 0x1b, 0xbc, 0x4c, 0x11, 0xbe, 0x4c, 0x13, 0xfd, + 0x17, 0x92, 0xdb, 0xbd, 0x83, 0xcb, 0xb9, 0xf1, 0xcd, 0x93, 0x97, 0xa2, + 0x67, 0x3f, 0x53, 0x0d, 0x72, 0xe3, 0xdf, 0x1b, 0xec, 0xcd, 0x8d, 0x1f, + 0xb9, 0x7d, 0x3b, 0x7a, 0x99, 0x36, 0xf9, 0xa2, 0x19, 0x9c, 0xbd, 0x99, + 0x1b, 0xff, 0xe2, 0xa7, 0x1e, 0x8d, 0x5e, 0x66, 0x6d, 0x58, 0xe7, 0xc6, + 0x3f, 0xb6, 0x71, 0x2b, 0x37, 0x7e, 0xb8, 0x1a, 0xe6, 0xc6, 0x37, 0xba, + 0xdd, 0xe8, 0xd9, 0x77, 0x74, 0xa7, 0x73, 0xfa, 0x9d, 0x3d, 0x1e, 0x65, + 0x2f, 0x33, 0x4e, 0x26, 0x81, 0x5f, 0x38, 0x00, 0x80, 0x38, 0xc1, 0x01, + 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, + 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, + 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x80, 0x59, 0xa9, 0xce, 0xdf, 0x19, 0xe4, + 0xd6, 0x6f, 0x15, 0xdd, 0xe8, 0xd3, 0xef, 0xe8, 0x4c, 0xe7, 0xb4, 0xc5, + 0x86, 0x4d, 0x36, 0xf5, 0x7e, 0xb4, 0x77, 0x6f, 0x6e, 0x7c, 0xf3, 0x76, + 0x93, 0x1b, 0x1f, 0x7c, 0xfb, 0x42, 0x6e, 0xfc, 0xf9, 0x7f, 0xf9, 0x54, + 0xf4, 0xec, 0x4b, 0x7f, 0xf8, 0x7a, 0xf0, 0x35, 0xf3, 0xeb, 0x47, 0x73, + 0xe3, 0xed, 0xbf, 0x7d, 0x3e, 0x7a, 0x99, 0x3b, 0x55, 0x99, 0x1b, 0xbf, + 0xb1, 0x63, 0x31, 0x37, 0xfe, 0xd4, 0xff, 0x38, 0x15, 0xbd, 0xcc, 0xe1, + 0xd1, 0x30, 0x37, 0xde, 0x2f, 0x82, 0x6f, 0xd5, 0xb2, 0x68, 0x83, 0x1f, + 0x32, 0x75, 0x15, 0x3d, 0x7b, 0x9b, 0x1c, 0x8f, 0x5e, 0xa6, 0x08, 0x37, + 0xc1, 0xe6, 0x34, 0xf8, 0xad, 0xed, 0x17, 0x0e, 0x00, 0x20, 0x4e, 0x70, + 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, + 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, + 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, + 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, + 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x60, 0x56, 0xaa, 0xff, 0x78, 0xff, + 0xf1, 0xdc, 0xfa, 0xee, 0x8d, 0xed, 0xe8, 0xd3, 0x3f, 0x75, 0xf5, 0xca, + 0x9c, 0xde, 0x7d, 0xa3, 0xed, 0x46, 0xf7, 0x9b, 0xdb, 0xd3, 0xdc, 0xf8, + 0x5f, 0x7d, 0xfa, 0x27, 0x72, 0xe3, 0xe5, 0xe9, 0xf5, 0xdc, 0xf8, 0xd3, + 0xbf, 0xf2, 0x70, 0xf4, 0xec, 0x5f, 0xea, 0x17, 0xc1, 0xff, 0xd3, 0x2f, + 0x9c, 0xcd, 0x8d, 0x5f, 0x38, 0xba, 0x16, 0xbd, 0xcc, 0xad, 0xaa, 0xcc, + 0x8d, 0xef, 0x39, 0xb3, 0x91, 0x1b, 0x5f, 0xee, 0x34, 0xd1, 0xcb, 0x2c, + 0x15, 0x75, 0x6e, 0xbc, 0x6d, 0x93, 0x1f, 0x32, 0xc9, 0xf1, 0x4e, 0x11, + 0xbd, 0x7a, 0x67, 0x73, 0x1a, 0xfc, 0x04, 0x8e, 0x1e, 0x66, 0xd4, 0x94, + 0xd1, 0xcb, 0x7c, 0x6b, 0xed, 0xee, 0xdc, 0xb8, 0x5f, 0x38, 0x00, 0x80, + 0x38, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, + 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, + 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, + 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, + 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x80, 0x59, 0xa9, 0xce, + 0xff, 0xca, 0xc3, 0xb9, 0xf5, 0xf6, 0x6b, 0x6f, 0x45, 0x9f, 0xfe, 0x95, + 0x77, 0x87, 0xb9, 0xf1, 0x03, 0xd3, 0xed, 0xdc, 0xf8, 0xb0, 0x28, 0xa3, + 0x97, 0xb9, 0x74, 0x60, 0x67, 0xf0, 0x45, 0xb3, 0xb6, 0x98, 0x1b, 0x5f, + 0xfe, 0x07, 0x27, 0x72, 0xe3, 0x07, 0x07, 0x4b, 0xd1, 0xb3, 0x7f, 0xe6, + 0x63, 0x8f, 0xe4, 0xc6, 0xbf, 0xd4, 0xab, 0x72, 0xe3, 0x6f, 0x9d, 0xdb, + 0x8c, 0x5e, 0xe6, 0xf0, 0x72, 0xf0, 0xf2, 0xe7, 0x9e, 0xbd, 0x94, 0x1b, + 0x3f, 0xfe, 0xf5, 0xf5, 0xe8, 0x65, 0xc6, 0x45, 0xf0, 0xaf, 0xbe, 0xcd, + 0x36, 0xf8, 0x9a, 0xd9, 0xd1, 0x04, 0xc7, 0xab, 0xa2, 0x9d, 0xdf, 0xaf, + 0xd5, 0xad, 0x26, 0xf8, 0xf1, 0xfe, 0x4a, 0x77, 0x25, 0xfa, 0xf0, 0xaf, + 0x1d, 0xd9, 0x97, 0x1b, 0xf7, 0x0b, 0x07, 0x00, 0x10, 0x27, 0x38, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, + 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, + 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, + 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, + 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x30, 0x2b, 0xd5, 0x3f, 0xfc, 0xdd, 0x6f, + 0xe6, 0xd6, 0x5f, 0xea, 0xad, 0x44, 0x9f, 0xfe, 0x4f, 0x7f, 0xe3, 0xfd, + 0xb9, 0xf1, 0x8f, 0xff, 0xe7, 0x93, 0xb9, 0xf1, 0x51, 0x95, 0x4d, 0xbd, + 0x95, 0x4b, 0xb7, 0x73, 0xe3, 0x4b, 0xcf, 0x5f, 0xcf, 0x8d, 0x5f, 0xde, + 0xdb, 0x9b, 0xdf, 0xbe, 0x3e, 0xd0, 0x5b, 0xca, 0x8d, 0x7f, 0xf2, 0x17, + 0x4f, 0xe4, 0xc6, 0xbf, 0xf1, 0xdc, 0xd9, 0xe8, 0x65, 0xce, 0x9d, 0xbe, + 0x99, 0x1b, 0xdf, 0xfd, 0xc6, 0x46, 0x6e, 0xfc, 0xc2, 0xca, 0x20, 0x7a, + 0x99, 0x1f, 0x1c, 0xda, 0x9f, 0x1b, 0xff, 0xd0, 0x0b, 0x97, 0x72, 0xe3, + 0xef, 0xf4, 0x83, 0x97, 0x79, 0x64, 0xb8, 0x1e, 0x3d, 0x7b, 0x99, 0x1c, + 0xaf, 0xdb, 0xe0, 0xf8, 0x1b, 0x07, 0xf6, 0x44, 0x2f, 0xf3, 0xc1, 0x1f, + 0x9c, 0x99, 0xdf, 0x4f, 0x60, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, + 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, + 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, + 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, + 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, + 0x0e, 0x00, 0x80, 0x99, 0xa9, 0xf6, 0xb5, 0xa3, 0xdc, 0x7a, 0xd1, 0x5b, + 0x8d, 0x3e, 0xfd, 0xc6, 0xfa, 0x76, 0x6e, 0xfc, 0xd5, 0x3d, 0xbb, 0x72, + 0xe3, 0xbd, 0xed, 0x69, 0xf4, 0x32, 0xa7, 0x3f, 0x79, 0x22, 0x37, 0xbe, + 0x79, 0x6e, 0x23, 0x37, 0xfe, 0xd8, 0xcf, 0x1e, 0xce, 0x8d, 0x2f, 0x86, + 0x0b, 0xbb, 0xe9, 0xb4, 0xb9, 0xf1, 0x7d, 0x65, 0x3f, 0x37, 0xfe, 0x5b, + 0x1f, 0x7a, 0x28, 0x7a, 0x99, 0xff, 0x30, 0x7e, 0x39, 0x37, 0xde, 0xfd, + 0xad, 0xe0, 0xc3, 0xbf, 0xf5, 0x85, 0xd3, 0xd1, 0xcb, 0xf4, 0x3e, 0x76, + 0x24, 0x37, 0xfe, 0xcd, 0xbf, 0x73, 0x28, 0x37, 0x7e, 0xe2, 0xf3, 0xaf, + 0x04, 0x5f, 0xed, 0xc3, 0xed, 0xe8, 0xd9, 0xfb, 0x9d, 0x26, 0x37, 0x7e, + 0x6d, 0x65, 0x29, 0x37, 0x7e, 0x76, 0xcf, 0x8e, 0xe8, 0x65, 0x9e, 0x78, + 0xfb, 0x4a, 0x6e, 0xdc, 0x2f, 0x1c, 0x00, 0x40, 0x9c, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, + 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, + 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, + 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, + 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, + 0x00, 0x04, 0x07, 0x00, 0xc0, 0xac, 0x54, 0xff, 0xeb, 0xd8, 0xa1, 0xdc, + 0xfa, 0x33, 0x4f, 0xdc, 0x17, 0x7d, 0xfa, 0xf7, 0x3e, 0x73, 0x31, 0x37, + 0xfe, 0xec, 0x2f, 0xdf, 0x9f, 0x1b, 0xdf, 0xb9, 0x3e, 0x89, 0x5e, 0x66, + 0x74, 0xf7, 0x52, 0x6e, 0xbc, 0xfb, 0xe8, 0x6a, 0x6e, 0xfc, 0x89, 0xfd, + 0xbb, 0x73, 0xe3, 0x6d, 0xf8, 0xed, 0x54, 0x14, 0xc5, 0x9c, 0x7e, 0x10, + 0xd4, 0xe1, 0xdb, 0x7c, 0xe2, 0xa7, 0x1f, 0xc8, 0x8d, 0xff, 0xfb, 0x2f, + 0xbf, 0x10, 0xbc, 0xcc, 0x53, 0xfb, 0xa2, 0x97, 0x59, 0x1b, 0x4f, 0x73, + 0xe3, 0xfd, 0xef, 0x04, 0x3f, 0x21, 0x77, 0x0e, 0x83, 0x1f, 0x62, 0x57, + 0xba, 0xfd, 0xec, 0x9f, 0xda, 0x75, 0x93, 0x1b, 0xff, 0xce, 0xe3, 0x47, + 0x72, 0xe3, 0x07, 0x27, 0x4d, 0xf4, 0x32, 0xbd, 0xb2, 0x0e, 0x9e, 0x5d, + 0x73, 0x01, 0x00, 0x69, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, + 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, + 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, + 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, + 0xb3, 0x52, 0x8d, 0xde, 0x9d, 0xe6, 0xd6, 0x3f, 0xfb, 0xdf, 0x4e, 0x46, + 0x9f, 0x7e, 0xbd, 0xec, 0xe6, 0xc6, 0x57, 0x3e, 0xbf, 0x95, 0x1b, 0xbf, + 0xb8, 0x3a, 0x88, 0x5e, 0xe6, 0xe2, 0x3b, 0xb7, 0x83, 0x67, 0xff, 0xf9, + 0x83, 0xc1, 0xb3, 0x57, 0x5d, 0x6f, 0xcb, 0xbf, 0x7d, 0x56, 0x17, 0x82, + 0xff, 0xad, 0x7f, 0xff, 0xef, 0x3e, 0x92, 0x1b, 0x3f, 0x75, 0xe5, 0x56, + 0xf4, 0x32, 0x2f, 0xfc, 0xde, 0x8f, 0x72, 0xe3, 0xdd, 0xed, 0xe0, 0xc7, + 0xfb, 0xd5, 0x41, 0x3f, 0x37, 0xfe, 0xd6, 0xa3, 0xfb, 0xa3, 0x67, 0xbf, + 0xfc, 0xd0, 0x6a, 0x6e, 0xfc, 0xc4, 0x76, 0xf0, 0xc9, 0x9f, 0xfc, 0xfc, + 0xf7, 0xa3, 0x97, 0xb9, 0xbb, 0x1c, 0xe5, 0xc6, 0xfd, 0xc2, 0x01, 0x00, + 0xc4, 0x09, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, + 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, + 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, + 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0xcc, 0x4a, 0xf5, + 0xb1, 0x8d, 0x8b, 0xb9, 0xf5, 0xf5, 0xa2, 0x9b, 0xcd, 0xa5, 0x3a, 0x38, + 0x7e, 0xbb, 0xa8, 0x72, 0xe3, 0xd7, 0x9a, 0x36, 0x7b, 0x99, 0xbd, 0x4b, + 0xb9, 0xf1, 0xfb, 0x7e, 0xe9, 0xde, 0xdc, 0xf8, 0xb0, 0x0d, 0xfe, 0xa7, + 0xf6, 0x8b, 0xd2, 0x7b, 0xfe, 0xff, 0xd2, 0x5f, 0x36, 0x45, 0x6e, 0xfc, + 0x68, 0x77, 0x90, 0x1b, 0x6f, 0xd6, 0xea, 0xe8, 0x65, 0x4e, 0xfd, 0xdc, + 0xdd, 0xb9, 0xf1, 0x9d, 0x9f, 0x3a, 0x96, 0x1b, 0x3f, 0xfd, 0xaf, 0x9f, + 0xcf, 0x8d, 0x2f, 0xed, 0x5c, 0x8c, 0x9e, 0xfd, 0x27, 0xff, 0xeb, 0xeb, + 0xc1, 0xcb, 0xfc, 0xc2, 0x7d, 0xb9, 0xf1, 0x1f, 0x1e, 0xb8, 0x2b, 0x7a, + 0x99, 0x7b, 0xde, 0x1d, 0x27, 0x3f, 0x07, 0x00, 0x00, 0xe2, 0x7f, 0x78, + 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, + 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, + 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, + 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, + 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, + 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, + 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x80, 0xd9, 0xa8, 0x96, 0xcb, 0x3a, + 0xb7, 0xbe, 0xd8, 0x36, 0xd1, 0xa7, 0xbf, 0x5e, 0xf7, 0x72, 0xe3, 0xdf, + 0xf8, 0xb9, 0x63, 0xb9, 0xf1, 0x41, 0xaf, 0x8c, 0x5e, 0x66, 0xb4, 0x39, + 0xc9, 0x8d, 0x9f, 0xfd, 0xf6, 0xc5, 0xdc, 0xf8, 0xf0, 0x37, 0xf6, 0xe5, + 0xc6, 0xd7, 0x04, 0xf6, 0xdf, 0x46, 0x6d, 0x72, 0xfc, 0xd8, 0xf2, 0x4a, + 0xf4, 0xe1, 0x7f, 0xfb, 0xe9, 0xf7, 0xe6, 0xc6, 0xff, 0xf8, 0xaf, 0xde, + 0xcc, 0x8d, 0x17, 0x9f, 0x38, 0x9a, 0x1b, 0xdf, 0xf5, 0x27, 0x6f, 0x47, + 0xcf, 0x7e, 0xcf, 0x78, 0x3b, 0x37, 0xfe, 0xe8, 0x57, 0x5e, 0xc8, 0x8d, + 0xaf, 0xd6, 0x93, 0xe8, 0x65, 0xca, 0x41, 0xf0, 0x5b, 0xdb, 0x07, 0x30, + 0x00, 0x10, 0x27, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, + 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, + 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, + 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x30, 0x2b, + 0x55, 0x51, 0xb4, 0xb9, 0xf5, 0xb6, 0x2d, 0xc2, 0x4f, 0xdf, 0xe4, 0xc6, + 0x7f, 0xea, 0x99, 0x73, 0xb9, 0xf1, 0x67, 0xfe, 0xc9, 0xe3, 0xd1, 0xcb, + 0x14, 0x7b, 0x7a, 0xb9, 0xf1, 0x9f, 0xfc, 0xa9, 0x7b, 0x72, 0xe3, 0x87, + 0xba, 0x4b, 0xb9, 0xf1, 0xc6, 0x3b, 0x9e, 0xbf, 0xe9, 0x87, 0x58, 0x78, + 0xbf, 0x9f, 0xfc, 0x90, 0xfc, 0x7b, 0x4f, 0x1e, 0xcf, 0x8d, 0xff, 0x97, + 0xe1, 0x2b, 0xc1, 0x4f, 0xb0, 0x4b, 0xc3, 0xec, 0x77, 0x47, 0x37, 0xf8, + 0x1f, 0xbb, 0x77, 0x34, 0xce, 0x8d, 0xdf, 0xd5, 0x1d, 0x45, 0x2f, 0x73, + 0x57, 0x27, 0xb8, 0xef, 0x17, 0x0e, 0x00, 0x20, 0x4e, 0x70, 0x00, 0x00, + 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, + 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x60, 0x56, 0xaa, 0xba, 0x2d, 0x72, 0xeb, 0x37, + 0xeb, 0xc5, 0xe8, 0xd3, 0x17, 0x6d, 0x70, 0xbc, 0x57, 0x06, 0xd7, 0x77, + 0x7d, 0xf5, 0x4c, 0xf4, 0x32, 0xe7, 0xde, 0xbf, 0x37, 0xf8, 0xa2, 0xf9, + 0xe8, 0xe1, 0xdc, 0x78, 0xe3, 0x4d, 0xc9, 0xff, 0x57, 0x8a, 0xe0, 0x27, + 0xf0, 0x42, 0x27, 0x38, 0xde, 0xdf, 0x11, 0xfc, 0x78, 0xbf, 0xf0, 0x99, + 0x13, 0xd1, 0xab, 0x5f, 0xff, 0xdc, 0x0f, 0x73, 0xe3, 0xf7, 0x97, 0xc3, + 0xdc, 0xf8, 0x60, 0x3c, 0x8d, 0x5e, 0xa6, 0x4d, 0x7e, 0xab, 0xfa, 0x85, + 0x03, 0x00, 0x88, 0x13, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, + 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, + 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, + 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x98, + 0x95, 0xea, 0xe4, 0xc2, 0x5a, 0x6e, 0xbd, 0x0e, 0x3f, 0x7d, 0x5d, 0x14, + 0xb9, 0xf1, 0x72, 0xd2, 0xe4, 0xc6, 0x07, 0xeb, 0xa3, 0xe8, 0x65, 0xee, + 0x7b, 0xfa, 0x48, 0x6e, 0xfc, 0xee, 0x5e, 0xdf, 0x3b, 0x07, 0xfe, 0xdf, + 0x77, 0x7a, 0x6b, 0x33, 0x37, 0x7e, 0xee, 0x5b, 0xe7, 0x73, 0xe3, 0x3b, + 0xbf, 0x75, 0x29, 0x7a, 0x99, 0x33, 0xc7, 0x56, 0x73, 0xe3, 0x1f, 0x7c, + 0xf6, 0x6a, 0x6e, 0xbc, 0x5d, 0x2c, 0xa2, 0x97, 0x99, 0xb6, 0xc1, 0x7d, + 0xbf, 0x70, 0x00, 0x00, 0x71, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, + 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, + 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, + 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, + 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, + 0x00, 0xb3, 0x52, 0x2d, 0x26, 0x93, 0xe3, 0x8f, 0x3e, 0x70, 0x7f, 0xf4, + 0xe9, 0xef, 0x7b, 0xf9, 0x7a, 0x6e, 0x7c, 0x7d, 0xb0, 0x98, 0x1b, 0xbf, + 0xf1, 0x8f, 0xdf, 0x1b, 0xbd, 0x4c, 0x77, 0xd2, 0xe4, 0xc6, 0x7f, 0x62, + 0xe7, 0x6a, 0x6e, 0xbc, 0xee, 0xb4, 0xde, 0x96, 0xf8, 0x9b, 0x6f, 0x26, + 0x9e, 0x7b, 0xed, 0x4a, 0x6e, 0xbc, 0xd9, 0x9c, 0xe4, 0xc6, 0xef, 0xb9, + 0x7c, 0x3b, 0x7a, 0xf6, 0xe3, 0xeb, 0xc1, 0xfd, 0xad, 0xb2, 0xca, 0x8d, + 0x5f, 0xae, 0xfb, 0xd1, 0xcb, 0x94, 0x75, 0x3b, 0xa7, 0xaf, 0x76, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, + 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, + 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, + 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, + 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x80, 0x59, 0xaa, 0x7a, + 0xb7, 0x27, 0xc1, 0xf9, 0x6e, 0x11, 0x7d, 0xfa, 0x57, 0x7f, 0xe1, 0x68, + 0x6e, 0xbc, 0x9c, 0x36, 0xc1, 0xd0, 0xfb, 0xc3, 0x53, 0xd1, 0xcb, 0xdc, + 0xfb, 0xef, 0x3e, 0x9c, 0x1b, 0x6f, 0x3b, 0xed, 0x9c, 0x8e, 0x17, 0x9d, + 0xc2, 0x7b, 0x9e, 0xbf, 0xd9, 0x0b, 0xb2, 0x6d, 0xa3, 0xfb, 0x0b, 0x45, + 0xf0, 0xaf, 0xbe, 0xad, 0xeb, 0x5b, 0xb9, 0xf1, 0x7a, 0x6d, 0x31, 0x37, + 0x7e, 0xfa, 0xfd, 0xfb, 0xa2, 0x67, 0xbf, 0x75, 0x6d, 0x39, 0xf8, 0xdd, + 0xf1, 0xe2, 0xa5, 0xdc, 0xf8, 0x0b, 0xab, 0xab, 0xd9, 0x17, 0x64, 0x1d, + 0x7c, 0xc1, 0xfb, 0x85, 0x03, 0x00, 0x88, 0x13, 0x1c, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, + 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, + 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, + 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, + 0xe0, 0x00, 0x00, 0x98, 0x95, 0xea, 0xbf, 0x3f, 0x7e, 0x2c, 0xb7, 0x7e, + 0xfc, 0xc0, 0xae, 0xe8, 0xd3, 0xef, 0xff, 0xe2, 0x8b, 0xb9, 0xf1, 0xe1, + 0x42, 0x99, 0x1b, 0x7f, 0x73, 0x6d, 0x25, 0x7a, 0x99, 0x1f, 0xfe, 0xfe, + 0xcb, 0xb9, 0xf1, 0xde, 0x67, 0x8b, 0xe0, 0x6b, 0xe6, 0xc1, 0xbd, 0xb9, + 0xf1, 0x03, 0x65, 0x2f, 0xfb, 0x7e, 0x2a, 0x8a, 0x0e, 0x3f, 0xf6, 0x30, + 0xd9, 0x3f, 0x9b, 0x82, 0xf3, 0x9b, 0x45, 0x1d, 0xbd, 0xcc, 0x17, 0x9f, + 0x3d, 0x9d, 0x1b, 0x1f, 0x7f, 0xf5, 0x6c, 0x6e, 0xfc, 0xe8, 0x38, 0x78, + 0x99, 0x3d, 0xcf, 0x5e, 0x8a, 0x9e, 0xfd, 0xd2, 0x4f, 0x1f, 0xca, 0x8d, + 0xff, 0xc5, 0xfe, 0xe0, 0xc7, 0xfb, 0x91, 0xcb, 0x9b, 0xd1, 0xcb, 0x7c, + 0xe2, 0xf4, 0xeb, 0xc9, 0xb7, 0x2a, 0x00, 0x40, 0x98, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, + 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, + 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, + 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, + 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, + 0x00, 0x04, 0x07, 0x00, 0xc0, 0xac, 0x54, 0xbb, 0x6f, 0x0c, 0x73, 0xeb, + 0x4f, 0xfc, 0xe0, 0xaf, 0xb3, 0xb9, 0x94, 0xec, 0xa5, 0xab, 0x4d, 0x2f, + 0x37, 0x7e, 0xfa, 0xe7, 0xef, 0x8d, 0x5e, 0xa6, 0xb8, 0xab, 0x9f, 0x1b, + 0x7f, 0xe7, 0x2f, 0x2f, 0xe4, 0xc6, 0x5f, 0x7b, 0xe9, 0x6a, 0x6e, 0xfc, + 0xb3, 0x9f, 0x7a, 0x5f, 0xf4, 0xec, 0x2b, 0x73, 0x5b, 0xf0, 0xb7, 0xda, + 0x49, 0x74, 0xff, 0xad, 0x9b, 0x9b, 0xb9, 0xf1, 0x57, 0x2f, 0xbc, 0x9b, + 0x1b, 0x3f, 0xf3, 0xfd, 0xcb, 0xd1, 0xcb, 0xdc, 0x73, 0x70, 0x25, 0x37, + 0x3e, 0x78, 0xf1, 0x46, 0x6e, 0xfc, 0xe1, 0x4b, 0x37, 0x73, 0xe3, 0x3b, + 0xea, 0x69, 0xf4, 0xec, 0xcb, 0xa7, 0x82, 0x97, 0xb9, 0xb1, 0xdc, 0xcd, + 0x8d, 0xff, 0xec, 0x8f, 0x4e, 0x47, 0x2f, 0xb3, 0xa7, 0xda, 0x0e, 0x7e, + 0x65, 0x6b, 0x2e, 0x00, 0x20, 0x4d, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, + 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, + 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, + 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, + 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, + 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, + 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x60, 0x56, 0xaa, 0xfb, 0x97, 0xa7, 0xb9, 0xf5, 0xdd, 0xe5, 0x24, + 0xfa, 0xf4, 0x8b, 0x0b, 0x6d, 0x6e, 0xbc, 0x08, 0x6e, 0x77, 0x7e, 0xf9, + 0x8f, 0x5e, 0x8a, 0x5e, 0xe6, 0xd4, 0x89, 0xbb, 0x72, 0xe3, 0xd3, 0x1b, + 0xe3, 0xdc, 0xf8, 0xa5, 0xdf, 0x3c, 0x91, 0x1b, 0xff, 0xdd, 0xcf, 0x7d, + 0x37, 0x7a, 0xf6, 0xbb, 0x56, 0x97, 0x82, 0x2f, 0xc8, 0x2a, 0xf8, 0xe7, + 0xc1, 0xf5, 0x73, 0x1b, 0xd1, 0xcb, 0x0c, 0xf6, 0x0f, 0x72, 0xe3, 0xe3, + 0xe7, 0xae, 0x05, 0xff, 0x4f, 0xdf, 0xc8, 0x5e, 0xe6, 0xc2, 0x53, 0xfb, + 0x72, 0xe3, 0x0f, 0x1c, 0x0c, 0xbe, 0x20, 0x0f, 0x9e, 0xbb, 0x94, 0x1b, + 0xef, 0x37, 0x4d, 0xf4, 0xec, 0xcd, 0x1b, 0x57, 0x73, 0xe3, 0x6f, 0x7c, + 0xf4, 0x81, 0xdc, 0xf8, 0xf3, 0x7b, 0xf6, 0x44, 0x2f, 0xb3, 0xb9, 0x51, + 0xe5, 0xc6, 0xfd, 0xc2, 0x01, 0x00, 0xc4, 0x09, 0x0e, 0x00, 0x40, 0x70, + 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, + 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, + 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, + 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, + 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, + 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, + 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, + 0x70, 0x00, 0x00, 0xcc, 0x4a, 0xf5, 0xc1, 0x53, 0xe7, 0x73, 0xeb, 0x2b, + 0xd5, 0x34, 0xfa, 0xf4, 0x45, 0xd1, 0xe6, 0xc6, 0x97, 0x9a, 0xe0, 0xc3, + 0x17, 0x75, 0xf6, 0xff, 0x75, 0xd7, 0x6b, 0xc1, 0x87, 0x3f, 0xb3, 0xb4, + 0x9c, 0x1b, 0x7f, 0xf5, 0xf2, 0x30, 0x37, 0xfe, 0xe0, 0x77, 0x2f, 0x45, + 0xcf, 0xfe, 0xee, 0xf1, 0xd5, 0xe0, 0x7b, 0xf5, 0xee, 0x1d, 0xb9, 0xf1, + 0xe3, 0x7f, 0x71, 0x3e, 0x7a, 0x99, 0x1b, 0x9f, 0x7e, 0x30, 0xf8, 0x6a, + 0x3f, 0xb5, 0x9e, 0x1b, 0x3f, 0x7c, 0x61, 0x3d, 0x7a, 0x99, 0x95, 0x5d, + 0x65, 0x6e, 0x7c, 0x79, 0x63, 0x9c, 0x1b, 0xdf, 0x51, 0x07, 0x3f, 0x64, + 0x56, 0x3a, 0xd9, 0xef, 0x8e, 0xdd, 0xc5, 0x28, 0x37, 0xbe, 0xf6, 0xe7, + 0xa7, 0x72, 0xe3, 0x5f, 0xfb, 0xe7, 0x1f, 0x89, 0x5e, 0x66, 0xf2, 0x07, + 0x2f, 0xe4, 0xc6, 0xfd, 0xc2, 0x01, 0x00, 0xc4, 0x09, 0x0e, 0x00, 0x40, + 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, + 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, + 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, + 0x40, 0x70, 0x00, 0x00, 0xcc, 0x4a, 0x75, 0xef, 0xd2, 0x56, 0x6e, 0xbd, + 0x69, 0x8b, 0xe8, 0xd3, 0x0f, 0x9b, 0x32, 0xf8, 0xf0, 0x45, 0x9b, 0x1b, + 0x1f, 0x14, 0x75, 0x36, 0x24, 0xeb, 0xe0, 0xc3, 0x6f, 0x17, 0xc1, 0xff, + 0xd6, 0xbd, 0xc9, 0xf1, 0x63, 0x57, 0x37, 0xa3, 0x67, 0xbf, 0xf6, 0xe1, + 0x83, 0xb9, 0xf1, 0x23, 0xff, 0xf3, 0xed, 0xdc, 0xf8, 0xfd, 0x57, 0x6f, + 0x47, 0x2f, 0x73, 0xe5, 0x73, 0x2f, 0xe4, 0xc6, 0x5f, 0xfa, 0xd5, 0x07, + 0x73, 0xe3, 0xbb, 0x4f, 0x5f, 0x8b, 0x5e, 0xe6, 0x3d, 0xcf, 0xbc, 0x95, + 0x1b, 0xef, 0xb7, 0xc1, 0xcf, 0x99, 0xa3, 0x0b, 0x77, 0x82, 0xdf, 0x4c, + 0xc9, 0x8f, 0xdf, 0x4e, 0xa7, 0x33, 0x49, 0x7e, 0x37, 0xbd, 0xb1, 0xb2, + 0x33, 0x37, 0xfe, 0x81, 0xff, 0xf4, 0x7c, 0xf4, 0x32, 0x9b, 0xfb, 0x83, + 0x0f, 0xef, 0x17, 0x0e, 0x00, 0x20, 0x4e, 0x70, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, + 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, + 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, + 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, + 0x03, 0x00, 0x60, 0x56, 0xaa, 0x41, 0x55, 0xe7, 0xd6, 0xcb, 0xa2, 0x8d, + 0x3e, 0x7d, 0xbf, 0x0e, 0x3e, 0xfc, 0xe5, 0xed, 0x7e, 0x6e, 0x7c, 0xab, + 0x29, 0xa3, 0x97, 0xf9, 0xf2, 0x47, 0x1f, 0xca, 0x8d, 0x6f, 0x27, 0x9f, + 0xfc, 0x91, 0x2f, 0x9c, 0xca, 0x8d, 0x3f, 0x38, 0xdc, 0x8c, 0x9e, 0x7d, + 0xd7, 0x57, 0x5f, 0xcd, 0x8d, 0x1f, 0xb9, 0x11, 0x7c, 0xf8, 0x61, 0x91, + 0xfd, 0xdb, 0xa3, 0x6e, 0x8b, 0xdc, 0xf8, 0x9d, 0x2a, 0xf8, 0xe4, 0x3b, + 0x27, 0xd3, 0xe8, 0x65, 0x76, 0x36, 0x93, 0xdc, 0xf8, 0xfe, 0xce, 0x28, + 0x37, 0x1e, 0xfd, 0xee, 0xe8, 0x64, 0xbf, 0x3a, 0x3a, 0x83, 0x85, 0x26, + 0x37, 0xfe, 0xf4, 0xf0, 0x62, 0xf0, 0xad, 0x34, 0x2c, 0xa2, 0x97, 0x79, + 0xa9, 0xda, 0x97, 0x1b, 0xf7, 0x0b, 0x07, 0x00, 0x10, 0x27, 0x38, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, + 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, + 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, + 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, + 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x30, 0x2b, 0xd5, 0xce, 0xfe, 0x38, 0xb7, + 0x7e, 0x67, 0xd4, 0x8d, 0x3e, 0xfd, 0x52, 0x55, 0xe7, 0xc6, 0x6f, 0x2d, + 0xf5, 0x73, 0xe3, 0x5f, 0x7e, 0xec, 0x44, 0xf4, 0x32, 0xfb, 0xaf, 0x6d, + 0xe4, 0xc6, 0x1f, 0x78, 0xfb, 0x46, 0x6e, 0xfc, 0xb5, 0x87, 0xf7, 0xe5, + 0xc6, 0xef, 0x7e, 0xfe, 0x7a, 0xf4, 0xec, 0x8f, 0xdd, 0x5a, 0xcf, 0x8d, + 0x8f, 0x17, 0x82, 0x7f, 0x1e, 0x5c, 0x6f, 0x7a, 0xd1, 0xcb, 0x7c, 0xe5, + 0xe3, 0x8f, 0xe6, 0xc6, 0x0f, 0x0d, 0x83, 0x4f, 0x7e, 0x75, 0xd7, 0x52, + 0xf4, 0x32, 0xc7, 0x6f, 0x6c, 0xe6, 0xc6, 0xcb, 0xb6, 0xcd, 0x8d, 0x17, + 0x9d, 0xe0, 0x78, 0xb5, 0xd0, 0x46, 0xcf, 0xbe, 0xda, 0x9d, 0x24, 0xbf, + 0x98, 0xa6, 0xf3, 0xdb, 0x04, 0x6b, 0xeb, 0xef, 0xe4, 0xc6, 0xfd, 0xc2, + 0x01, 0x00, 0xc4, 0x09, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, + 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0xcc, + 0x4a, 0xb5, 0x58, 0x35, 0xb9, 0xf5, 0x72, 0x61, 0x12, 0x7d, 0xfa, 0x8d, + 0x61, 0x37, 0x37, 0xbe, 0xe3, 0xf6, 0x28, 0x78, 0x99, 0xb5, 0xe5, 0xe8, + 0x65, 0x1e, 0x7f, 0xf5, 0x9d, 0xdc, 0xf8, 0x89, 0xad, 0x9b, 0xb9, 0xf1, + 0xcd, 0x9b, 0x2b, 0xb9, 0xf1, 0x9d, 0x45, 0xf6, 0x05, 0xd9, 0x2d, 0xda, + 0xe4, 0x78, 0x1d, 0x3c, 0x7b, 0xdb, 0x44, 0x2f, 0xf3, 0xc0, 0x5f, 0x07, + 0x5f, 0x90, 0x6b, 0x1b, 0xdb, 0xb9, 0xf1, 0xbf, 0x7c, 0xe2, 0x70, 0xf6, + 0xad, 0xfa, 0xed, 0xeb, 0xb9, 0xf1, 0xd5, 0xe4, 0x0b, 0xb2, 0x69, 0x8b, + 0xdc, 0xf8, 0x52, 0x39, 0x8d, 0x9e, 0x7d, 0xb1, 0x0c, 0xbe, 0x9b, 0xda, + 0xe4, 0x65, 0xaa, 0x32, 0xfb, 0x56, 0x3d, 0xb0, 0xbc, 0x95, 0x1b, 0xf7, + 0x0b, 0x07, 0x00, 0x10, 0x27, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, + 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, + 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, + 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, + 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, + 0x30, 0x2b, 0xd5, 0x72, 0x7f, 0x32, 0xbf, 0x4f, 0x3f, 0xaa, 0x83, 0xc1, + 0xf4, 0xfd, 0xfe, 0x9e, 0xdc, 0xf8, 0xe3, 0xcf, 0xbd, 0x1e, 0xbd, 0xcc, + 0x93, 0x93, 0x2b, 0xb9, 0xf1, 0xdd, 0xfd, 0x71, 0x6e, 0xbc, 0x3e, 0x77, + 0x2e, 0x37, 0xbe, 0x5a, 0x8d, 0xa3, 0x67, 0x5f, 0xeb, 0x06, 0xdf, 0x4d, + 0xe5, 0x42, 0x9b, 0x1b, 0x5f, 0x9a, 0xd4, 0xd1, 0xcb, 0x7c, 0xfa, 0xca, + 0x99, 0xdc, 0xf8, 0x7a, 0xa7, 0x9b, 0x1b, 0xdf, 0xb8, 0xb1, 0x1a, 0xbd, + 0xcc, 0xb7, 0xdf, 0x77, 0x5f, 0x6e, 0xfc, 0xa9, 0x53, 0x17, 0x83, 0xef, + 0xa6, 0xc9, 0x8d, 0xdc, 0x78, 0x31, 0xcf, 0x7f, 0x6a, 0x57, 0x65, 0x13, + 0x7c, 0xab, 0x76, 0xb3, 0x6f, 0xd5, 0xa5, 0xc5, 0xe9, 0x9c, 0x9e, 0x1d, + 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, + 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, + 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x60, 0x96, 0xaa, + 0x85, 0x64, 0x72, 0xd4, 0x75, 0x11, 0x7d, 0xfa, 0x3d, 0x3b, 0xb6, 0x73, + 0xe3, 0xbf, 0x5e, 0x5e, 0xca, 0x8d, 0x3f, 0x7b, 0x69, 0x25, 0x7a, 0x99, + 0xa3, 0xbb, 0xef, 0x24, 0x5f, 0x34, 0x4d, 0x6e, 0xfc, 0x83, 0x83, 0x49, + 0xf0, 0x2e, 0x93, 0xec, 0xdb, 0xa9, 0x6e, 0x83, 0x2f, 0xf8, 0xa2, 0x68, + 0x73, 0xe3, 0x77, 0x95, 0x75, 0xf8, 0x2f, 0x9b, 0x5e, 0x6e, 0xbc, 0xd7, + 0x04, 0x5f, 0x90, 0xbf, 0xf4, 0xca, 0xe9, 0xe8, 0x65, 0x2e, 0x8e, 0x16, + 0x73, 0xe3, 0x5f, 0xfb, 0xd5, 0xc7, 0x72, 0xe3, 0x77, 0x7f, 0xf3, 0x64, + 0x6e, 0x7c, 0x35, 0xfd, 0x5e, 0x4d, 0x5a, 0xea, 0x06, 0xdf, 0x4d, 0x0b, + 0xc9, 0xcf, 0x81, 0xf4, 0xe7, 0x8c, 0x5f, 0x38, 0x00, 0x80, 0x38, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, + 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, + 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, + 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, + 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, + 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, + 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x80, 0x59, 0xa9, 0x96, 0x96, 0x26, + 0xb9, 0xf5, 0xba, 0xce, 0x06, 0xcd, 0x74, 0x5a, 0xe4, 0xc6, 0x77, 0x6c, + 0x6d, 0xe7, 0xc6, 0x77, 0x1f, 0x59, 0x89, 0x5e, 0x66, 0xb5, 0x1e, 0xe5, + 0xc6, 0xfb, 0x8b, 0x75, 0x6e, 0xbc, 0x28, 0xda, 0xe0, 0x0b, 0x26, 0xfc, + 0x82, 0xdc, 0x1a, 0x55, 0xb9, 0xf1, 0xe1, 0x38, 0x38, 0x3e, 0x6d, 0xb2, + 0x97, 0xe9, 0x97, 0x75, 0x67, 0x3e, 0x6d, 0x2d, 0x64, 0x9f, 0x7c, 0xb5, + 0x9b, 0x7c, 0x37, 0xed, 0xe9, 0x07, 0xbf, 0x3c, 0x26, 0xc1, 0x27, 0x9f, + 0x2e, 0x14, 0xd9, 0x17, 0x64, 0x77, 0x5e, 0x3f, 0xc4, 0x16, 0x16, 0xda, + 0xce, 0xdc, 0xf2, 0x0b, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, + 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, + 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, + 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, + 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, + 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, + 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x30, 0x37, 0xaa, 0xb2, 0xdb, 0xe4, 0xd6, 0xbb, 0xfd, 0x3a, + 0xfa, 0xf4, 0x6d, 0x53, 0xe4, 0xc6, 0x8f, 0x0d, 0xd6, 0x73, 0xe3, 0x87, + 0x46, 0xb7, 0xa3, 0x97, 0x99, 0x4c, 0xca, 0xdc, 0x78, 0x5d, 0x17, 0x73, + 0xfb, 0x72, 0x6f, 0xa2, 0xfb, 0x8b, 0xdd, 0xe8, 0xfe, 0x34, 0x37, 0x3d, + 0x1c, 0x57, 0xd1, 0xcb, 0xf4, 0xca, 0xe0, 0x6b, 0xa6, 0x6e, 0x82, 0x7f, + 0x38, 0x75, 0x8b, 0x36, 0x7a, 0x99, 0x69, 0x11, 0x7c, 0xf8, 0x5e, 0x27, + 0xf8, 0x39, 0xf0, 0xf5, 0x23, 0x87, 0x73, 0xe3, 0x4f, 0x5e, 0xbd, 0x1a, + 0x3d, 0xfb, 0xbd, 0xc5, 0x9d, 0xe4, 0x7c, 0xf4, 0x13, 0x32, 0xfb, 0x82, + 0x8c, 0xf2, 0x0b, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, + 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, + 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, + 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, + 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, + 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, + 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x30, 0x37, 0xaa, 0xee, 0x62, 0x93, 0x5b, 0x2f, 0x16, 0xda, 0xe8, + 0xd3, 0xb7, 0xc9, 0xf9, 0xb6, 0x29, 0x72, 0xe3, 0xe5, 0x62, 0x1d, 0xbd, + 0xcc, 0x78, 0x58, 0xe5, 0xc6, 0x9b, 0xe4, 0x65, 0xc6, 0xe3, 0x32, 0x37, + 0x3e, 0x9d, 0x66, 0x0b, 0xbb, 0x57, 0x05, 0xff, 0x5b, 0x47, 0xc9, 0xcb, + 0x2c, 0x2d, 0x4e, 0xa3, 0x97, 0x99, 0x26, 0x5f, 0x33, 0xd1, 0x4f, 0x99, + 0xa2, 0xc9, 0x7e, 0x88, 0x9d, 0xdc, 0xb5, 0x96, 0x1b, 0x1f, 0x7c, 0xf3, + 0x74, 0x6e, 0xfc, 0x23, 0x17, 0x2f, 0xe6, 0xc6, 0x4f, 0xf4, 0x6e, 0x67, + 0xbf, 0x3b, 0x3a, 0xc9, 0x17, 0x64, 0x9b, 0x7d, 0xcd, 0xcc, 0x2f, 0xbf, + 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, + 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, + 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, + 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, + 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x73, + 0xa3, 0xea, 0x2d, 0x4f, 0x72, 0xeb, 0x45, 0xd1, 0xce, 0xef, 0x69, 0x9a, + 0xba, 0xc8, 0x8d, 0x8f, 0x87, 0x55, 0xf4, 0xe1, 0x7b, 0x83, 0x69, 0x6e, + 0x7c, 0xfb, 0x4e, 0x37, 0x37, 0xde, 0xef, 0x07, 0x9f, 0x7c, 0x32, 0x29, + 0xa3, 0x67, 0x1f, 0x8d, 0xca, 0xb9, 0x7d, 0xbd, 0x17, 0xd1, 0xf5, 0xb6, + 0x0d, 0xee, 0x4f, 0x93, 0xe3, 0x1b, 0x9d, 0x6e, 0xf4, 0x32, 0xe7, 0x1f, + 0xda, 0x13, 0x1c, 0x1f, 0x2c, 0xe5, 0xc6, 0x7f, 0xed, 0xe6, 0x85, 0xe0, + 0x37, 0x53, 0xf8, 0xbb, 0x63, 0x52, 0x07, 0xff, 0xd8, 0xae, 0xca, 0x69, + 0x87, 0x1f, 0xc7, 0x2f, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, + 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, + 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, + 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, + 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, + 0x1c, 0x00, 0xc0, 0xdc, 0xa8, 0x8a, 0x22, 0xba, 0x5f, 0xcc, 0xef, 0x69, + 0x8a, 0x64, 0x8c, 0xf5, 0x06, 0xd3, 0xe8, 0xc3, 0x6f, 0xdf, 0xe9, 0xe6, + 0xc6, 0x17, 0xfb, 0x75, 0x6e, 0x7c, 0x32, 0x0a, 0xde, 0xbd, 0xdb, 0xad, + 0xa3, 0x67, 0xaf, 0xeb, 0xf9, 0x7d, 0xc1, 0xb7, 0xd1, 0xf5, 0xab, 0xe3, + 0x7e, 0x6e, 0xfc, 0xdd, 0x49, 0xf0, 0xd5, 0x7e, 0xae, 0x5c, 0x8a, 0x5e, + 0x66, 0xdf, 0xeb, 0xb7, 0x72, 0xe3, 0xef, 0xbf, 0x73, 0x31, 0x37, 0xbe, + 0xd2, 0x04, 0x3f, 0xc4, 0x8a, 0x2a, 0xfb, 0x82, 0x1c, 0x4d, 0xcb, 0xe0, + 0xe7, 0x4c, 0xd9, 0x24, 0xbf, 0x53, 0x9b, 0xce, 0xdc, 0xf2, 0x0b, 0x07, + 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, + 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, + 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, + 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, + 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, + 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, + 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x30, 0x37, 0x2a, + 0x27, 0xf8, 0x3f, 0x29, 0x8a, 0xe8, 0x7a, 0x1b, 0x7d, 0xf8, 0xb2, 0xdb, + 0xcc, 0xe9, 0x2c, 0x96, 0xde, 0xcd, 0x00, 0x00, 0x01, 0x91, 0x49, 0x44, + 0x41, 0x54, 0xd9, 0xdb, 0xb6, 0x9c, 0xdf, 0xd7, 0x4c, 0xaf, 0x57, 0x07, + 0x5f, 0x32, 0x9d, 0xe0, 0x6b, 0xe6, 0xd6, 0x56, 0x2f, 0x7a, 0x99, 0xf3, + 0xa3, 0xa5, 0xdc, 0xf8, 0xb3, 0x83, 0xb5, 0xdc, 0xf8, 0xa5, 0x13, 0xfb, + 0xa3, 0x97, 0x39, 0x7b, 0x78, 0x67, 0x6e, 0x7c, 0xf9, 0xcf, 0xde, 0xcc, + 0x8d, 0x0f, 0x87, 0xc1, 0xbf, 0x57, 0xb7, 0x9b, 0xec, 0xe7, 0x40, 0xb7, + 0x09, 0x7e, 0x42, 0x6e, 0x8d, 0x83, 0x5f, 0xac, 0xcb, 0xbd, 0x49, 0xfa, + 0xab, 0x2f, 0x37, 0xed, 0x17, 0x0e, 0x00, 0x20, 0x4e, 0x70, 0x00, 0x00, + 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, + 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, + 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, + 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, + 0x00, 0x82, 0x03, 0x00, 0x60, 0x56, 0xaa, 0xb6, 0x0d, 0xae, 0x17, 0x85, + 0x0b, 0xff, 0x78, 0x6d, 0x9b, 0x3d, 0x4d, 0xb5, 0x58, 0xe7, 0xc6, 0xeb, + 0x49, 0xb0, 0x53, 0x17, 0xfb, 0xd3, 0xdc, 0xf8, 0x64, 0x54, 0x85, 0xff, + 0x5b, 0x83, 0xe3, 0x2f, 0x6e, 0xac, 0xe6, 0xc6, 0x5f, 0xee, 0xad, 0x46, + 0x2f, 0xf3, 0x6e, 0xb7, 0x9b, 0x1b, 0x7f, 0xf6, 0x9f, 0xfe, 0x4c, 0x6e, + 0xfc, 0x37, 0xff, 0xd5, 0xd7, 0xa3, 0x97, 0x19, 0x3e, 0x1f, 0x1c, 0xff, + 0xd6, 0x93, 0x27, 0x72, 0xe3, 0xd7, 0xbe, 0xb7, 0x11, 0x7c, 0x2b, 0x4d, + 0xa3, 0x57, 0xef, 0xdc, 0x99, 0x96, 0xb9, 0xf1, 0xe5, 0xb5, 0xe0, 0xc7, + 0xfb, 0x78, 0x38, 0x8c, 0x5e, 0x66, 0xc7, 0xd2, 0x24, 0x37, 0xee, 0x17, + 0x0e, 0x00, 0x20, 0x4e, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, + 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, + 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, + 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, + 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, + 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, + 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, + 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, + 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x60, + 0x56, 0xfe, 0x37, 0x78, 0x5d, 0xa8, 0x59, 0xa3, 0x1a, 0x66, 0x14, 0x00, + 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; + +static const unsigned int sEncodedBufferImageDataPNGLength = sizeof( sEncodedBufferImageDataPNG ); + +} // anonymous namespace + + +int UtcDaliEncodedBufferImageCtorsP(void) +{ + TestApplication application; + + EncodedBufferImage image1; + DALI_TEST_CHECK( !image1 ); + + image1 = EncodedBufferImage::New( sEncodedBufferImageDataPNG, sEncodedBufferImageDataPNGLength, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::DEFAULT, Image::NEVER ); + EncodedBufferImage image2( image1 ); + + DALI_TEST_EQUALS( image1, image2, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliEncodedBufferImageOperatorAssignmentP(void) +{ + TestApplication application; + + EncodedBufferImage image1; + DALI_TEST_CHECK( !image1 ); + + image1 = EncodedBufferImage::New( sEncodedBufferImageDataPNG, sEncodedBufferImageDataPNGLength, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::DEFAULT, Image::NEVER ); + EncodedBufferImage image2; + image2 = image1; + + DALI_TEST_EQUALS( image1, image2, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliEncodedBufferImageDownCastP(void) +{ + TestApplication application; + + Image image1 = EncodedBufferImage::New( sEncodedBufferImageDataPNG, sEncodedBufferImageDataPNGLength, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::DEFAULT, Image::NEVER ); + EncodedBufferImage image2 = DownCast< EncodedBufferImage >(image1); + + DALI_TEST_EQUALS( image1, image2, TEST_LOCATION ); + END_TEST; +} + +// Positive test case for constructors: +int UtcDaliEncodedBufferImageNew01(void) +{ + TestApplication application; + + tet_infoline( "UtcDaliEncodedBufferImageNew01() - EncodedBufferImage::New( const uint8_t * const encodedImage, const std::size_t encodedImageByteCount, ImageDimensions size, FittingMode::Type scalingMode, SamplingMode::Type samplingMode, ReleasePolicy releasePol, bool orientationCorrection )" ); + + // Invoke default handle constructor for the Image base class: + Image image; + + DALI_TEST_CHECK( !image ); + + // Trigger image decode to initialise the handle + image = EncodedBufferImage::New( sEncodedBufferImageDataPNG, sEncodedBufferImageDataPNGLength, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::DEFAULT, Image::NEVER ); + + DALI_TEST_CHECK( image ); + + // Change the release policy to Unused: + Image image2; + + DALI_TEST_CHECK( !image2 ); + + // Trigger image decode to initialise the handle + image2 = EncodedBufferImage::New( sEncodedBufferImageDataPNG, sEncodedBufferImageDataPNGLength, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::DEFAULT, Image::UNUSED ); + + DALI_TEST_CHECK( image2 ); + END_TEST; +} + +// Negative test case for constructor - null pointer: +int UtcDaliEncodedBufferImageNew02(void) +{ + TestApplication application; + + tet_infoline( "UtcDaliEncodedBufferImageNew02() - EncodedBufferImage::New( const uint8_t * const encodedImage, const std::size_t encodedImageByteCount )" ); + + // Invoke default handle constructor for the Image base class: + Image image; + + DALI_TEST_CHECK( !image ); + + // Trigger image decode to initialise the handle + try + { + // This should throw on the null pointer: + image = EncodedBufferImage::New( 0, sEncodedBufferImageDataPNGLength ); + tet_result( TET_FAIL ); + } + catch (Dali::DaliException& e) + { + // Tests that a negative test of an assertion succeeds + DALI_TEST_PRINT_ASSERT( e ); + } + END_TEST; +} + +// Negative test case for constructor - zero-length input buffer: +int UtcDaliEncodedBufferImageNew03(void) +{ + TestApplication application; + + tet_infoline( "UtcDaliEncodedBufferImageNew03() - EncodedBufferImage::New( const uint8_t * const encodedImage, const std::size_t encodedImageByteCount )" ); + + // Invoke default handle constructor for the Image base class: + Image image; + + DALI_TEST_CHECK( !image ); + + // Trigger image decode to initialise the handle + try + { + // This should throw on the zero size: + image = EncodedBufferImage::New( sEncodedBufferImageDataPNG, /** Trigger the assertion.*/ 0 ); + tet_result( TET_FAIL ); + } + catch (Dali::DaliException& e) + { + // Tests that a negative test of an assertion succeeds + DALI_TEST_PRINT_ASSERT( e ); + } + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-FrameBufferImage.cpp b/automated-tests/src/dali/utc-Dali-FrameBufferImage.cpp new file mode 100644 index 0000000..31c4939 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-FrameBufferImage.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +using std::max; +using namespace Dali; + +void utc_dali_framebuffer_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_framebuffer_cleanup(void) +{ + test_return_value = TET_PASS; +} + +static const float ROTATION_EPSILON = 0.0001f; + + +int UtcDaliFrameBufferImageNew01(void) +{ + TestApplication application; + + tet_infoline("UtcDaliFrameBufferImageNew01 - FrameBufferImage::New(unsigned int, unsigned int, Pixel::Format)"); + + // invoke default handle constructor + FrameBufferImage image; + Vector2 stageSize = Stage::GetCurrent().GetSize(); + + // initialise handle + image = FrameBufferImage::New(); // create framebuffer with the same dimensions as the stage + ImageActor actor=ImageActor::New(image); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + DALI_TEST_CHECK( image ); + DALI_TEST_EQUALS((float)image.GetWidth(), stageSize.width, TEST_LOCATION); + DALI_TEST_EQUALS((float)image.GetHeight(), stageSize.height, TEST_LOCATION); + + image = FrameBufferImage::New(16, 16); // create framebuffer with dimensions of 16x16 + actor.SetImage(image); + + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + DALI_TEST_CHECK( image ); + DALI_TEST_EQUALS(image.GetWidth(), 16u, TEST_LOCATION); + DALI_TEST_EQUALS(image.GetHeight(), 16u, TEST_LOCATION); + END_TEST; +} + +int UtcDaliFrameBufferImageNew02(void) +{ + TestApplication application; + + tet_infoline("UtcDaliFrameBufferImageNew02 - FrameBufferImage::New(NativeImageInterface&)"); + + // invoke default handle constructor + FrameBufferImage image; + TestNativeImagePointer nativeImage = TestNativeImage::New(16, 16); + + DALI_TEST_CHECK( !image ); + + // initialise handle + image = FrameBufferImage::New(*(nativeImage.Get())); + + DALI_TEST_CHECK( image ); + END_TEST; +} + +int UtcDaliFrameBufferImageNew03(void) +{ + TestApplication application; + + tet_infoline("UtcDaliFrameBufferImageNew03 - FrameBufferImage::New(NativeImageInterface&, ReleasePolicy)"); + + // invoke default handle constructor + FrameBufferImage image; + TestNativeImagePointer nativeImage = TestNativeImage::New(16, 16); + + DALI_TEST_CHECK( !image ); + + // initialise handle with UNUSED release policy + image = FrameBufferImage::New(*(nativeImage.Get()), Image::UNUSED); + + DALI_TEST_CHECK( image ); + DALI_TEST_EQUALS( image.GetReleasePolicy(), Image::UNUSED, TEST_LOCATION ); + + // initialise handle with NEVER release policy + image.Reset(); + DALI_TEST_CHECK( !image ); + + image = FrameBufferImage::New(*(nativeImage.Get()), Image::NEVER); + + DALI_TEST_CHECK( image ); + DALI_TEST_EQUALS( image.GetReleasePolicy(), Image::NEVER, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliFrameBufferImageAttachments01(void) +{ + TestApplication application; + + tet_infoline("UtcDaliFrameBufferImageAttachments01 - FrameBufferImage::New(unsigned int, unsigned int, Pixel::Format, RenderBuffer::Format)"); + + // invoke default handle constructor + FrameBufferImage image; + + // initialise handle + image = FrameBufferImage::New(64, 64, Pixel::RGBA8888, RenderBuffer::COLOR); // create framebuffer with Color buffer + ImageActor actor=ImageActor::New(image); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferColorAttachment(), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferDepthAttachment(), false, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferStencilAttachment(), false, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliFrameBufferImageAttachments02(void) +{ + TestApplication application; + + tet_infoline("UtcDaliFrameBufferImageAttachments02 - FrameBufferImage::New(unsigned int, unsigned int, Pixel::Format, RenderBuffer::Format)"); + + // invoke default handle constructor + FrameBufferImage image; + + // initialise handle + image = FrameBufferImage::New(64, 64, Pixel::RGBA8888, RenderBuffer::COLOR_DEPTH); // create framebuffer with Color and Depth buffer + ImageActor actor=ImageActor::New(image); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferColorAttachment(), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferDepthAttachment(), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferStencilAttachment(), false, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliFrameBufferImageAttachments03(void) +{ + TestApplication application; + + tet_infoline("UtcDaliFrameBufferImageAttachments03 - FrameBufferImage::New(unsigned int, unsigned int, Pixel::Format, RenderBuffer::Format)"); + + // invoke default handle constructor + FrameBufferImage image; + + // initialise handle + image = FrameBufferImage::New(64, 64, Pixel::RGBA8888, RenderBuffer::COLOR_STENCIL); // create framebuffer with Color and Stencil + ImageActor actor=ImageActor::New(image); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferColorAttachment(), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferDepthAttachment(), false, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferStencilAttachment(), true, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliFrameBufferImageAttachments04(void) +{ + TestApplication application; + + tet_infoline("UtcDaliFrameBufferImageAttachments04 - FrameBufferImage::New(unsigned int, unsigned int, Pixel::Format, RenderBuffer::Format)"); + + // invoke default handle constructor + FrameBufferImage image; + + // initialise handle + image = FrameBufferImage::New(64, 64, Pixel::RGBA8888, RenderBuffer::COLOR_DEPTH_STENCIL); // create framebuffer with Color, Depth and Stencil buffers + ImageActor actor=ImageActor::New(image); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferColorAttachment(), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferDepthAttachment(), true, TEST_LOCATION); + DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferStencilAttachment(), true, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliFrameBufferImageDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::FrameBufferImage::DownCast()"); + + FrameBufferImage image = FrameBufferImage::New(); + + BaseHandle object(image); + + FrameBufferImage image2 = FrameBufferImage::DownCast(object); + DALI_TEST_CHECK(image2); + + FrameBufferImage image3 = DownCast< FrameBufferImage >(object); + DALI_TEST_CHECK(image3); + + BaseHandle unInitializedObject; + FrameBufferImage image4 = FrameBufferImage::DownCast(unInitializedObject); + DALI_TEST_CHECK(!image4); + + FrameBufferImage image5 = DownCast< FrameBufferImage >(unInitializedObject); + DALI_TEST_CHECK(!image5); + + Image image6 = FrameBufferImage::New(); + FrameBufferImage image7 = FrameBufferImage::DownCast(image6); + DALI_TEST_CHECK(image7); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Gesture.cpp b/automated-tests/src/dali/utc-Dali-Gesture.cpp new file mode 100644 index 0000000..ccd31a6 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Gesture.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_gesture_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_gesture_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +// TestGesture Struct (Gesture constructor is protected) +struct TestGesture : public Gesture +{ +public: + TestGesture(Gesture::Type type, Gesture::State state) + : Gesture(type, state) {} + + virtual ~TestGesture() {} +}; + +} // anon namespace + +int UtcDaliGestureConstructor(void) +{ + TestApplication application; // Reset all test adapter return codes + + TestGesture pan(Gesture::Pan, Gesture::Started); + DALI_TEST_EQUALS(Gesture::Pan, pan.type, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, pan.state, TEST_LOCATION); + + TestGesture pinch(Gesture::Pinch, Gesture::Clear); + DALI_TEST_EQUALS(Gesture::Pinch, pinch.type, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Clear, pinch.state, TEST_LOCATION); + + // Test copy constructor + TestGesture pan2(pan); + DALI_TEST_EQUALS(Gesture::Pan, pan2.type, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, pan2.state, TEST_LOCATION); + END_TEST; +} + +int UtcDaliGestureAssignment(void) +{ + // Test Assignment operator + TestGesture pan(Gesture::Pan, Gesture::Finished); + DALI_TEST_EQUALS(Gesture::Pan, pan.type, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Finished, pan.state, TEST_LOCATION); + + TestGesture test(Gesture::Pinch, Gesture::Started); + DALI_TEST_EQUALS(Gesture::Pinch, test.type, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, test.state, TEST_LOCATION); + + test = pan; + DALI_TEST_EQUALS(Gesture::Pan, test.type, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Finished, test.state, TEST_LOCATION); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-GestureDetector.cpp b/automated-tests/src/dali/utc-Dali-GestureDetector.cpp new file mode 100644 index 0000000..12a41c4 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-GestureDetector.cpp @@ -0,0 +1,439 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include + +using namespace Dali; + +void utc_dali_gesture_detector_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_gesture_detector_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +int UtcDaliGestureDetectorConstructorN(void) +{ + TestApplication application; + + GestureDetector detector; + + Actor actor = Actor::New(); + + try + { + detector.Attach(actor); + tet_result(TET_FAIL); + } + catch (DaliException& e) + { + DALI_TEST_ASSERT( e, "detector", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliGestureDetectorConstructorP(void) +{ + TestApplication application; + + // Use pan gesture as GestureDetector cannot be created. + GestureDetector detector = PanGestureDetector::New(); + + Actor actor = Actor::New(); + + try + { + detector.Attach(actor); + tet_result(TET_PASS); + } + catch (DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + tet_result(TET_FAIL); + } + END_TEST; +} + +int UtcDaliGestureDetectorAssignP(void) +{ + TestApplication application; + + // Use pan gesture as GestureDetector cannot be created. + GestureDetector detector = PanGestureDetector::New(); + GestureDetector detector2; + + detector2 = detector; + + Actor actor = Actor::New(); + + try + { + detector2.Attach(actor); + tet_result(TET_PASS); + } + catch (DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + tet_result(TET_FAIL); + } + END_TEST; +} + +int UtcDaliGestureDetectorDownCastP(void) +{ + TestApplication application; + tet_infoline("Testing Dali::GestureDetector::DownCast()"); + + GestureDetector detector = PanGestureDetector::New(); + + BaseHandle object(detector); + + GestureDetector detector2 = GestureDetector::DownCast(object); + DALI_TEST_CHECK(detector2); + + GestureDetector detector3 = DownCast< GestureDetector >(object); + DALI_TEST_CHECK(detector3); + + BaseHandle unInitializedObject; + GestureDetector detector4 = GestureDetector::DownCast(unInitializedObject); + DALI_TEST_CHECK(!detector4); + + GestureDetector detector5 = DownCast< GestureDetector >(unInitializedObject); + DALI_TEST_CHECK(!detector5); + END_TEST; +} + +int UtcDaliGestureDetectorAttachP(void) +{ + TestApplication application; + + // Use pan gesture as GestureDetector cannot be created. + GestureDetector detector = PanGestureDetector::New(); + + Actor actor = Actor::New(); + + detector.Attach(actor); + + bool found = false; + for(size_t i = 0; i < detector.GetAttachedActorCount(); i++) + { + if( detector.GetAttachedActor(i) == actor ) + { + tet_result(TET_PASS); + found = true; + } + } + + if(!found) + { + tet_result(TET_FAIL); + } + + // Scoped gesture detector. GestureDetectors connect to a destroy signal of the actor. If the + // actor is still alive when the gesture detector is destroyed, then it should disconnect from + // this signal. If it does not, then when this function ends, there will be a segmentation fault + // thus, a TET case failure. + { + GestureDetector detector2 = PanGestureDetector::New(); + detector2.Attach(actor); + } + END_TEST; +} + +int UtcDaliGestureDetectorAttachN(void) +{ + TestApplication application; + + // Use pan gesture as GestureDetector cannot be created. + GestureDetector detector = PanGestureDetector::New(); + + // Do not initialise actor + Actor actor; + + try + { + detector.Attach(actor); + tet_result(TET_FAIL); + } + catch (DaliException& e) + { + DALI_TEST_ASSERT( e, "actor", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliGestureDetectorDetachP(void) +{ + TestApplication application; + + // Use pan gesture as GestureDetector cannot be created. + GestureDetector detector = PanGestureDetector::New(); + + Actor actor = Actor::New(); + detector.Attach(actor); + + bool found = false; + for(size_t i = 0; i < detector.GetAttachedActorCount(); i++) + { + if( detector.GetAttachedActor(i) == actor ) + { + tet_result(TET_PASS); + found = true; + } + } + + if(!found) + { + tet_result(TET_FAIL); + } + + // Detach and retrieve attached actors again, the vector should be empty. + detector.Detach(actor); + + found = false; + for(size_t i = 0; i < detector.GetAttachedActorCount(); i++) + { + if( detector.GetAttachedActor(i) == actor ) + { + found = true; + } + } + + if(found) + { + tet_result(TET_FAIL); + } + else + { + tet_result(TET_PASS); + } + + END_TEST; +} + +int UtcDaliGestureDetectorDetachN01(void) +{ + TestApplication application; + + // Use pan gesture as GestureDetector cannot be created. + GestureDetector detector = PanGestureDetector::New(); + + // Do not initialise actor + Actor actor; + + try + { + detector.Detach(actor); + tet_result(TET_FAIL); + } + catch (DaliException& e) + { + DALI_TEST_ASSERT( e, "actor", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliGestureDetectorDetachN02(void) +{ + TestApplication application; + + // Use pan gesture as GestureDetector cannot be created. + GestureDetector detector = PanGestureDetector::New(); + + Actor actor = Actor::New(); + detector.Attach(actor); + + // Detach an actor that hasn't been attached. This should not cause an exception, it's a no-op. + try + { + Actor actor2 = Actor::New(); + detector.Detach(actor2); + tet_result(TET_PASS); + } + catch (DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + tet_result(TET_FAIL); + } + END_TEST; +} + +int UtcDaliGestureDetectorDetachN03(void) +{ + TestApplication application; + TestGestureManager& gestureManager = application.GetGestureManager(); + + // Use pan gesture as GestureDetector cannot be created. + GestureDetector detector = PanGestureDetector::New(); + + Actor actor = Actor::New(); + detector.Attach(actor); + + // Detach an actor twice - no exception should happen. + try + { + detector.Detach(actor); + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + gestureManager.Initialize(); // Reset values + detector.Detach(actor); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + } + catch (DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + tet_result(TET_FAIL); + } + END_TEST; +} + +int UtcDaliGestureDetectorDetachAllP(void) +{ + TestApplication application; + + // Use pan gesture as GestureDetector cannot be created. + GestureDetector detector = PanGestureDetector::New(); + + const unsigned int actorsToAdd = 5; + std::vector myActors; + + for (unsigned int i = 0; i < actorsToAdd; ++i) + { + Actor actor = Actor::New(); + myActors.push_back(actor); + detector.Attach(actor); + } + + DALI_TEST_EQUALS(actorsToAdd, detector.GetAttachedActorCount(), TEST_LOCATION); + + // Detach and retrieve attached actors again, the vector should be empty. + detector.DetachAll(); + + DALI_TEST_EQUALS(0u, detector.GetAttachedActorCount(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliGestureDetectorDetachAllN(void) +{ + TestApplication application; + TestGestureManager& gestureManager = application.GetGestureManager(); + + // Use pan gesture as GestureDetector cannot be created. + GestureDetector detector = PanGestureDetector::New(); + + const unsigned int actorsToAdd = 5; + std::vector myActors; + + for (unsigned int i = 0; i < actorsToAdd; ++i) + { + Actor actor = Actor::New(); + myActors.push_back(actor); + detector.Attach(actor); + } + + DALI_TEST_EQUALS(actorsToAdd, detector.GetAttachedActorCount(), TEST_LOCATION); + + // Detach and retrieve attached actors again, the vector should be empty. + detector.DetachAll(); + + DALI_TEST_EQUALS(0u, detector.GetAttachedActorCount(), TEST_LOCATION); + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + // Call DetachAll again, there should not be any exception + try + { + gestureManager.Initialize(); // Reset values + detector.DetachAll(); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + } + catch (DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + tet_result(TET_FAIL); + } + END_TEST; +} + +int UtcDaliGestureDetectorGetAttachedActors(void) +{ + TestApplication application; + + // Use pan gesture as GestureDetector cannot be created. + GestureDetector detector = PanGestureDetector::New(); + + // Initially there should not be any actors. + DALI_TEST_EQUALS(0u, detector.GetAttachedActorCount(), TEST_LOCATION); + + // Attach one actor + Actor actor1 = Actor::New(); + detector.Attach(actor1); + DALI_TEST_EQUALS(1u, detector.GetAttachedActorCount(), TEST_LOCATION); + + // Attach another actor + Actor actor2 = Actor::New(); + detector.Attach(actor2); + DALI_TEST_EQUALS(2u, detector.GetAttachedActorCount(), TEST_LOCATION); + + // Attach another five actors + std::vector myActors; + for (unsigned int i = 0; i < 5; ++i) + { + Actor actor = Actor::New(); + myActors.push_back(actor); + detector.Attach(actor); + } + DALI_TEST_EQUALS(7u, detector.GetAttachedActorCount(), TEST_LOCATION); + + // Detach actor2 + detector.Detach(actor2); + DALI_TEST_EQUALS(6u, detector.GetAttachedActorCount(), TEST_LOCATION); + + // Attach actor1 again, count should not increase. + detector.Attach(actor1); + DALI_TEST_EQUALS(6u, detector.GetAttachedActorCount(), TEST_LOCATION); + + // Detach actor2 again, count should not decrease. + detector.Detach(actor2); + DALI_TEST_EQUALS(6u, detector.GetAttachedActorCount(), TEST_LOCATION); + + // Detach actor1. + detector.Detach(actor1); + DALI_TEST_EQUALS(5u, detector.GetAttachedActorCount(), TEST_LOCATION); + + // Create scoped actor, actor should be automatically removed from the detector when it goes out + // of scope. + { + Actor scopedActor = Actor::New(); + detector.Attach(scopedActor); + DALI_TEST_EQUALS(6u, detector.GetAttachedActorCount(), TEST_LOCATION); + } + DALI_TEST_EQUALS(5u, detector.GetAttachedActorCount(), TEST_LOCATION); + + // Detach all so nothing remains. + detector.DetachAll(); + DALI_TEST_EQUALS(0u, detector.GetAttachedActorCount(), TEST_LOCATION); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Handle.cpp b/automated-tests/src/dali/utc-Dali-Handle.cpp new file mode 100644 index 0000000..b0cd8cf --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Handle.cpp @@ -0,0 +1,760 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include "dali-test-suite-utils/dali-test-suite-utils.h" +#include + +using namespace Dali; + +void handle_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void handle_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +/// Allows the creation of a BaseObject +class BaseObjectType : public BaseObject +{ +public: + BaseObjectType() + { + } +}; + +Handle ImplicitCopyConstructor(Handle passedByValue) +{ + // object + copy + passedByValue, ref count == 3 + DALI_TEST_CHECK(passedByValue); + if (passedByValue) + { + DALI_TEST_EQUALS(3, passedByValue.GetBaseObject().ReferenceCount(), TEST_LOCATION); + } + + return passedByValue; +} + +} // anon namespace + + +int UtcDaliHandleConstructorVoid(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Handle::Handle()"); + + Handle object; + + DALI_TEST_CHECK(!object); + + END_TEST; +} + +int UtcDaliHandleCopyConstructor(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Handle::Handle(const Handle&)"); + + // Initialize an object, ref count == 1 + Handle object = Actor::New(); + + DALI_TEST_EQUALS(1, object.GetBaseObject().ReferenceCount(), TEST_LOCATION); + + // Copy the object, ref count == 2 + Handle copy(object); + DALI_TEST_CHECK(copy); + if (copy) + { + DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION); + } + + { + // Pass by value, and return another copy, ref count == 3 + Handle anotherCopy = ImplicitCopyConstructor(copy); + + DALI_TEST_CHECK(anotherCopy); + if (anotherCopy) + { + DALI_TEST_EQUALS(3, anotherCopy.GetBaseObject().ReferenceCount(), TEST_LOCATION); + } + } + + // anotherCopy out of scope, ref count == 2 + DALI_TEST_CHECK(copy); + if (copy) + { + DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliHandleAssignmentOperator(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Handle::operator="); + + Handle object = Actor::New(); + + DALI_TEST_CHECK(object); + DALI_TEST_EQUALS(1, object.GetBaseObject().ReferenceCount(), TEST_LOCATION); + + Handle copy; + DALI_TEST_CHECK(!copy); + + copy = object; + DALI_TEST_CHECK(copy); + DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION); + DALI_TEST_CHECK(&(copy.GetBaseObject()) == &(object.GetBaseObject())); + END_TEST; +} + +int UtcDaliHandleSupports(void) +{ + tet_infoline("Positive Test Dali::Handle::Supports()"); + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_CHECK( true == actor.Supports( Handle::DYNAMIC_PROPERTIES ) ); + END_TEST; +} + +int UtcDaliHandleGetPropertyCount(void) +{ + tet_infoline("Positive Test Dali::Handle::GetPropertyCount()"); + TestApplication application; + + Actor actor = Actor::New(); + int defaultPropertyCount( actor.GetPropertyCount() ); + + // Register a dynamic property + actor.RegisterProperty( "test-property", float(123.0f) ); + DALI_TEST_CHECK( (defaultPropertyCount + 1u) == actor.GetPropertyCount() ); + END_TEST; +} + +int UtcDaliHandleGetPropertyName(void) +{ + tet_infoline("Positive Test Dali::Handle::GetPropertyName()"); + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_CHECK( "parent-origin" == actor.GetPropertyName( Actor::Property::PARENT_ORIGIN ) ); + + // Register a dynamic property + std::string name("this-name-should-match"); + Property::Index index = actor.RegisterProperty( name, float(123.0f) ); + DALI_TEST_CHECK( name == actor.GetPropertyName( index ) ); + + END_TEST; +} + +int UtcDaliHandleGetPropertyIndex(void) +{ + tet_infoline("Positive Test Dali::Handle::GetPropertyIndex()"); + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_CHECK( Actor::Property::PARENT_ORIGIN == actor.GetPropertyIndex("parent-origin") ); + + // Register a dynamic property + std::string name("this-name-should-match"); + Property::Index index = actor.RegisterProperty( name, float(123.0f) ); + DALI_TEST_CHECK( index == actor.GetPropertyIndex( name ) ); + END_TEST; +} + +int UtcDaliHandleIsPropertyWritable(void) +{ + tet_infoline("Positive Test Dali::Handle::IsPropertyWritable()"); + TestApplication application; + + Actor actor = Actor::New(); + + // Actor properties which are writable: + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::PARENT_ORIGIN ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::PARENT_ORIGIN_X ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::PARENT_ORIGIN_Y ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::PARENT_ORIGIN_Z ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::ANCHOR_POINT ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::ANCHOR_POINT_X ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::ANCHOR_POINT_Y ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::ANCHOR_POINT_Z ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SIZE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SIZE_WIDTH ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SIZE_HEIGHT ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SIZE_DEPTH ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::POSITION ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::POSITION_X ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::POSITION_Y ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::POSITION_Z ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::ORIENTATION ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SCALE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SCALE_X ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SCALE_Y ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SCALE_Z ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::VISIBLE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::COLOR ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::COLOR_RED ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::COLOR_GREEN ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::COLOR_BLUE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::COLOR_ALPHA ) ); + + // World-properties are not writable: + DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_POSITION ) ); + DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_ORIENTATION ) ); + DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_SCALE ) ); + DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_COLOR ) ); + DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_POSITION_X ) ); + DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_POSITION_Y ) ); + DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_POSITION_Z ) ); + + END_TEST; +} + +int UtcDaliHandleIsPropertyAnimatable(void) +{ + tet_infoline("Positive Test Dali::Handle::IsPropertyAnimatable()"); + TestApplication application; + + Actor actor = Actor::New(); + + // Actor properties which are animatable: + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::PARENT_ORIGIN ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::PARENT_ORIGIN_X ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::PARENT_ORIGIN_Y ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::PARENT_ORIGIN_Z ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::ANCHOR_POINT ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::ANCHOR_POINT_X ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::ANCHOR_POINT_Y ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::ANCHOR_POINT_Z ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SIZE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SIZE_WIDTH ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SIZE_HEIGHT ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SIZE_DEPTH ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::POSITION ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::POSITION_X ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::POSITION_Y ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::POSITION_Z ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::ORIENTATION ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SCALE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SCALE_X ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SCALE_Y ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SCALE_Z ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::VISIBLE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::COLOR ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::COLOR_RED ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::COLOR_GREEN ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::COLOR_BLUE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::COLOR_ALPHA ) ); + + // World-properties can not be animated + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_POSITION ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_ORIENTATION ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_SCALE ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_COLOR ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_POSITION_X ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_POSITION_Y ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_POSITION_Z ) ); + + END_TEST; +} + +int UtcDaliHandleIsPropertyAConstraintInput(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Actor properties which can be used as a constraint input: + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::PARENT_ORIGIN ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::PARENT_ORIGIN_X ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::PARENT_ORIGIN_Y ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::PARENT_ORIGIN_Z ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::ANCHOR_POINT ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::ANCHOR_POINT_X ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::ANCHOR_POINT_Y ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::ANCHOR_POINT_Z ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SIZE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SIZE_WIDTH ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SIZE_HEIGHT ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SIZE_DEPTH ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::POSITION ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::POSITION_X ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::POSITION_Y ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::POSITION_Z ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::ORIENTATION ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SCALE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SCALE_X ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SCALE_Y ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SCALE_Z ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::VISIBLE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::COLOR ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::COLOR_RED ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::COLOR_GREEN ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::COLOR_BLUE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::COLOR_ALPHA ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_POSITION ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_ORIENTATION ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_SCALE ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_COLOR ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_POSITION_X ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_POSITION_Y ) ); + DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_POSITION_Z ) ); + + // Actor properties that cannot be used as a constraint input + DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::NAME ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::SENSITIVE ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::LEAVE_REQUIRED ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::INHERIT_ORIENTATION ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::INHERIT_SCALE ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::COLOR_MODE ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::POSITION_INHERITANCE ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::DRAW_MODE ) ); + DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::SIZE_MODE_FACTOR ) ); + + END_TEST; +} + + +int UtcDaliHandleGetPropertyType(void) +{ + tet_infoline("Positive Test Dali::Handle::GetPropertyType()"); + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_CHECK( Property::VECTOR3 == actor.GetPropertyType( Actor::Property::PARENT_ORIGIN ) ); + DALI_TEST_CHECK( Property::VECTOR3 == actor.GetPropertyType( Actor::Property::ANCHOR_POINT ) ); + DALI_TEST_CHECK( Property::VECTOR3 == actor.GetPropertyType( Actor::Property::SIZE ) ); + DALI_TEST_CHECK( Property::VECTOR3 == actor.GetPropertyType( Actor::Property::POSITION ) ); + DALI_TEST_CHECK( Property::ROTATION == actor.GetPropertyType( Actor::Property::ORIENTATION ) ); + DALI_TEST_CHECK( Property::VECTOR3 == actor.GetPropertyType( Actor::Property::SCALE ) ); + DALI_TEST_CHECK( Property::BOOLEAN == actor.GetPropertyType( Actor::Property::VISIBLE ) ); + DALI_TEST_CHECK( Property::VECTOR4 == actor.GetPropertyType( Actor::Property::COLOR ) ); + + // Register some dynamic properties + Property::Index boolIndex = actor.RegisterProperty( "bool-property", bool(true) ); + Property::Index floatIndex = actor.RegisterProperty( "float-property", float(123.0f) ); + Property::Index intIndex = actor.RegisterProperty( "int-property", 123 ); + Property::Index vector2Index = actor.RegisterProperty( "vector2-property", Vector2(1.0f, 2.0f) ); + Property::Index vector3Index = actor.RegisterProperty( "vector3-property", Vector3(1.0f, 2.0f, 3.0f) ); + Property::Index vector4Index = actor.RegisterProperty( "vector4-property", Vector4(1.0f, 2.0f, 3.0f, 4.0f) ); + Property::Index rotationIndex = actor.RegisterProperty( "rotation-property", AngleAxis(Degree(180.0f), Vector3::YAXIS) ); + + DALI_TEST_CHECK( Property::BOOLEAN == actor.GetPropertyType( boolIndex ) ); + DALI_TEST_CHECK( Property::FLOAT == actor.GetPropertyType( floatIndex ) ); + DALI_TEST_CHECK( Property::INTEGER == actor.GetPropertyType( intIndex ) ); + DALI_TEST_CHECK( Property::VECTOR2 == actor.GetPropertyType( vector2Index ) ); + DALI_TEST_CHECK( Property::VECTOR3 == actor.GetPropertyType( vector3Index ) ); + DALI_TEST_CHECK( Property::VECTOR4 == actor.GetPropertyType( vector4Index ) ); + DALI_TEST_CHECK( Property::ROTATION == actor.GetPropertyType( rotationIndex ) ); + + // Non animatable properties + Property::Index nonAnimStringIndex = actor.RegisterProperty( "man-from-delmonte", std::string("yes"), Property::READ_WRITE); + Property::Index nonAnimV2Index = actor.RegisterProperty( "v2", Vector2(1.f, 2.f), Property::READ_WRITE); + Property::Index nonAnimV3Index = actor.RegisterProperty( "v3", Vector3(1.f, 2.f, 3.f), Property::READ_WRITE); + Property::Index nonAnimV4Index = actor.RegisterProperty( "v4", Vector4(1.f, 2.f, 3.f, 4.f), Property::READ_WRITE); + Property::Index nonAnimBooleanIndex = actor.RegisterProperty( "bool", true, Property::READ_WRITE); + Property::Index nonAnimFloatIndex = actor.RegisterProperty( "float", 0.f, Property::READ_WRITE); + Property::Index nonAnimIntegerIndex = actor.RegisterProperty( "int", 0, Property::READ_WRITE); + + DALI_TEST_CHECK( nonAnimStringIndex != Property::INVALID_INDEX ); + DALI_TEST_CHECK( nonAnimV2Index != Property::INVALID_INDEX ); + DALI_TEST_CHECK( nonAnimV3Index != Property::INVALID_INDEX ); + DALI_TEST_CHECK( nonAnimV4Index != Property::INVALID_INDEX ); + DALI_TEST_CHECK( nonAnimBooleanIndex != Property::INVALID_INDEX ); + DALI_TEST_CHECK( nonAnimFloatIndex != Property::INVALID_INDEX ); + DALI_TEST_CHECK( nonAnimIntegerIndex != Property::INVALID_INDEX ); + + DALI_TEST_CHECK( Property::STRING == actor.GetPropertyType( nonAnimStringIndex ) ); + DALI_TEST_CHECK( Property::VECTOR2 == actor.GetPropertyType( nonAnimV2Index ) ); + DALI_TEST_CHECK( Property::VECTOR3 == actor.GetPropertyType( nonAnimV3Index ) ); + DALI_TEST_CHECK( Property::VECTOR4 == actor.GetPropertyType( nonAnimV4Index ) ); + DALI_TEST_CHECK( Property::BOOLEAN == actor.GetPropertyType( nonAnimBooleanIndex ) ); + DALI_TEST_CHECK( Property::FLOAT == actor.GetPropertyType( nonAnimFloatIndex ) ); + DALI_TEST_CHECK( Property::INTEGER == actor.GetPropertyType( nonAnimIntegerIndex ) ); + + DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimStringIndex ) ); + DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimV2Index ) ); + DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimV3Index ) ); + DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimV4Index ) ); + DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimBooleanIndex ) ); + DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimFloatIndex ) ); + DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimIntegerIndex ) ); + + DALI_TEST_EQUALS( "yes" , actor.GetProperty( nonAnimStringIndex ).Get(), TEST_LOCATION ); + DALI_TEST_EQUALS( Vector2(1.f, 2.f) , actor.GetProperty( nonAnimV2Index ).Get(), TEST_LOCATION ); + DALI_TEST_EQUALS( Vector3(1.f, 2.f, 3.f) , actor.GetProperty( nonAnimV3Index ).Get(), TEST_LOCATION ); + DALI_TEST_EQUALS( Vector4(1.f, 2.f, 3.f, 4.f) , actor.GetProperty( nonAnimV4Index ).Get(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, actor.GetProperty( nonAnimBooleanIndex ).Get(), TEST_LOCATION ); + DALI_TEST_EQUALS( 0.f, actor.GetProperty( nonAnimFloatIndex ).Get(), TEST_LOCATION ); + DALI_TEST_EQUALS( 0, actor.GetProperty( nonAnimIntegerIndex ).Get(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliHandleNonAnimtableProperties(void) +{ + tet_infoline("Test Non Animatable Properties"); + TestApplication application; + + Actor actor = Actor::New(); + + Property::Index nonAnimStringIndex = actor.RegisterProperty( "man-from-delmonte", std::string("no"), Property::READ_WRITE); + + //// modify writable? + try + { + actor.SetProperty( nonAnimStringIndex, Property::Value("yes") ); + } + catch (Dali::DaliException& e) + { + DALI_TEST_CHECK(!"exception"); + } + + DALI_TEST_CHECK( "yes" == actor.GetProperty( nonAnimStringIndex ).Get() ); + + //// cannot modify read only? + Property::Index readonly = actor.RegisterProperty( "float", 0.f, Property::READ_ONLY); + + DALI_TEST_CHECK(!actor.IsPropertyAnimatable(readonly)); + DALI_TEST_CHECK(!actor.IsPropertyWritable(readonly)); + + bool exception = false; + try + { + actor.SetProperty( readonly, Property::Value(1.f) ); + } + catch (Dali::DaliException& e) + { + exception = true; + } + + DALI_TEST_CHECK(!exception);// trying to set a read-only property is a no-op + + DALI_TEST_EQUALS( 0.f, actor.GetProperty( readonly ).Get(), TEST_LOCATION ); + + /// animatable can be set + Property::Index write_anim = actor.RegisterProperty( "write_float", 0.f, Property::ANIMATABLE); + + DALI_TEST_CHECK(actor.IsPropertyAnimatable(write_anim)); + DALI_TEST_CHECK(actor.IsPropertyWritable(write_anim)); + + exception = false; + try + { + actor.SetProperty( write_anim, Property::Value(1.f) ); + } + catch (Dali::DaliException& e) + { + exception = true; + } + + DALI_TEST_CHECK(!exception); + + //// animate a non animatable property is a noop? + float durationSeconds(2.0f); + Animation animation = Animation::New(durationSeconds); + bool relativeValue(true); + + exception = false; + + try + { + animation.AnimateBy(Property(actor, nonAnimStringIndex), relativeValue, AlphaFunction::EASE_IN); + animation.Play(); + application.SendNotification(); + application.Render(static_cast(durationSeconds*0100.0f)/* some progress */); + } + catch (Dali::DaliException& e) + { + exception = true; + } + + DALI_TEST_CHECK(!exception); + DALI_TEST_EQUALS( "yes", actor.GetProperty( nonAnimStringIndex ).Get(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliHandleNonAnimtableCompositeProperties(void) +{ + tet_infoline("Test Non Animatable Composite Properties"); + TestApplication application; + + Actor actor = Actor::New(); + + Property::Value value(Property::ARRAY); + Property::Array* array = value.GetArray(); + DALI_TEST_CHECK( array ); + + array->PushBack( Property::Value( 0.1f ) ); + array->PushBack( "a string" ); + array->PushBack( Property::Value( Vector3(1,2,3) ) ); + + DALI_TEST_EQUALS( 3, array->Count(), TEST_LOCATION ); + + Property::Index propertyIndex = actor.RegisterProperty( "composite", value, Property::READ_WRITE ); + + Property::Value out = actor.GetProperty( propertyIndex ); + Property::Array* outArray = out.GetArray(); + DALI_TEST_CHECK( outArray != NULL ); + + DALI_TEST_CHECK( Property::FLOAT == outArray->GetElementAt(0).GetType()); + DALI_TEST_CHECK( Property::STRING == outArray->GetElementAt(1).GetType()); + DALI_TEST_CHECK( Property::VECTOR3 == outArray->GetElementAt(2).GetType()); + + DALI_TEST_EQUALS( 0.1f, outArray->GetElementAt(0).Get(), TEST_LOCATION); + DALI_TEST_EQUALS( "a string", outArray->GetElementAt(1).Get(), TEST_LOCATION); + DALI_TEST_EQUALS( Vector3(1,2,3), outArray->GetElementAt(2).Get(), TEST_LOCATION); + + // composite types not animatable + bool exception = false; + try + { + actor.RegisterProperty( "compositemap", value, Property::ANIMATABLE); + } + catch (Dali::DaliException& e) + { + exception = true; + DALI_TEST_PRINT_ASSERT( e ); + } + + DALI_TEST_EQUALS(exception, true, TEST_LOCATION); + + // Map of maps + Property::Value mapOfMaps(Property::MAP); + Property::Map* map = mapOfMaps.GetMap(); + + map->Insert( "key", Property::Value(Property::MAP) ); + map->Insert( "2key", "a string" ); + + DALI_TEST_EQUALS( "a string", (*map)["2key"].Get(), TEST_LOCATION); + + Property::Map* innerMap = map->Find("key")->GetMap(); + innerMap->Insert( "subkey", 5.f ); + + DALI_TEST_CHECK( NULL != map->Find("key")->GetMap()->Find("subkey") ); + DALI_TEST_EQUALS( 5.f, map->Find("key")->GetMap()->Find("subkey")->Get(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliHandleSetProperty01(void) +{ + tet_infoline("Positive Test Dali::Handle::SetProperty()"); + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_CHECK( ParentOrigin::TOP_LEFT == actor.GetProperty( Actor::Property::PARENT_ORIGIN ).Get() ); + + actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER ); + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_CHECK( ParentOrigin::CENTER == actor.GetProperty( Actor::Property::PARENT_ORIGIN ).Get() ); + END_TEST; +} + +int UtcDaliHandleSetProperty02(void) +{ + tet_infoline("Positive Test Dali::Handle::SetProperty()"); + TestApplication application; + + Actor actor = Actor::New(); + + DALI_TEST_CHECK( !actor.IsPropertyWritable( Actor::Property::WORLD_POSITION ) ); + + // World position is not writable so this is a no-op and should not crash + actor.SetProperty( Actor::Property::WORLD_POSITION, Vector3(1,2,3) ); + + END_TEST; +} + +int UtcDaliHandleRegisterProperty(void) +{ + tet_infoline("Positive Test Dali::Handle::RegisterProperty()"); + TestApplication application; + + Actor actor = Actor::New(); + DALI_TEST_CHECK( ParentOrigin::TOP_LEFT == actor.GetProperty( Actor::Property::PARENT_ORIGIN ).Get() ); + + END_TEST; +} + +int UtcDaliHandleGetProperty(void) +{ + tet_infoline("Positive Test Dali::Handle::GetProperty()"); + TestApplication application; + + Actor actor = Actor::New(); + + DALI_TEST_CHECK( ParentOrigin::TOP_LEFT == actor.GetProperty( Actor::Property::PARENT_ORIGIN ).Get() ); + DALI_TEST_CHECK( AnchorPoint::CENTER == actor.GetProperty( Actor::Property::ANCHOR_POINT ).Get() ); + DALI_TEST_CHECK( Vector3::ZERO == actor.GetProperty( Actor::Property::SIZE ).Get() ); + DALI_TEST_CHECK( Vector3::ZERO == actor.GetProperty( Actor::Property::POSITION ).Get() ); + DALI_TEST_CHECK( Vector3::ONE == actor.GetProperty( Actor::Property::SCALE ).Get() ); + DALI_TEST_CHECK( true == actor.GetProperty( Actor::Property::VISIBLE ).Get() ); + DALI_TEST_CHECK( Color::WHITE == actor.GetProperty( Actor::Property::COLOR ).Get() ); + END_TEST; +} + +int UtcDaliHandleDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Handle::DownCast()"); + + Actor actor = Actor::New(); + + BaseHandle baseHandle = actor; + + Handle handle = Handle::DownCast(baseHandle); + + DALI_TEST_CHECK( handle ); + + baseHandle = BaseHandle(); + + handle = Handle::DownCast(baseHandle); + + DALI_TEST_CHECK( !handle ); + + END_TEST; +} + +int UtcDaliHandleDownCastNegative(void) +{ + TestApplication application; + + // BaseObject is NOT an Object, so this DownCast should fail + BaseHandle handle( new BaseObjectType ); + Handle customHandle1 = Handle::DownCast( handle ); + DALI_TEST_CHECK( ! customHandle1 ); + + // A DownCast on an empty handle will also fail + Handle empty; + Handle customHandle2 = Handle::DownCast( empty ); + DALI_TEST_CHECK( ! customHandle2 ); + END_TEST; +} + +int UtcDaliHandleGetPropertyIndices(void) +{ + TestApplication application; + Property::IndexContainer indices; + + // Actor + Actor actor = Actor::New(); + actor.GetPropertyIndices( indices ); + DALI_TEST_CHECK( indices.Size() ); + DALI_TEST_EQUALS( indices.Size(), actor.GetPropertyCount(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliHandleRegisterPropertyTypes(void) +{ + TestApplication application; + + struct PropertyTypeAnimatable + { + const char * name; + Property::Value value; + bool animatable; + }; + + Property::Array array; + Property::Map map; + + PropertyTypeAnimatable properties[] = + { + { "Property::BOOLEAN", true, true }, + { "Property::FLOAT", 1.0f, true }, + { "Property::INTEGER", 1, true }, + { "Property::VECTOR2", Vector2::ONE, true }, + { "Property::VECTOR3", Vector3::ONE, true }, + { "Property::VECTOR4", Vector4::ONE, true }, + { "Property::MATRIX3", Matrix3::IDENTITY, true }, + { "Property::MATRIX", Matrix::IDENTITY, true }, + { "Property::RECTANGLE", Rect(), false }, + { "Property::ROTATION", AngleAxis(), true }, + { "Property::STRING", std::string("Me"), false }, + { "Property::ARRAY", array, false }, + { "Property::MAP", map, false }, + }; + + unsigned int numOfProperties( sizeof( properties ) / sizeof( properties[0] ) ); + + for ( unsigned int i = 0; i < numOfProperties; ++i ) + { + tet_printf( "Testing: %s\n", properties[i].name ); + + bool exception = false; + try + { + Actor actor = Actor::New(); + actor.RegisterProperty( "man-from-delmonte", properties[i].value ); + } + catch (Dali::DaliException& e) + { + exception = true; + } + + DALI_TEST_CHECK( properties[i].animatable != exception ); + } + END_TEST; +} + +int UtcDaliHandleCustomProperty(void) +{ + TestApplication application; + + Handle handle = Handle::New(); + + float startValue(1.0f); + Property::Index index = handle.RegisterProperty( "test-property", startValue ); + DALI_TEST_CHECK( handle.GetProperty(index) == startValue ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_CHECK( handle.GetProperty(index) == startValue ); + application.Render(0); + DALI_TEST_CHECK( handle.GetProperty(index) == startValue ); + + handle.SetProperty( index, 5.0f ); + + application.SendNotification(); + application.Render(0); + DALI_TEST_CHECK( handle.GetProperty(index) == 5.0f ); + application.Render(0); + DALI_TEST_CHECK( handle.GetProperty(index) == 5.0f ); + END_TEST; +} +int UtcDaliHandleWeightNew(void) +{ + TestApplication application; + + Handle handle = WeightObject::New();; + DALI_TEST_CHECK( handle.GetProperty(WeightObject::WEIGHT) == 0.0f ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-HoverProcessing.cpp b/automated-tests/src/dali/utc-Dali-HoverProcessing.cpp new file mode 100644 index 0000000..97f1b28 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-HoverProcessing.cpp @@ -0,0 +1,1286 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include + +using namespace Dali; + +void utc_dali_hover_processing_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_hover_processing_cleanup(void) +{ + test_return_value = TET_PASS; +} + +/////////////////////////////////////////////////////////////////////////////// + +namespace +{ + +// Stores data that is populated in the callback and will be read by the TET cases +struct SignalData +{ + SignalData() + : functorCalled( false ), + hoverEvent(), + hoveredActor() + { + } + + void Reset() + { + functorCalled = false; + + hoverEvent.time = 0u; + hoverEvent.points.clear(); + + hoveredActor.Reset(); + } + + bool functorCalled; + HoverEvent hoverEvent; + Actor hoveredActor; +}; + +// Functor that sets the data when called +struct HoverEventFunctor +{ + /** + * Constructor. + * @param[in] data Reference to the data to store callback information. + * @param[in] returnValue What the functor should return. + */ + HoverEventFunctor( SignalData& data, bool returnValue = true ) + : signalData( data ), + returnValue( returnValue ) + { + } + + bool operator()( Actor actor, const HoverEvent& hoverEvent ) + { + signalData.functorCalled = true; + signalData.hoveredActor = actor; + signalData.hoverEvent = hoverEvent; + + return returnValue; + } + + SignalData& signalData; + bool returnValue; +}; + +// Functor that removes the actor when called. +struct RemoveActorFunctor : public HoverEventFunctor +{ + /** + * Constructor. + * @param[in] data Reference to the data to store callback information. + * @param[in] returnValue What the functor should return. + */ + RemoveActorFunctor( SignalData& data, bool returnValue = true ) + : HoverEventFunctor( data, returnValue ) + { + } + + bool operator()( Actor actor, const HoverEvent& hoverEvent ) + { + Actor parent( actor.GetParent() ); + if ( parent ) + { + parent.Remove( actor ); + } + + return HoverEventFunctor::operator()( actor, hoverEvent ); + } +}; + +Integration::HoverEvent GenerateSingleHover( TouchPoint::State state, Vector2 screenPosition ) +{ + Integration::HoverEvent hoverEvent; + hoverEvent.points.push_back( TouchPoint ( 0, state, screenPosition.x, screenPosition.y ) ); + return hoverEvent; +} + +} // anon namespace + +/////////////////////////////////////////////////////////////////////////////// + +int UtcDaliHoverNormalProcessing(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + actor.HoveredSignal().Connect( &application, functor ); + + Vector2 screenCoordinates( 10.0f, 10.0f ); + Vector2 localCoordinates; + actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( localCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION ); + + TouchPoint point = data.hoverEvent.GetPoint(0); + DALI_TEST_EQUALS( TouchPoint::Started, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, point.screen, TEST_LOCATION ); + DALI_TEST_EQUALS( localCoordinates, point.local, 0.1f, TEST_LOCATION ); + + data.Reset(); + + // Emit a motion signal + screenCoordinates.x = screenCoordinates.y = 11.0f; + actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( localCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION ); + data.Reset(); + + // Emit a finished signal + screenCoordinates.x = screenCoordinates.y = 12.0f; + actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Finished, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Finished, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( localCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION ); + data.Reset(); + + // Emit a started signal where the actor is not present + screenCoordinates.x = screenCoordinates.y = 200.0f; + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliHoverOutsideCameraNearFarPlanes(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + Vector2 stageSize = stage.GetSize(); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::CENTER); + actor.SetParentOrigin(ParentOrigin::CENTER); + stage.Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Get the camera's near and far planes + RenderTaskList taskList = stage.GetRenderTaskList(); + Dali::RenderTask task = taskList.GetTask(0); + CameraActor camera = task.GetCameraActor(); + float nearPlane = camera.GetNearClippingPlane(); + float farPlane = camera.GetFarClippingPlane(); + + // Calculate the current distance of the actor from the camera + float tanHalfFov = tanf(camera.GetFieldOfView() * 0.5f); + float distance = (stageSize.y * 0.5f) / tanHalfFov; + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + actor.HoveredSignal().Connect( &application, functor ); + + Vector2 screenCoordinates( stageSize.x * 0.5f, stageSize.y * 0.5f ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit a started signal where actor is just at the camera's near plane + actor.SetZ(distance - nearPlane); + + // Render and notify + application.SendNotification(); + application.Render(); + + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit a started signal where actor is closer than the camera's near plane + actor.SetZ((distance - nearPlane) + 1.0f); + + // Render and notify + application.SendNotification(); + application.Render(); + + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit a started signal where actor is just at the camera's far plane + actor.SetZ(distance - farPlane); + + // Render and notify + application.SendNotification(); + application.Render(); + + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit a started signal where actor is further than the camera's far plane + actor.SetZ((distance - farPlane) - 1.0f); + + // Render and notify + application.SendNotification(); + application.Render(); + + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliHoverEmitEmpty(void) +{ + TestApplication application; + + try + { + // Emit an empty HoverEvent + Integration::HoverEvent event; + application.ProcessEvent( event ); + tet_result( TET_FAIL ); + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_ASSERT( e, "!event.points.empty()", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliHoverInterrupted(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + actor.HoveredSignal().Connect( &application, functor ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + // Emit an interrupted signal, we should be signalled regardless of whether there is a hit or not. + application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f /* Outside actor */ ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, data.hoverEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + // Emit another interrupted signal, our signal handler should not be called. + application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliHoverParentConsumer(void) +{ + TestApplication application; + Actor rootActor( Stage::GetCurrent().GetRootLayer() ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data, false ); + actor.HoveredSignal().Connect( &application, functor ); + + // Connect to root actor's hovered signal + SignalData rootData; + HoverEventFunctor rootFunctor( rootData ); // Consumes signal + rootActor.HoveredSignal().Connect( &application, rootFunctor ); + + Vector2 screenCoordinates( 10.0f, 10.0f ); + Vector2 actorCoordinates, rootCoordinates; + actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, rootData.hoverEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( actorCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_EQUALS( rootCoordinates, rootData.hoverEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit a motion signal + screenCoordinates.x = screenCoordinates.y = 11.0f; + actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, rootData.hoverEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( actorCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_EQUALS( rootCoordinates, rootData.hoverEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit a finished signal + screenCoordinates.x = screenCoordinates.y = 12.0f; + actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Finished, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Finished, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Finished, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, rootData.hoverEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( actorCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_EQUALS( rootCoordinates, rootData.hoverEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit a started signal where the actor is not present, will hit the root actor though + screenCoordinates.x = screenCoordinates.y = 200.0f; + rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, rootData.hoverEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( rootCoordinates, rootData.hoverEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_CHECK( rootActor == rootData.hoverEvent.points[0].hitActor ); + END_TEST; +} + +int UtcDaliHoverInterruptedParentConsumer(void) +{ + TestApplication application; + Actor rootActor( Stage::GetCurrent().GetRootLayer() ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data, false ); + actor.HoveredSignal().Connect( &application, functor ); + + // Connect to root actor's hovered signal + SignalData rootData; + HoverEventFunctor rootFunctor( rootData ); // Consumes signal + rootActor.HoveredSignal().Connect( &application, rootFunctor ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit an interrupted signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit another started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + rootData.Reset(); + + // Remove actor from Stage + Stage::GetCurrent().Remove( actor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit an interrupted signal, only root actor's signal should be called. + application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f /* Outside actor */ ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( rootActor == rootData.hoverEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit another interrupted state, none of the signal's should be called. + application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, rootData.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliHoverLeave(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + actor.HoveredSignal().Connect( &application, functor ); + + // Set actor to require leave events + actor.SetLeaveRequired( true ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + // Emit a motion signal outside of actor, should be signalled with a Leave + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Leave, data.hoverEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + // Another motion outside of actor, no signalling + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 201.0f, 201.0f )) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Another motion event inside actor, signalled with motion + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 10.0f, 10.0f )) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, data.hoverEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + // We do not want to listen to leave events anymore + actor.SetLeaveRequired( false ); + + // Another motion event outside of actor, no signalling + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliHoverLeaveParentConsumer(void) +{ + TestApplication application; + Actor rootActor( Stage::GetCurrent().GetRootLayer() ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data, false ); + actor.HoveredSignal().Connect( &application, functor ); + + // Connect to root actor's hovered signal + SignalData rootData; + HoverEventFunctor rootFunctor( rootData ); // Consumes signal + rootActor.HoveredSignal().Connect( &application, rootFunctor ); + + // Set actor to require leave events + actor.SetLeaveRequired( true ); + rootActor.SetLeaveRequired( true ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit a motion signal outside of actor, should be signalled with a Leave + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Leave, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Leave, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Another motion outside of actor, only rootActor signalled + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 201.0f, 201.0f )) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( rootActor == rootData.hoverEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Another motion event inside actor, signalled with motion + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 10.0f, 10.0f )) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // We do not want to listen to leave events of actor anymore + actor.SetLeaveRequired( false ); + + // Another motion event outside of root actor, only root signalled + Vector2 stageSize( Stage::GetCurrent().GetSize() ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( stageSize.width + 10.0f, stageSize.height + 10.0f )) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Leave, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliHoverActorBecomesInsensitive(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + actor.HoveredSignal().Connect( &application, functor ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + // Change actor to insensitive + actor.SetSensitive( false ); + + // Emit a motion signal, signalled with an interrupted + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, data.hoverEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliHoverActorBecomesInsensitiveParentConsumer(void) +{ + TestApplication application; + Actor rootActor( Stage::GetCurrent().GetRootLayer() ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data, false ); + actor.HoveredSignal().Connect( &application, functor ); + + // Connect to root actor's hovered signal + SignalData rootData; + HoverEventFunctor rootFunctor( rootData ); // Consumes signal + rootActor.HoveredSignal().Connect( &application, rootFunctor ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Remove actor from Stage + Stage::GetCurrent().Remove( actor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Make root actor insensitive + rootActor.SetSensitive( false ); + + // Emit a motion signal, signalled with an interrupted (should get interrupted even if within root actor) + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.hoverEvent.points[0].state, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliHoverMultipleLayers(void) +{ + TestApplication application; + Actor rootActor( Stage::GetCurrent().GetRootLayer() ); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + + Layer layer1 ( Layer::New() ); + layer1.SetSize(100.0f, 100.0f); + layer1.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add( layer1 ); + + Actor actor1 ( Actor::New() ); + actor1.SetSize( 100.0f, 100.0f ); + actor1.SetAnchorPoint(AnchorPoint::TOP_LEFT); + actor1.SetZ( 1.0f ); // Should hit actor1 in this layer + layer1.Add( actor1 ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to layer1 and actor1 + layer1.HoveredSignal().Connect( &application, functor ); + actor1.HoveredSignal().Connect( &application, functor ); + + // Hit in hittable area, actor1 should be hit + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.hoveredActor == actor1 ); + data.Reset(); + + // Make layer1 insensitive, nothing should be hit + layer1.SetSensitive( false ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Make layer1 sensitive again, again actor1 will be hit + layer1.SetSensitive( true ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.hoveredActor == actor1 ); + data.Reset(); + + // Make rootActor insensitive, nothing should be hit + rootActor.SetSensitive( false ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Make rootActor sensitive + rootActor.SetSensitive( true ); + + // Add another layer + Layer layer2 ( Layer::New() ); + layer2.SetSize(100.0f, 100.0f ); + layer2.SetAnchorPoint(AnchorPoint::TOP_LEFT); + layer2.SetZ( 10.0f ); // Should hit layer2 in this layer rather than actor2 + Stage::GetCurrent().Add( layer2 ); + + Actor actor2 ( Actor::New() ); + actor2.SetSize(100.0f, 100.0f); + actor2.SetAnchorPoint(AnchorPoint::TOP_LEFT); + layer2.Add( actor2 ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to layer2 and actor2 + layer2.HoveredSignal().Connect( &application, functor ); + actor2.HoveredSignal().Connect( &application, functor ); + + // Emit an event, should hit layer2 + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + //DALI_TEST_CHECK( data.hoveredActor == layer2 ); // TODO: Uncomment this after removing renderable hack! + data.Reset(); + + // Make layer2 insensitive, should hit actor1 + layer2.SetSensitive( false ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.hoveredActor == actor1 ); + data.Reset(); + + // Make layer2 sensitive again, should hit layer2 + layer2.SetSensitive( true ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + //DALI_TEST_CHECK( data.hoveredActor == layer2 ); // TODO: Uncomment this after removing renderable hack! + data.Reset(); + + // Make layer2 invisible, render and notify + layer2.SetVisible( false ); + application.SendNotification(); + application.Render(); + + // Should hit actor1 + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.hoveredActor == actor1 ); + data.Reset(); + + // Make rootActor invisible, render and notify + rootActor.SetVisible( false ); + application.SendNotification(); + application.Render(); + + // Should not hit anything + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliHoverMultipleRenderTasks(void) +{ + TestApplication application; + Stage stage ( Stage::GetCurrent() ); + Vector2 stageSize ( stage.GetSize() ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stage.Add(actor); + + // Create render task + Viewport viewport( stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f ); + RenderTask renderTask ( Stage::GetCurrent().GetRenderTaskList().CreateTask() ); + renderTask.SetViewport( viewport ); + renderTask.SetInputEnabled( true ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + actor.HoveredSignal().Connect( &application, functor ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Ensure renderTask actor can be hit too. + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Disable input on renderTask, should not be hittable + renderTask.SetInputEnabled( false ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliHoverMultipleRenderTasksWithChildLayer(void) +{ + TestApplication application; + Stage stage ( Stage::GetCurrent() ); + Vector2 stageSize ( stage.GetSize() ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stage.Add(actor); + + Layer layer = Layer::New(); + layer.SetSize(100.0f, 100.0f); + layer.SetAnchorPoint(AnchorPoint::TOP_LEFT); + actor.Add(layer); + + // Create render task + Viewport viewport( stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f ); + RenderTask renderTask ( Stage::GetCurrent().GetRenderTaskList().CreateTask() ); + renderTask.SetViewport( viewport ); + renderTask.SetInputEnabled( true ); + renderTask.SetSourceActor( actor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to layer's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + actor.HoveredSignal().Connect( &application, functor ); + layer.HoveredSignal().Connect( &application, functor ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Ensure renderTask actor can be hit too. + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Disable input on renderTask, should not be hittable + renderTask.SetInputEnabled( false ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliHoverOffscreenRenderTasks(void) +{ + TestApplication application; + Stage stage ( Stage::GetCurrent() ); + Vector2 stageSize ( stage.GetSize() ); + + // FrameBufferImage for offscreen RenderTask + FrameBufferImage frameBufferImage( FrameBufferImage::New( stageSize.width, stageSize.height, Pixel::RGBA8888 ) ); + + // Create an image actor to display the FrameBufferImage + ImageActor imageActor ( ImageActor::New( frameBufferImage ) ); + imageActor.SetParentOrigin(ParentOrigin::CENTER); + imageActor.SetSize( stageSize.x, stageSize.y ); + imageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME + stage.Add( imageActor ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stage.Add( actor ); + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); // Ensure framebuffer connects + + stage.GetRenderTaskList().GetTask( 0u ).SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION ); + + // Create a RenderTask + RenderTask renderTask = stage.GetRenderTaskList().CreateTask(); + renderTask.SetSourceActor( actor ); + renderTask.SetTargetFrameBuffer( frameBufferImage ); + renderTask.SetInputEnabled( true ); + + // Create another RenderTask + RenderTask renderTask2( stage.GetRenderTaskList().CreateTask() ); + renderTask2.SetInputEnabled( true ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + actor.HoveredSignal().Connect( &application, functor ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliHoverMultipleRenderableActors(void) +{ + TestApplication application; + Stage stage ( Stage::GetCurrent() ); + Vector2 stageSize ( stage.GetSize() ); + + ImageActor parent = ImageActor::New(); + parent.SetSize( 100.0f, 100.0f ); + parent.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stage.Add(parent); + + ImageActor actor = ImageActor::New(); + actor.SetSize( 100.0f, 100.0f ); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + actor.SetSortModifier( 1.0f ); + parent.Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to layer's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + parent.HoveredSignal().Connect( &application, functor ); + actor.HoveredSignal().Connect( &application, functor ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.hoveredActor ); + END_TEST; +} + +int UtcDaliHoverActorRemovedInSignal(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + RemoveActorFunctor functor( data ); + actor.HoveredSignal().Connect( &application, functor ); + + // Register for leave events + actor.SetLeaveRequired( true ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Re-add, render and notify + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(); + + // Emit another signal outside of actor's area, should not get anything as the scene has changed. + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit another signal outside of actor's area, should not get anything as the scene has changed. + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Re-add actor back to stage, render and notify + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(); + + // Emit another started event + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Completely delete the actor + actor.Reset(); + + // Emit event, should not crash and should not receive an event. + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliHoverActorSignalNotConsumed(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data, false ); + actor.HoveredSignal().Connect( &application, functor ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliHoverActorUnStaged(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + actor.HoveredSignal().Connect( &application, functor ); + + // Emit a started signal + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Remove actor from stage + Stage::GetCurrent().Remove( actor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit a move at the same point, we should not be signalled. + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliHoverSystemOverlayActor(void) +{ + TestApplication application; + Dali::Integration::Core& core( application.GetCore() ); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + // Create an actor and add it to the system overlay. + Actor systemActor = Actor::New(); + systemActor.SetSize(100.0f, 100.0f); + systemActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add( systemActor ); + + // Create an actor and add it to the stage as per normal, same position and size as systemActor + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Connect to the hover signals. + SignalData data; + HoverEventFunctor functor( data ); + systemActor.HoveredSignal().Connect( &application, functor ); + actor.HoveredSignal().Connect( &application, functor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit a started signal, the system overlay is drawn last so is at the top, should hit the systemActor. + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( systemActor == data.hoveredActor ); + END_TEST; +} + +int UtcDaliHoverLeaveActorReadded(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stage.Add(actor); + + // Set actor to receive hover-events + actor.SetLeaveRequired( true ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + actor.HoveredSignal().Connect( &application, functor ); + + // Emit a started and motion + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 11.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Remove actor from stage and add again + stage.Remove( actor ); + stage.Add( actor ); + + // Emit a motion within the actor's bounds + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 12.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit a motion outside the actor's bounds + application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 200.0f, 200.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Leave, data.hoverEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + END_TEST; +} + + +int UtcDaliHoverStencilNonRenderableActor(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stage.Add(actor); + + Actor stencil = Actor::New(); + stencil.SetSize(50.0f, 50.0f); + stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stencil.SetDrawMode( DrawMode::STENCIL ); + stage.Add(stencil); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's hovered signal + SignalData data; + HoverEventFunctor functor( data ); + actor.HoveredSignal().Connect( &application, functor ); + + // Emit an event within stencil area + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit an event outside the stencil area but within the actor area, we should have a hit! + application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 60.0f, 60.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Image.cpp b/automated-tests/src/dali/utc-Dali-Image.cpp new file mode 100644 index 0000000..1c1ba77 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Image.cpp @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; + +void utc_dali_image_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_image_cleanup(void) +{ + test_return_value = TET_PASS; +} + +static const char* gTestImageFilename = "icon_wrt.png"; + +namespace +{ +void LoadBitmapResource(TestPlatformAbstraction& platform) +{ + Integration::ResourceRequest* request = platform.GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD ); + Integration::ResourcePointer resource(bitmap); + bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80); + + if(request) + { + platform.SetResourceLoaded(request->GetId(), request->GetType()->id, resource); + } +} + +} + +int UtcDaliImageDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Image::DownCast()"); + + Image image = ResourceImage::New(gTestImageFilename); + + BaseHandle object(image); + + Image image2 = Image::DownCast(object); + DALI_TEST_CHECK(image2); + + Image image3 = DownCast< Image >(object); + DALI_TEST_CHECK(image3); + + BaseHandle unInitializedObject; + Image image4 = Image::DownCast(unInitializedObject); + DALI_TEST_CHECK(!image4); + + Image image5 = DownCast< Image >(unInitializedObject); + DALI_TEST_CHECK(!image5); + END_TEST; +} + +int UtcDaliImageGetReleasePolicy(void) +{ + TestApplication application; + + tet_infoline("UtcDaliImageGetReleasePolicy"); + + Image image = ResourceImage::New(gTestImageFilename, ResourceImage::IMMEDIATE, Image::UNUSED); + + DALI_TEST_CHECK( image ); + + DALI_TEST_CHECK( Image::UNUSED == image.GetReleasePolicy() ); + + END_TEST; +} + +int UtcDaliImageGetWidthHeight(void) +{ + TestApplication application; + + tet_infoline("UtcDaliImageGetWidthHeight - Image::GetWidth() & Image::GetHeight"); + + Vector2 testSize(8.0f, 16.0f); + application.GetPlatform().SetClosestImageSize(testSize); + Image image1 = ResourceImage::New(gTestImageFilename); + DALI_TEST_EQUALS( image1.GetWidth(), testSize.width, TEST_LOCATION ); + DALI_TEST_EQUALS( image1.GetHeight(), testSize.height, TEST_LOCATION ); + + Image image2 = ResourceImage::New( gTestImageFilename, ImageDimensions(128, 256), FittingMode::SCALE_TO_FILL, SamplingMode::DEFAULT ); + DALI_TEST_EQUALS( image2.GetWidth(), 128u, TEST_LOCATION ); + DALI_TEST_EQUALS( image2.GetHeight(), 256u, TEST_LOCATION ); + + Image image3 = FrameBufferImage::New(16, 32); + DALI_TEST_EQUALS(image3.GetWidth(), 16u, TEST_LOCATION); + DALI_TEST_EQUALS(image3.GetHeight(), 32u, TEST_LOCATION); + + TestNativeImagePointer nativeImage = TestNativeImage::New(32, 64); + Image image4 = NativeImage::New(*(nativeImage.Get())); + DALI_TEST_EQUALS(image4.GetWidth(), 32u, TEST_LOCATION); + DALI_TEST_EQUALS(image4.GetHeight(), 64u, TEST_LOCATION); + + END_TEST; +} + +static bool SignalUploadedFlag = false; + +static void SignalUploadedHandler(Image image) +{ + tet_infoline("Received image uploaded signal"); + + SignalUploadedFlag = true; +} + +int UtcDaliImageSignalUploaded(void) +{ + TestApplication application; + TestPlatformAbstraction& platform = application.GetPlatform(); + tet_infoline("UtcDaliImageSignalUploaded - Image::SignalUploaded()"); + + // set up image in fake platform abstraction + Vector2 testSize(80.0f, 80.0f); + platform.SetClosestImageSize(testSize); + + ResourceImage image = ResourceImage::New(gTestImageFilename); + + // Load image + application.SendNotification(); + application.Render(16); + std::vector ids; + ids.push_back( 23 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + Integration::ResourceRequest* request = platform.GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD ); + Integration::ResourcePointer resource(bitmap); + bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80); + + if(request) + { + platform.SetResourceLoaded(request->GetId(), request->GetType()->id, resource); + } + application.Render(16); + application.SendNotification(); + + image.UploadedSignal().Connect( SignalUploadedHandler ); + + Dali::ImageActor imageActor = ImageActor::New(image); + Stage::GetCurrent().Add(imageActor); + imageActor.SetSize(80, 80); + imageActor.SetVisible(true); + + application.SendNotification(); + application.Render(0); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK( SignalUploadedFlag == true ); + SignalUploadedFlag = false; + + image.Reload(); + bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 160, 160, 160, 160); + + // image loading + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + //upload + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + DALI_TEST_CHECK( SignalUploadedFlag == true ); + END_TEST; +} + +int UtcDaliImageDiscard01(void) +{ + TestApplication application; + tet_infoline("UtcDaliImageDiscard01 - no actors"); + + { + Image image = ResourceImage::New(gTestImageFilename); + + // Load image + application.SendNotification(); + application.Render(16); + std::vector ids; + ids.push_back( 23 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + TestPlatformAbstraction& platform = application.GetPlatform(); + LoadBitmapResource( platform ); + application.Render(16); + application.SendNotification(); + } // Drop image handle + + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + // Shouldn't have been sent to GL... + const std::vector& texIds = application.GetGlAbstraction().GetNextTextureIds(); + DALI_TEST_CHECK( texIds.size() == 1 ); + DALI_TEST_CHECK( texIds[0] == 23 ); + END_TEST; +} + +int UtcDaliImageDiscard02(void) +{ + TestApplication application; + application.GetGlAbstraction().EnableTextureCallTrace( true ); + tet_infoline("UtcDaliImageDiscard02 - one actor, tests TextureCache::DiscardTexture"); + + { + { + ImageActor actor; + { + Image image = ResourceImage::New(gTestImageFilename, ImageDimensions( 40, 30 ) ); + actor = ImageActor::New(image); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + + std::vector ids; + ids.push_back( 23 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + + TestPlatformAbstraction& platform = application.GetPlatform(); + LoadBitmapResource( platform ); + application.Render(16); + application.SendNotification(); + DALI_TEST_CHECK( application.GetGlAbstraction().GetTextureTrace().FindMethod("BindTexture") ); + } // lose image handle, actor should still keep one + application.SendNotification(); + application.Render(16); + + Stage::GetCurrent().Remove(actor); + application.SendNotification(); + application.Render(16); + } // lose actor + application.SendNotification(); + application.Render(16); + } + + // Cleanup + application.SendNotification(); + application.Render(16); + application.Render(16); + application.SendNotification(); + + // texture should have been removed: + DALI_TEST_CHECK( application.GetGlAbstraction().CheckTextureDeleted( 23 )); + END_TEST; +} + +int UtcDaliImageDiscard03(void) +{ + TestApplication application; + tet_infoline("UtcDaliImageDiscard03 - one actor, tests TextureCache::RemoveObserver"); + + const Vector2 closestImageSize( 1, 1); + application.GetPlatform().SetClosestImageSize(closestImageSize); + + Image image = ResourceImage::New(gTestImageFilename); + ImageActor actor = ImageActor::New(image); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + + std::vector ids; + ids.push_back( 23 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + + TestPlatformAbstraction& platform = application.GetPlatform(); + LoadBitmapResource( platform ); + application.Render(16); + application.SendNotification(); + application.SendNotification(); + application.Render(16); + + const std::vector& texIds = application.GetGlAbstraction().GetNextTextureIds(); + DALI_TEST_CHECK( texIds.size() == 0 ); + const std::vector& boundTexIds = application.GetGlAbstraction().GetBoundTextures(); + DALI_TEST_CHECK( boundTexIds[0] == 23 ); + + Stage::GetCurrent().Remove(actor); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); // Should remove image renderer + + END_TEST; +} + +int UtcDaliImageContextLoss(void) +{ + TestApplication application; // Default config: DALI_DISCARDS_ALL_DATA + + const Vector2 closestImageSize( 80, 80 ); + TestPlatformAbstraction& platform = application.GetPlatform(); + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + + platform.SetClosestImageSize(closestImageSize); + + tet_infoline("UtcDaliImageContextLoss - Load image with LoadPolicy::Immediate, ReleasePolicy::Never, bitmap discard. Check that the image is re-requested on context regain\n"); + + Image image = ResourceImage::New("image.png", ResourceImage::IMMEDIATE, Image::NEVER); + + DALI_TEST_CHECK( image ); + + application.SendNotification(); + application.Render(16); + + // request file loading immediately + + DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + ImageActor actor = ImageActor::New(image); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + textureTrace.Enable(true); + + std::vector ids; + ids.push_back( 23 ); + glAbstraction.SetNextTextureIds( ids ); + + LoadBitmapResource(platform); + + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK( textureTrace.FindMethod("GenTextures") ); + + textureTrace.Reset(); + textureTrace.Enable(true); + platform.ResetTrace(); + platform.EnableTrace(true); + + // Lose & regain context (in render 'thread') + application.ResetContext(); + + application.GetCore().RecoverFromContextLoss(); // start the recovery process + application.SendNotification(); + + // Run update/render loop + application.Render(16); + application.SendNotification(); + + // Expect new load request + DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + + // Finish loading image + LoadBitmapResource(platform); + ids.clear(); + ids.push_back( 57 ); + glAbstraction.SetNextTextureIds(ids); + + // Run update/render loop + application.Render(16); + application.SendNotification(); + + // Expect new GenTextures + DALI_TEST_CHECK( textureTrace.FindMethod("GenTextures") ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-ImageActor.cpp b/automated-tests/src/dali/utc-Dali-ImageActor.cpp new file mode 100644 index 0000000..6c44479 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-ImageActor.cpp @@ -0,0 +1,1653 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include "dali-test-suite-utils/dali-test-suite-utils.h" + +using namespace Dali; + +static const char* TestImageFilename = "icon_wrt.png"; + +void image_actor_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void image_actor_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +int UtcDaliImageActorConstructorVoid(void) +{ + TestApplication application; + tet_infoline("Testing Dali::ImageActor::ImageActor()"); + + ImageActor actor; + + DALI_TEST_CHECK(!actor); + END_TEST; +} + +int UtcDaliImageActorDestructor(void) +{ + TestApplication application; + + ImageActor* actor = new ImageActor(); + delete actor; + + DALI_TEST_CHECK( true ); + END_TEST; +} + +int UtcDaliImageActorNew01(void) +{ + TestApplication application; + tet_infoline("Positive test for Dali::ImageActor::New()"); + + Image image = ResourceImage::New(TestImageFilename); + ImageActor actor = ImageActor::New(image); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + DALI_TEST_CHECK(application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc)); + + DALI_TEST_CHECK(actor); + END_TEST; +} + +int UtcDaliImageActorNew02(void) +{ + TestApplication application; + tet_infoline("Negative test for Dali::ImageActor::New()"); + + Image image = ResourceImage::New("hopefully-this-image-file-does-not-exist"); + ImageActor actor = ImageActor::New(image); + + DALI_TEST_CHECK(actor); + END_TEST; +} + +int UtcDaliImageActorDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::ImageActor::DownCast()"); + + Image image = ResourceImage::New("IncorrectImageName"); + ImageActor actor1 = ImageActor::New(image); + Actor anActor = Actor::New(); + anActor.Add(actor1); + + Actor child = anActor.GetChildAt(0); + ImageActor imageActor = DownCast< ImageActor >(child); + + DALI_TEST_CHECK(imageActor); + END_TEST; +} + +int UtcDaliImageActorDownCast2(void) +{ + TestApplication application; + tet_infoline("Testing Dali::ImageActor::DownCast()"); + + Actor actor1 = Actor::New(); + Actor anActor = Actor::New(); + anActor.Add(actor1); + + Actor child = anActor.GetChildAt(0); + ImageActor imageActor = ImageActor::DownCast(child); + DALI_TEST_CHECK(!imageActor); + + Actor unInitialzedActor; + imageActor = ImageActor::DownCast( unInitialzedActor ); + DALI_TEST_CHECK(!imageActor); + END_TEST; +} + +int UtcDaliImageActorCopyConstructor(void) +{ + TestApplication application; + tet_infoline("Testing Dali::ImageActor::ImageActor(const ImageActor& )"); + + Image image = ResourceImage::New("IncorrectImageName"); + ImageActor actor1 = ImageActor::New(image); + + ImageActor actor2(actor1); + DALI_TEST_CHECK(actor2); + DALI_TEST_EQUALS( actor2, actor1, TEST_LOCATION ); + DALI_TEST_EQUALS( actor2.GetImage(), image, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliImageActor9Patch(void) +{ + TestApplication application; + tet_infoline("Positive test for Dali::ImageActor:: 9 patch api"); + + Image image = ResourceImage::New(TestImageFilename); + ImageActor actor = ImageActor::New(image); + + actor.SetStyle(ImageActor::STYLE_NINE_PATCH); + Vector4 border(0.1,0.2,0.3,0.4); + actor.SetNinePatchBorder(border); + + DALI_TEST_EQUALS( 0.1f, actor.GetNinePatchBorder().x, TEST_LOCATION ); + DALI_TEST_EQUALS( 0.2f, actor.GetNinePatchBorder().y, TEST_LOCATION ); + DALI_TEST_EQUALS( 0.3f, actor.GetNinePatchBorder().z, TEST_LOCATION ); + DALI_TEST_EQUALS( 0.4f, actor.GetNinePatchBorder().w, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorPixelArea(void) +{ + TestApplication application; + tet_infoline("Positive test for Dali::ImageActor::UtcDaliImageActorPixelArea"); + + BufferImage img = BufferImage::New( 10, 10 ); + ImageActor actor = ImageActor::New( img ); + + ImageActor::PixelArea area( 1, 2, 3, 4 ); + actor.SetPixelArea( area ); + + DALI_TEST_EQUALS( 1, actor.GetPixelArea().x, TEST_LOCATION ); + DALI_TEST_EQUALS( 2, actor.GetPixelArea().y, TEST_LOCATION ); + DALI_TEST_EQUALS( 3, actor.GetPixelArea().width, TEST_LOCATION ); + DALI_TEST_EQUALS( 4, actor.GetPixelArea().height, TEST_LOCATION ); + + ImageActor actor2 = ImageActor::New( img, ImageActor::PixelArea( 5, 6, 7, 8 ) ); + + DALI_TEST_EQUALS( 5, actor2.GetPixelArea().x, TEST_LOCATION ); + DALI_TEST_EQUALS( 6, actor2.GetPixelArea().y, TEST_LOCATION ); + DALI_TEST_EQUALS( 7, actor2.GetPixelArea().width, TEST_LOCATION ); + DALI_TEST_EQUALS( 8, actor2.GetPixelArea().height, TEST_LOCATION ); + END_TEST; +} + +// Set a size that is too large on an Image with a shader that requires grid +int UtcDaliImageActorSetSize01(void) +{ + TestApplication application; + + BufferImage img = BufferImage::New( 1,1 ); + ImageActor actor = ImageActor::New( img ); + + ShaderEffect effect = ShaderEffect::New( " ", " ", ShaderEffect::HINT_GRID ); + actor.SetShaderEffect( effect ); + + const float INVALID_SIZE = float(1u<<31); + Vector3 vector( INVALID_SIZE, INVALID_SIZE, INVALID_SIZE ); + + DALI_TEST_CHECK(vector != actor.GetCurrentSize()); + + actor.SetSize(vector); + Stage::GetCurrent().Add(actor); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS(vector, actor.GetCurrentSize(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorGetCurrentSize01(void) +{ + TestApplication application; + tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize"); + + Vector2 initialImageSize(100, 50); + BufferImage image = BufferImage::New( initialImageSize.width, initialImageSize.height ); + ImageActor actor = ImageActor::New( image ); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), initialImageSize, TEST_LOCATION ); + + Vector2 size(200.0f, 200.0f); + actor.SetSize(size); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), size, TEST_LOCATION ); + + size.x = 200.0f; + size.y = 200.0f; + actor.SetSize(size); + application.Render(8); + + // Test when a pixel area is set + ImageActor::PixelArea area(0, 0, 10, 10); + actor.SetPixelArea(area); + application.Render(9); + // natural size is not used as setsize is called + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), size, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliImageActorGetCurrentSize02(void) +{ + TestApplication application; + tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize - Test that using an image resource sets the actor size with it's natural size immediately rather than on load"); + + Vector2 initialImageSize(100, 50); + + application.GetPlatform().SetClosestImageSize(initialImageSize); + + Image image = ResourceImage::New("image.jpg"); + ImageActor actor = ImageActor::New( image ); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), initialImageSize, TEST_LOCATION ); + + // Now complete the image load + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, initialImageSize.width,initialImageSize.height, initialImageSize.width,initialImageSize.height ); + + Integration::ResourcePointer resourcePtr(bitmap); // reference it + application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr); + application.Render(); // Process LoadComplete + application.SendNotification(); // Process event messages + application.GetPlatform().DiscardRequest(); // Ensure load request is discarded + application.GetPlatform().ClearReadyResources(); // + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), initialImageSize, TEST_LOCATION ); + + Vector2 size(200.0f, 200.0f); + actor.SetSize(size); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), size, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliImageActorGetCurrentSize03(void) +{ + TestApplication application; + tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize - Test that using an image resource with a requested size sets the actor size with it's nearest size immediately rather than on load"); + + const Vector2 closestImageSize( 80, 45); + application.GetPlatform().SetClosestImageSize(closestImageSize); + + Vector2 requestedSize( 40, 30 ); + Image image = ResourceImage::New("image.jpg", ImageDimensions( requestedSize.x, requestedSize.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT ); + ImageActor actor = ImageActor::New( image ); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION ); + + // Now complete the image load + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height ); + + Integration::ResourcePointer resourcePtr(bitmap); // reference it + application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr); + application.Render(); // Process LoadComplete + application.SendNotification(); // Process event messages + application.GetPlatform().DiscardRequest(); // Ensure load request is discarded + application.GetPlatform().ClearReadyResources(); // + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliImageActorGetCurrentSize04(void) +{ + TestApplication application; + tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize - check a new image doesn't change a set actor size"); + + const Vector2 closestImageSize( 80, 45); + application.GetPlatform().SetClosestImageSize(closestImageSize); + + Vector2 requestedSize( 40, 30 ); + Image image = ResourceImage::New("image.jpg", ImageDimensions( requestedSize.x, requestedSize.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT ); + ImageActor actor = ImageActor::New( image ); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION ); + + // Now complete the image load + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height ); + + Integration::ResourcePointer resourcePtr(bitmap); // reference it + application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr); + application.Render(); // Process LoadComplete + application.SendNotification(); // Process event messages + application.GetPlatform().DiscardRequest(); // Ensure load request is discarded + application.GetPlatform().ClearReadyResources(); // + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION ); + + Vector2 size(200.0f, 200.0f); + actor.SetSize(size); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), size, TEST_LOCATION ); + + // Load a different image + + Vector2 image2ClosestSize = Vector2(240, 150); // The actual size image loader will return for the request below + application.GetPlatform().SetClosestImageSize(image2ClosestSize); + + const Vector2 request2Size( 100, 100 ); + Image image2 = ResourceImage::New("image.jpg", ImageDimensions( request2Size.x, request2Size.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT ); + actor.SetImage(image2); + + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + + // Ensure the actor size is kept + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), size, TEST_LOCATION ); + + // Now complete the image load + req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap2->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, image2ClosestSize.width, image2ClosestSize.height, image2ClosestSize.width, image2ClosestSize.height ); + + Integration::ResourcePointer resourcePtr2(bitmap2); // reference it + application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr2); + application.Render(); // Process LoadComplete + application.SendNotification(); // Process event messages + application.GetPlatform().DiscardRequest(); // Ensure load request is discarded + application.GetPlatform().ClearReadyResources(); // + + // Ensure the actor size is kept + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), size, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliImageActorGetCurrentSize05(void) +{ + TestApplication application; + tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize - check a new image doens't change actor size until load complete"); + + Vector2 closestImageSize( 80, 45); + application.GetPlatform().SetClosestImageSize(closestImageSize); + + Vector2 requestedSize( 40, 30 ); + Image image = ResourceImage::New("image.jpg", ImageDimensions( requestedSize.x, requestedSize.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT ); + ImageActor actor = ImageActor::New( image ); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION ); + + // Now complete the image load + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height ); + + Integration::ResourcePointer resourcePtr(bitmap); // reference it + application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr); + application.Render(); // Process LoadComplete + application.SendNotification(); // Process event messages + application.GetPlatform().DiscardRequest(); // Ensure load request is discarded + application.GetPlatform().ClearReadyResources(); // + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION ); + + // Load a different image + + Vector2 image2ClosestSize = Vector2(240, 150); + application.GetPlatform().SetClosestImageSize(image2ClosestSize); + + const Vector2 requestedSize2( 100, 100 ); + Image image2 = ResourceImage::New("image.jpg", ImageDimensions( requestedSize2.x, requestedSize2.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT ); + actor.SetImage(image2); + + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + + // Ensure the actor size is kept + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize2, TEST_LOCATION ); + + // Now complete the image load + req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap2->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, image2ClosestSize.width, image2ClosestSize.height, image2ClosestSize.width, image2ClosestSize.height ); + + Integration::ResourcePointer resourcePtr2(bitmap2); // reference it + application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr2); + application.Render(); // Process LoadComplete + application.SendNotification(); // Process event messages + application.GetPlatform().DiscardRequest(); // Ensure load request is discarded + application.GetPlatform().ClearReadyResources(); // + + application.SendNotification(); // Process event messages + application.Render(); // Process LoadComplete + + // Ensure the actor size gets the new image's natural size + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize2, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorNaturalPixelAreaSize01(void) +{ + TestApplication application; + tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize - check a new image doens't change actor size until load complete"); + +//If an image is loaded without setting size, then the actor gets the natural size of the image +//Setting the pixel area will change the actor size to match the pixel area +//Setting the actor size will not change pixel area, and will cause the partial image to stretch +//to the new size. +//Clearing the pixel area will not change actor size, and the actor will show the whole image. + + + Vector2 closestImageSize( 80, 45); + application.GetPlatform().SetClosestImageSize(closestImageSize); + + Vector2 requestedSize( 40, 30 ); + Image image = ResourceImage::New("image.jpg", ImageDimensions( requestedSize.x, requestedSize.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT ); + ImageActor actor = ImageActor::New( image ); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION ); + + // Now complete the image load + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height ); + + Integration::ResourcePointer resourcePtr(bitmap); // reference it + application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr); + application.Render(); // Process LoadComplete + application.SendNotification(); // Process event messages + application.GetPlatform().DiscardRequest(); // Ensure load request is discarded + application.GetPlatform().ClearReadyResources(); // + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION ); + + // Set a pixel area on a naturally sized actor - expect the actor to take the + // pixel area as size + actor.SetPixelArea(ImageActor::PixelArea(0, 0, 30, 30)); + application.SendNotification(); // Process event messages + application.Render(); // Process LoadComplete + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), Vector2(30, 30), TEST_LOCATION ); + + // Set a size. Expect the partial image to stretch to fill the new size + actor.SetSize(100, 100); + application.SendNotification(); // Process event messages + application.Render(); // Process LoadComplete + application.Render(); // Process LoadComplete + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), Vector2(100, 100), TEST_LOCATION ); + + // Clear the pixel area. Expect the whole image to be shown, filling the set size. + actor.SetPixelArea( ImageActor::PixelArea( 0, 0, image.GetWidth(), image.GetHeight()) ); + application.SendNotification(); // Process event messages + application.Render(); // Process LoadComplete + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), Vector2(100, 100), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorNaturalPixelAreaSize02(void) +{ + TestApplication application; + tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize - check a new image doens't change actor size until load complete"); + +//If an image is loaded without setting size, then the actor gets the natural size of the image +//Setting the pixel area will change the actor size to match the pixel area +//Setting the actor size will not change pixel area, and will cause the partial image to stretch +//to the new size. +//Clearing the pixel area will not change actor size, and the actor will show the whole image. + + + Vector2 closestImageSize( 80, 45); + application.GetPlatform().SetClosestImageSize(closestImageSize); + + Vector2 requestedSize( 40, 30 ); + Image image = ResourceImage::New("image.jpg", ImageDimensions( requestedSize.x, requestedSize.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT ); + ImageActor actor = ImageActor::New( image ); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); // Flush update messages + application.Render(); // Process resource request + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION ); + + // Now complete the image load + Integration::ResourceRequest* req = application.GetPlatform().GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height ); + + Integration::ResourcePointer resourcePtr(bitmap); // reference it + application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr); + application.Render(); // Process LoadComplete + application.SendNotification(); // Process event messages + application.GetPlatform().DiscardRequest(); // Ensure load request is discarded + application.GetPlatform().ClearReadyResources(); // + + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION ); + + // Set a pixel area on a naturally sized actor - expect the actor to take the + // pixel area as size + actor.SetPixelArea(ImageActor::PixelArea(0, 0, 30, 30)); + application.SendNotification(); // Process event messages + application.Render(); // Process LoadComplete + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), Vector2(30, 30), TEST_LOCATION ); + + // Clear the pixel area. Expect the whole image to be shown, changing actor size + actor.SetPixelArea( ImageActor::PixelArea( 0, 0, image.GetWidth(), image.GetHeight()) ); + application.SendNotification(); // Process event messages + application.Render(); // Process LoadComplete + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION ); + + // Set a size. Expect the partial image to stretch to fill the new size + actor.SetSize(100, 100); + application.SendNotification(); // Process event messages + application.Render(); // Process LoadComplete + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), Vector2(100, 100), TEST_LOCATION ); + + // Set a pixel area, don't expect size to change + actor.SetPixelArea(ImageActor::PixelArea(0, 0, 40, 40)); + application.SendNotification(); // Process event messages + application.Render(); // Process LoadComplete + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), Vector2(100, 100), TEST_LOCATION ); + + // Clearing pixel area should change actor size to image size + actor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); + actor.SetPixelArea( ImageActor::PixelArea( 0, 0, image.GetWidth(), image.GetHeight()) ); + application.SendNotification(); // Process event messages + application.Render(); // Process LoadComplete + DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION ); + END_TEST; +} + + + +int UtcDaliImageActorDefaultProperties(void) +{ + TestApplication application; + tet_infoline("Testing Dali::ImageActor DefaultProperties"); + + BufferImage img = BufferImage::New( 10, 10 ); + ImageActor actor = ImageActor::New( img ); + + std::vector indices; + indices.push_back(ImageActor::Property::PIXEL_AREA ); + indices.push_back(ImageActor::Property::STYLE ); + indices.push_back(ImageActor::Property::BORDER ); + indices.push_back(ImageActor::Property::IMAGE ); + + DALI_TEST_CHECK(actor.GetPropertyCount() == ( Actor::New().GetPropertyCount() + indices.size() ) ); + + for(std::vector::iterator iter = indices.begin(); iter != indices.end(); ++iter) + { + DALI_TEST_CHECK( *iter == actor.GetPropertyIndex(actor.GetPropertyName(*iter)) ); + DALI_TEST_CHECK( actor.IsPropertyWritable(*iter) ); + DALI_TEST_CHECK( !actor.IsPropertyAnimatable(*iter) ); + DALI_TEST_CHECK( actor.GetPropertyType(*iter) == actor.GetPropertyType(*iter) ); // just checking call succeeds + } + + // set/get one of them + actor.SetPixelArea(ImageActor::PixelArea( 0, 0, 0, 0 )); + + ImageActor::PixelArea area( 1, 2, 3, 4 ); + actor.SetProperty(ImageActor::Property::PIXEL_AREA, Property::Value(Rect(area))); + + DALI_TEST_CHECK(Property::RECTANGLE == actor.GetPropertyType(ImageActor::Property::PIXEL_AREA)); + + Property::Value v = actor.GetProperty(ImageActor::Property::PIXEL_AREA); + + DALI_TEST_CHECK(v.Get >() == area); + + END_TEST; +} + +int UtcDaliImageActorUseImageAlpha01(void) +{ + TestApplication application; + + tet_infoline("Testing Dali::RenderableActor::SetUseImageAlpha()"); + + BufferImage image = BufferImage::New( 100, 50 ); + ImageActor actor = ImageActor::New( image ); + actor.SetBlendMode( BlendingMode::ON ); + actor.SetSize(100, 50); + application.GetGlAbstraction().EnableCullFaceCallTrace(true); // For Enable(GL_BLEND) + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + const TraceCallStack& callTrace = application.GetGlAbstraction().GetCullFaceTrace(); + DALI_TEST_EQUALS( BlendEnabled( callTrace), true, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendDisabled( callTrace ), false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorUseImageAlpha02(void) +{ + TestApplication application; + + tet_infoline("Testing Dali::RenderableActor::SetUseImageAlpha()"); + + BufferImage image = BufferImage::New( 100, 50 ); + ImageActor actor = ImageActor::New( image ); + actor.SetBlendMode( BlendingMode::OFF ); + actor.SetSize(100, 50); + application.GetGlAbstraction().EnableCullFaceCallTrace(true); // For Enable(GL_BLEND) + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + const TraceCallStack& callTrace = application.GetGlAbstraction().GetCullFaceTrace(); + DALI_TEST_EQUALS( BlendDisabled( callTrace ), false, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendEnabled( callTrace), false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorUseImageAlpha03(void) +{ + TestApplication application; + + tet_infoline("Testing Dali::RenderableActor::SetUseImageAlpha()"); + + BufferImage image = BufferImage::New( 100, 50 ); + ImageActor actor = ImageActor::New( image ); + actor.SetBlendMode( BlendingMode::AUTO ); + actor.SetColor(Vector4(1.0, 1.0, 1.0, 0.5)); + actor.SetSize(100, 50); + application.GetGlAbstraction().EnableCullFaceCallTrace(true); // For Enable(GL_BLEND) + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + const TraceCallStack& callTrace = application.GetGlAbstraction().GetCullFaceTrace(); + DALI_TEST_EQUALS( BlendDisabled( callTrace ), false, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendEnabled( callTrace), true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorUseImageAlpha04(void) +{ + TestApplication application; + + tet_infoline("Testing Dali::RenderableActor::SetUseImageAlpha()"); + + FrameBufferImage image = FrameBufferImage::New( 100, 50, Pixel::RGBA8888 ); + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask task = taskList.GetTask( 0u ); + task.SetTargetFrameBuffer( image ); // To ensure frame buffer is connected + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + application.SendNotification(); + application.Render(0); + + ImageActor actor = ImageActor::New( image ); + application.SendNotification(); + application.Render(0); + + actor.SetBlendMode( BlendingMode::ON ); + actor.SetColor(Vector4(1.0, 1.0, 1.0, 1.0)); + actor.SetSize(100, 50); + application.GetGlAbstraction().EnableCullFaceCallTrace(true); // For Enable(GL_BLEND) + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + const TraceCallStack& callTrace = application.GetGlAbstraction().GetCullFaceTrace(); + DALI_TEST_EQUALS( BlendDisabled( callTrace ), false, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendEnabled( callTrace), true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorUseImageAlpha05(void) +{ + TestApplication application; + + tet_infoline("Testing Dali::RenderableActor::SetUseImageAlpha()"); + + BufferImage image = BufferImage::New( 100, 50, Pixel::RGB888 ); + ImageActor actor = ImageActor::New( image ); + actor.SetBlendMode( BlendingMode::AUTO ); + actor.SetColor(Vector4(1.0, 1.0, 1.0, 1.0)); + actor.SetSize(100, 50); + application.GetGlAbstraction().EnableCullFaceCallTrace(true); // For Enable(GL_BLEND) + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + const TraceCallStack& callTrace = application.GetGlAbstraction().GetCullFaceTrace(); + DALI_TEST_EQUALS( BlendDisabled( callTrace ), false, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendEnabled( callTrace), false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageGetStyle(void) +{ + TestApplication application; + + Image image = ResourceImage::New(TestImageFilename); + ImageActor actor = ImageActor::New(image); + + actor.SetStyle(ImageActor::STYLE_NINE_PATCH); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( ImageActor::STYLE_NINE_PATCH, actor.GetStyle(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageSetNinePatchBorder(void) +{ + TestApplication application; + + Image image = ResourceImage::New(TestImageFilename); + ImageActor actor = ImageActor::New(image); + + actor.SetStyle(ImageActor::STYLE_NINE_PATCH); + actor.SetNinePatchBorder(Vector4( 1.0f, 2.0f, 3.0f, 4.0f)); + + DALI_TEST_EQUALS( 1.0f, actor.GetNinePatchBorder().x, TEST_LOCATION ); + DALI_TEST_EQUALS( 2.0f, actor.GetNinePatchBorder().y, TEST_LOCATION ); + DALI_TEST_EQUALS( 3.0f, actor.GetNinePatchBorder().z, TEST_LOCATION ); + DALI_TEST_EQUALS( 4.0f, actor.GetNinePatchBorder().w, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorNewNull(void) +{ + TestApplication application; + + ImageActor actor = ImageActor::New(Image()); + + DALI_TEST_CHECK(actor); + END_TEST; +} + +int UtcDaliImageActorNewNullWithArea(void) +{ + TestApplication application; + + ImageActor::PixelArea area( 1, 2, 3, 4 ); + + ImageActor actor = ImageActor::New(Image(), area); + + DALI_TEST_CHECK(actor); + END_TEST; +} + +int UtcDaliImageActorSetImage(void) +{ + TestApplication application; + + ImageActor actor = ImageActor::New(Image()); + + DALI_TEST_CHECK(actor); + + actor.SetImage( Image() ); + + DALI_TEST_CHECK(!actor.GetImage()); + END_TEST; +} + +int UtcDaliImageActorPropertyIndices(void) +{ + TestApplication application; + Actor basicActor = Actor::New(); + ImageActor imageActor = ImageActor::New(); + + Property::IndexContainer indices; + imageActor.GetPropertyIndices( indices ); + DALI_TEST_CHECK( indices.Size() > basicActor.GetPropertyCount() ); + DALI_TEST_EQUALS( indices.Size(), imageActor.GetPropertyCount(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorImageProperty(void) +{ + TestApplication application; + Image image = ResourceImage::New( "MY_PATH" ); + ImageActor imageActor = ImageActor::New( image ); + + Stage::GetCurrent().Add( imageActor ); + application.SendNotification(); + application.Render(); + + Property::Value imageProperty = imageActor.GetProperty( ImageActor::Property::IMAGE ); + Property::Map* imageMap = imageProperty.GetMap(); + DALI_TEST_CHECK( imageMap != NULL ); + DALI_TEST_CHECK( NULL != imageMap->Find( "filename" ) ); + DALI_TEST_EQUALS( (*imageMap)[ "filename" ].Get< std::string >(), "MY_PATH", TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorNinePatch01(void) +{ + TestApplication application; + TestPlatformAbstraction& platform = application.GetPlatform(); + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + + tet_infoline("Test the successful loading of a nine-patch image\n"); + + platform.SetClosestImageSize(Vector2(4, 4)); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + Integration::PixelBuffer* pixels = bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 4,4,4,4 ); + memset( pixels, 0, 64 ); + + Integration::ResourcePointer resourcePtr(bitmap); // reference it + platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr ); + + Image ninePatchImage = ResourceImage::New( "blah.#.png" ); + DALI_TEST_CHECK( ninePatchImage ); + + ImageActor imageActor = ImageActor::New( ninePatchImage ); + DALI_TEST_CHECK( imageActor ); + Stage::GetCurrent().Add( imageActor ); + + drawTrace.Reset(); + textureTrace.Reset(); + drawTrace.Enable(true); + textureTrace.Enable(true); + glAbstraction.ClearBoundTextures(); + std::vector ids; + ids.push_back( 23 ); + glAbstraction.SetNextTextureIds( ids ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) ); + typedef std::vector TexVec; + const TexVec& textures = glAbstraction.GetBoundTextures(GL_TEXTURE0); + DALI_TEST_CHECK( textures.size() > 0 ); + if( textures.size() > 0 ) + { + DALI_TEST_EQUALS( textures[0], 23u, TEST_LOCATION ); + } + + END_TEST; +} + + +int UtcDaliImageActorNinePatch02(void) +{ + TestApplication application; + TestPlatformAbstraction& platform = application.GetPlatform(); + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + + tet_infoline("Test the failed loading of a nine-patch image\n"); + + platform.SetClosestImageSize(Vector2(0, 0)); + Integration::ResourcePointer resourcePtr; + platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr ); + + Image ninePatchImage = ResourceImage::New( "blah.#.png" ); + DALI_TEST_CHECK( ninePatchImage ); + + ImageActor imageActor = ImageActor::New( ninePatchImage ); + DALI_TEST_CHECK( imageActor ); + Stage::GetCurrent().Add( imageActor ); + + drawTrace.Reset(); + textureTrace.Reset(); + drawTrace.Enable(true); + textureTrace.Enable(true); + glAbstraction.ClearBoundTextures(); + std::vector ids; + ids.push_back( 23 ); + glAbstraction.SetNextTextureIds( ids ); + + application.SendNotification(); + application.Render(); + + // Check that nothing was drawn. + DALI_TEST_CHECK( ! drawTrace.FindMethod( "DrawArrays" ) ); + typedef std::vector TexVec; + const TexVec& textures = glAbstraction.GetBoundTextures(GL_TEXTURE0); + DALI_TEST_CHECK( textures.size() == 0u ); + + END_TEST; +} + + +int UtcDaliImageActorNinePatch03(void) +{ + TestApplication application; + TestPlatformAbstraction& platform = application.GetPlatform(); + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + + tet_infoline("Test the successful loading of a nine-patch image added using ImageActor::SetImage()\n"); + + platform.SetClosestImageSize(Vector2(4, 4)); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + Integration::PixelBuffer* pixels = bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 4,4,4,4 ); + memset( pixels, 0, 64 ); + + Integration::ResourcePointer resourcePtr(bitmap); // reference it + platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr ); + + Image ninePatchImage = ResourceImage::New( "blah.#.png" ); + DALI_TEST_CHECK( ninePatchImage ); + + ImageActor imageActor = ImageActor::New(); + DALI_TEST_CHECK( imageActor ); + Stage::GetCurrent().Add( imageActor ); + + imageActor.SetImage( ninePatchImage ); + + drawTrace.Reset(); + textureTrace.Reset(); + drawTrace.Enable(true); + textureTrace.Enable(true); + glAbstraction.ClearBoundTextures(); + std::vector ids; + ids.push_back( 23 ); + glAbstraction.SetNextTextureIds( ids ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) ); + typedef std::vector TexVec; + const TexVec& textures = glAbstraction.GetBoundTextures(GL_TEXTURE0); + DALI_TEST_CHECK( textures.size() > 0 ); + if( textures.size() > 0 ) + { + DALI_TEST_EQUALS( textures[0], 23u, TEST_LOCATION ); + } + + END_TEST; +} + + +int UtcDaliImageActorNinePatch04(void) +{ + TestApplication application; + TestPlatformAbstraction& platform = application.GetPlatform(); + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + TraceCallStack& textureTrace = glAbstraction.GetTextureTrace(); + TraceCallStack& drawTrace = glAbstraction.GetDrawTrace(); + + tet_infoline("Test the failed loading of a nine-patch image using ImageActor::SetImage()\n"); + + platform.SetClosestImageSize(Vector2(0, 0)); + Integration::ResourcePointer resourcePtr; + platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr ); + + Image ninePatchImage = ResourceImage::New( "blah.#.png" ); + DALI_TEST_CHECK( ninePatchImage ); + + ImageActor imageActor = ImageActor::New(); + DALI_TEST_CHECK( imageActor ); + Stage::GetCurrent().Add( imageActor ); + + imageActor.SetImage( ninePatchImage ); + + drawTrace.Reset(); + textureTrace.Reset(); + drawTrace.Enable(true); + textureTrace.Enable(true); + glAbstraction.ClearBoundTextures(); + std::vector ids; + ids.push_back( 23 ); + glAbstraction.SetNextTextureIds( ids ); + + application.SendNotification(); + application.Render(); + + // Check that nothing was drawn. + DALI_TEST_CHECK( ! drawTrace.FindMethod( "DrawArrays" ) ); + typedef std::vector TexVec; + const TexVec& textures = glAbstraction.GetBoundTextures(GL_TEXTURE0); + DALI_TEST_CHECK( textures.size() == 0u ); + + END_TEST; +} + +int UtcDaliImageActorGetNaturalSize(void) +{ + TestApplication application; + + // Standard image + BufferImage img = BufferImage::New( 10, 10 ); + ImageActor actor = ImageActor::New( img ); + + DALI_TEST_CHECK( actor.GetNaturalSize().GetVectorXY() == Vector2( 10, 10 ) ); + + // Pixel area set + ImageActor::PixelArea area( 1, 2, 3, 4 ); + actor.SetPixelArea( area ); + + DALI_TEST_CHECK( actor.GetNaturalSize().GetVectorXY() == Vector2( 3, 4 ) ); + + END_TEST; +} + +int UtcDaliImageActorGetSortModifier(void) +{ + TestApplication application; + + tet_infoline("Testing Dali::ImageActor::GetSortModifier()"); + + ImageActor actor = ImageActor::New(); + Stage::GetCurrent().Add(actor); + + DALI_TEST_EQUALS(actor.GetSortModifier(), 0.0f, TEST_LOCATION); + + Stage::GetCurrent().Remove(actor); + END_TEST; +} + +int UtcDaliImageActorSetGetBlendMode(void) +{ + TestApplication application; + + tet_infoline("Testing Dali::ImageActor::SetBlendMode() / Dali::ImageActor::GetBlendMode()"); + + ImageActor actor = ImageActor::New(); + + actor.SetBlendMode( BlendingMode::OFF ); + DALI_TEST_CHECK( BlendingMode::OFF == actor.GetBlendMode() ); + + actor.SetBlendMode( BlendingMode::AUTO ); + DALI_TEST_CHECK( BlendingMode::AUTO == actor.GetBlendMode() ); + + actor.SetBlendMode( BlendingMode::ON ); + DALI_TEST_CHECK( BlendingMode::ON == actor.GetBlendMode() ); + END_TEST; +} + +int UtcDaliImageActorSetGetBlendFunc(void) +{ + TestApplication application; + TestGlAbstraction& glAbstraction = application.GetGlAbstraction(); + + tet_infoline("Testing Dali::ImageActor::UtcDaliImageActorSetGetBlendFunc()"); + + BufferImage img = BufferImage::New( 1,1 ); + ImageActor actor = ImageActor::New( img ); + Stage::GetCurrent().Add( actor ); + application.SendNotification(); + application.Render(); + + // Test the defaults as documented int blending.h + { + BlendingFactor::Type srcFactorRgb( BlendingFactor::ZERO ); + BlendingFactor::Type destFactorRgb( BlendingFactor::ZERO ); + BlendingFactor::Type srcFactorAlpha( BlendingFactor::ZERO ); + BlendingFactor::Type destFactorAlpha( BlendingFactor::ZERO ); + actor.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha ); + DALI_TEST_EQUALS( BlendingFactor::SRC_ALPHA, srcFactorRgb, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_SRC_ALPHA, destFactorRgb, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::ONE, srcFactorAlpha, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_SRC_ALPHA, destFactorAlpha, TEST_LOCATION ); + } + + // Set to non-default values + actor.SetBlendFunc( BlendingFactor::ONE_MINUS_SRC_COLOR, BlendingFactor::SRC_ALPHA_SATURATE, BlendingFactor::ONE_MINUS_SRC_COLOR, BlendingFactor::SRC_ALPHA_SATURATE ); + + // Test that Set was successful + { + BlendingFactor::Type srcFactorRgb( BlendingFactor::ZERO ); + BlendingFactor::Type destFactorRgb( BlendingFactor::ZERO ); + BlendingFactor::Type srcFactorAlpha( BlendingFactor::ZERO ); + BlendingFactor::Type destFactorAlpha( BlendingFactor::ZERO ); + actor.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha ); + DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_SRC_COLOR, srcFactorRgb, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::SRC_ALPHA_SATURATE, destFactorRgb, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_SRC_COLOR, srcFactorAlpha, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::SRC_ALPHA_SATURATE, destFactorAlpha, TEST_LOCATION ); + } + + // Render & check GL commands + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_SRC_COLOR, glAbstraction.GetLastBlendFuncSrcRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_SRC_ALPHA_SATURATE, glAbstraction.GetLastBlendFuncDstRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_SRC_COLOR, glAbstraction.GetLastBlendFuncSrcAlpha(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_SRC_ALPHA_SATURATE, glAbstraction.GetLastBlendFuncDstAlpha(), TEST_LOCATION ); + + // Set using separate alpha settings + actor.SetBlendFunc( BlendingFactor::CONSTANT_COLOR, BlendingFactor::ONE_MINUS_CONSTANT_COLOR, + BlendingFactor::CONSTANT_ALPHA, BlendingFactor::ONE_MINUS_CONSTANT_ALPHA ); + + // Test that Set was successful + { + BlendingFactor::Type srcFactorRgb( BlendingFactor::ZERO ); + BlendingFactor::Type destFactorRgb( BlendingFactor::ZERO ); + BlendingFactor::Type srcFactorAlpha( BlendingFactor::ZERO ); + BlendingFactor::Type destFactorAlpha( BlendingFactor::ZERO ); + actor.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha ); + DALI_TEST_EQUALS( BlendingFactor::CONSTANT_COLOR, srcFactorRgb, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_CONSTANT_COLOR, destFactorRgb, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::CONSTANT_ALPHA, srcFactorAlpha, TEST_LOCATION ); + DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_CONSTANT_ALPHA, destFactorAlpha, TEST_LOCATION ); + } + + // Render & check GL commands + application.SendNotification(); + application.Render(); + DALI_TEST_EQUALS( (GLenum)GL_CONSTANT_COLOR, glAbstraction.GetLastBlendFuncSrcRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_CONSTANT_COLOR, glAbstraction.GetLastBlendFuncDstRgb(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_CONSTANT_ALPHA, glAbstraction.GetLastBlendFuncSrcAlpha(), TEST_LOCATION ); + DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_CONSTANT_ALPHA, glAbstraction.GetLastBlendFuncDstAlpha(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorSetGetAlpha(void) +{ + TestApplication application; + + tet_infoline("Testing Dali::ImageActor::SetGetAlpha()"); + + BufferImage img = BufferImage::New( 1,1 ); + ImageActor actor = ImageActor::New( img ); + Stage::GetCurrent().Add( actor ); + application.SendNotification(); + application.Render(); + + // use the image alpha on actor + actor.SetBlendMode(BlendingMode::ON); + + // Test that Set was successful + DALI_TEST_EQUALS( BlendingMode::ON, actor.GetBlendMode(), TEST_LOCATION ); + + // Now test that it can be set to false + actor.SetBlendMode(BlendingMode::OFF); + DALI_TEST_EQUALS(BlendingMode::OFF, actor.GetBlendMode(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliImageActorSetGetFilterModes(void) +{ + TestApplication application; + + tet_infoline("Testing Dali::ImageActor::SetFilterMode() / Dali::ImageActor::GetFilterMode()"); + + ImageActor actor = ImageActor::New(); + + FilterMode::Type minifyFilter = FilterMode::NEAREST; + FilterMode::Type magnifyFilter = FilterMode::NEAREST; + + // Default test + actor.GetFilterMode( minifyFilter, magnifyFilter ); + DALI_TEST_CHECK( FilterMode::DEFAULT == minifyFilter ); + DALI_TEST_CHECK( FilterMode::DEFAULT == magnifyFilter ); + + // Default/Default + actor.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT ); + actor.GetFilterMode( minifyFilter, magnifyFilter ); + DALI_TEST_CHECK( FilterMode::DEFAULT == minifyFilter ); + DALI_TEST_CHECK( FilterMode::DEFAULT == magnifyFilter ); + + // Nearest/Nearest + actor.SetFilterMode( FilterMode::NEAREST, FilterMode::NEAREST ); + actor.GetFilterMode( minifyFilter, magnifyFilter ); + DALI_TEST_CHECK( FilterMode::NEAREST == minifyFilter ); + DALI_TEST_CHECK( FilterMode::NEAREST == magnifyFilter ); + + // Linear/Linear + actor.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR ); + actor.GetFilterMode( minifyFilter, magnifyFilter ); + DALI_TEST_CHECK( FilterMode::LINEAR == minifyFilter ); + DALI_TEST_CHECK( FilterMode::LINEAR == magnifyFilter ); + + // Nearest/Linear + actor.SetFilterMode( FilterMode::NEAREST, FilterMode::LINEAR ); + actor.GetFilterMode( minifyFilter, magnifyFilter ); + DALI_TEST_CHECK( FilterMode::NEAREST == minifyFilter ); + DALI_TEST_CHECK( FilterMode::LINEAR == magnifyFilter ); + + // Linear/Nearest + actor.SetFilterMode( FilterMode::LINEAR, FilterMode::NEAREST ); + actor.GetFilterMode( minifyFilter, magnifyFilter ); + DALI_TEST_CHECK( FilterMode::LINEAR == minifyFilter ); + DALI_TEST_CHECK( FilterMode::NEAREST == magnifyFilter ); + + END_TEST; +} + +int UtcDaliImageActorSetFilterMode(void) +{ + TestApplication application; + + tet_infoline("Testing Dali::ImageActor::SetFilterMode()"); + + BufferImage img = BufferImage::New( 1,1 ); + ImageActor actor = ImageActor::New( img ); + + actor.SetSize(100.0f, 100.0f); + actor.SetParentOrigin(ParentOrigin::CENTER); + actor.SetAnchorPoint(AnchorPoint::CENTER); + + Stage::GetCurrent().Add(actor); + + /**************************************************************/ + + // Default/Default + TraceCallStack& texParameterTrace = application.GetGlAbstraction().GetTexParameterTrace(); + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + actor.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + std::stringstream out; + + // Verify actor gl state + + // There are two calls to TexParameteri when the texture is first created + // Texture mag filter is not called as the first time set it uses the system default + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 3, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_LINEAR; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(2, "TexParameteri", out.str()), true, TEST_LOCATION); + + /**************************************************************/ + + // Default/Default + texParameterTrace = application.GetGlAbstraction().GetTexParameterTrace(); + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + actor.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify actor gl state + + // Should not make any calls when settings are the same + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 0, TEST_LOCATION); + + /**************************************************************/ + + // Nearest/Nearest + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + actor.SetFilterMode( FilterMode::NEAREST, FilterMode::NEAREST ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify actor gl state + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 2, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_NEAREST; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MAG_FILTER << ", " << GL_NEAREST; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(1, "TexParameteri", out.str()), true, TEST_LOCATION); + + /**************************************************************/ + + // Linear/Linear + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + actor.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify actor gl state + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 2, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_LINEAR; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MAG_FILTER << ", " << GL_LINEAR; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(1, "TexParameteri", out.str()), true, TEST_LOCATION); + + + /**************************************************************/ + + // Nearest/Linear + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + actor.SetFilterMode( FilterMode::NEAREST, FilterMode::LINEAR ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify actor gl state + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 1, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_NEAREST; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION); + + /**************************************************************/ + + // Default/Default + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + actor.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify actor gl state + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 1, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_LINEAR; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION); + + /**************************************************************/ + + // None/None + texParameterTrace.Reset(); + texParameterTrace.Enable( true ); + + actor.SetFilterMode( FilterMode::NONE, FilterMode::NONE ); + + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + texParameterTrace.Enable( false ); + + // Verify actor gl state + DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 1, TEST_LOCATION); + + out.str(""); + out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_NEAREST_MIPMAP_LINEAR; + DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION); + + /**************************************************************/ + + Stage::GetCurrent().Remove(actor); + + END_TEST; +} + +int UtcDaliImageActorSetShaderEffect(void) +{ + TestApplication application; + BufferImage img = BufferImage::New( 1,1 ); + ImageActor actor = ImageActor::New( img ); + Stage::GetCurrent().Add( actor ); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + GLuint lastShaderCompiledBefore = application.GetGlAbstraction().GetLastShaderCompiled(); + + application.GetGlAbstraction().EnableShaderCallTrace( true ); + + const std::string vertexShader = "UtcDaliImageActorSetShaderEffect-VertexSource"; + const std::string fragmentShader = "UtcDaliImageActorSetShaderEffect-FragmentSource"; + ShaderEffect effect = ShaderEffect::New(vertexShader, fragmentShader ); + DALI_TEST_CHECK( effect != actor.GetShaderEffect() ); + + actor.SetShaderEffect( effect ); + DALI_TEST_CHECK( effect == actor.GetShaderEffect() ); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + GLuint lastShaderCompiledAfter = application.GetGlAbstraction().GetLastShaderCompiled(); + DALI_TEST_EQUALS( lastShaderCompiledAfter, lastShaderCompiledBefore + 2, TEST_LOCATION ); + + std::string actualVertexShader = application.GetGlAbstraction().GetShaderSource( lastShaderCompiledBefore + 1 ); + DALI_TEST_EQUALS( vertexShader, + actualVertexShader.substr( actualVertexShader.length() - vertexShader.length() ), TEST_LOCATION ); + std::string actualFragmentShader = application.GetGlAbstraction().GetShaderSource( lastShaderCompiledBefore + 2 ); + DALI_TEST_EQUALS( fragmentShader, + actualFragmentShader.substr( actualFragmentShader.length() - fragmentShader.length() ), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliImageActorGetShaderEffect(void) +{ + TestApplication application; + ImageActor actor = ImageActor::New(); + + ShaderEffect effect = ShaderEffect::New("UtcDaliImageActorGetShaderEffect-VertexSource", "UtcDaliImageActorGetShaderEffect-FragmentSource" ); + actor.SetShaderEffect(effect); + + DALI_TEST_CHECK(effect == actor.GetShaderEffect()); + END_TEST; +} + +int UtcDaliImageActorRemoveShaderEffect01(void) +{ + TestApplication application; + ImageActor actor = ImageActor::New(); + + ShaderEffect defaultEffect = actor.GetShaderEffect(); + + ShaderEffect effect = ShaderEffect::New("UtcDaliImageActorRemoveShaderEffect-VertexSource", "UtcDaliImageActorRemoveShaderEffect-FragmentSource" ); + actor.SetShaderEffect(effect); + + DALI_TEST_CHECK(effect == actor.GetShaderEffect()); + + actor.RemoveShaderEffect(); + + DALI_TEST_CHECK(defaultEffect == actor.GetShaderEffect()); + END_TEST; +} + +int UtcDaliImageActorRemoveShaderEffect02(void) +{ + TestApplication application; + ImageActor actor = ImageActor::New(); + + ShaderEffect defaultEffect = actor.GetShaderEffect(); + + actor.RemoveShaderEffect(); + + DALI_TEST_CHECK(defaultEffect == actor.GetShaderEffect()); + END_TEST; +} + +int UtcDaliSetShaderEffectRecursively(void) +{ + TestApplication application; + /** + * create a tree + * actor1 + * actor2 actor4 + * actor3 imageactor1 + * imageactor2 + */ + BufferImage img = BufferImage::New( 1,1 ); + ImageActor actor1 = ImageActor::New( img ); + Actor actor2 = Actor::New(); + actor1.Add( actor2 ); + Actor actor3 = Actor::New(); + actor2.Add( actor3 ); + ImageActor imageactor1 = ImageActor::New( img ); + actor2.Add( imageactor1 ); + ImageActor imageactor2 = ImageActor::New( img ); + actor3.Add( imageactor2 ); + Actor actor4 = Actor::New(); + actor1.Add( actor4 ); + Stage::GetCurrent().Add( actor1 ); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + GLuint lastShaderCompiledBefore = application.GetGlAbstraction().GetLastShaderCompiled(); + + application.GetGlAbstraction().EnableShaderCallTrace( true ); + + const std::string vertexShader = "UtcDaliImageActorSetShaderEffect-VertexSource"; + const std::string fragmentShader = "UtcDaliImageActorSetShaderEffect-FragmentSource"; + // test with empty effect + ShaderEffect effect; + SetShaderEffectRecursively( actor1, effect ); + + effect = ShaderEffect::New(vertexShader, fragmentShader ); + + DALI_TEST_CHECK( effect != actor1.GetShaderEffect() ); + DALI_TEST_CHECK( effect != imageactor1.GetShaderEffect() ); + DALI_TEST_CHECK( effect != imageactor2.GetShaderEffect() ); + + SetShaderEffectRecursively( actor1, effect ); + DALI_TEST_CHECK( effect == imageactor1.GetShaderEffect() ); + DALI_TEST_CHECK( effect == imageactor2.GetShaderEffect() ); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + GLuint lastShaderCompiledAfter = application.GetGlAbstraction().GetLastShaderCompiled(); + DALI_TEST_EQUALS( lastShaderCompiledAfter, lastShaderCompiledBefore + 2, TEST_LOCATION ); + + std::string actualVertexShader = application.GetGlAbstraction().GetShaderSource( lastShaderCompiledBefore + 1 ); + DALI_TEST_EQUALS( vertexShader, + actualVertexShader.substr( actualVertexShader.length() - vertexShader.length() ), TEST_LOCATION ); + std::string actualFragmentShader = application.GetGlAbstraction().GetShaderSource( lastShaderCompiledBefore + 2 ); + DALI_TEST_EQUALS( fragmentShader, + actualFragmentShader.substr( actualFragmentShader.length() - fragmentShader.length() ), TEST_LOCATION ); + + // remove from one that does not have shader + RemoveShaderEffectRecursively( actor4 ); + + // remove partially + RemoveShaderEffectRecursively( actor3 ); + DALI_TEST_CHECK( effect == imageactor1.GetShaderEffect() ); + DALI_TEST_CHECK( effect != imageactor2.GetShaderEffect() ); + + // test with empty actor just to check it does not crash + Actor empty; + SetShaderEffectRecursively( empty, effect ); + RemoveShaderEffectRecursively( empty ); + + // test with actor with no children just to check it does not crash + Actor loner = Actor::New(); + Stage::GetCurrent().Add( loner ); + SetShaderEffectRecursively( loner, effect ); + RemoveShaderEffectRecursively( loner ); + + END_TEST; +} + +int UtcDaliImageActorTestClearCache(void) +{ + // Testing the framebuffer state caching in frame-buffer-state-caching.cpp + TestApplication application; + + tet_infoline("Testing Dali::ImageActor::ClearCache()"); + + BufferImage img = BufferImage::New( 1,1 ); + ImageActor actor = ImageActor::New( img ); + + actor.SetParentOrigin(ParentOrigin::CENTER); + actor.SetAnchorPoint(AnchorPoint::CENTER); + + Stage::GetCurrent().Add(actor); + + /**************************************************************/ + // Flush the queue and render once + application.SendNotification(); + application.Render(); + + // There should be a single call to Clear + DALI_TEST_EQUALS( application.GetGlAbstraction().GetClearCountCalled() , 1u, TEST_LOCATION ); + + // the last set clear mask should be COLOR, DEPTH & STENCIL which occurs at the start of each frame + GLbitfield mask = application.GetGlAbstraction().GetLastClearMask(); + DALI_TEST_CHECK( mask & GL_DEPTH_BUFFER_BIT ); + DALI_TEST_CHECK( mask & GL_STENCIL_BUFFER_BIT ); + DALI_TEST_CHECK( mask & GL_COLOR_BUFFER_BIT ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-IntrusivePtr.cpp b/automated-tests/src/dali/utc-Dali-IntrusivePtr.cpp new file mode 100644 index 0000000..23c7880 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-IntrusivePtr.cpp @@ -0,0 +1,461 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +#include +#include +#include +#include + +using namespace Dali; + +namespace +{ + +const int REPEAT = 1000; + +size_t g_creationCount = 0; +size_t g_destructionCount = 0; +size_t g_creationCountSubclass = 0; +size_t g_destructionCountSubclass = 0; +size_t g_creationCountUnrelated = 0; +size_t g_destructionCountUnrelated = 0; + +class Counted : public RefObject +{ +public: + Counted() + { + ++g_creationCount; + } + ~Counted() + { + ++g_destructionCount; + } +}; + +class CountedSubclass : public Counted +{ +public: + CountedSubclass() + { + ++g_creationCountSubclass; + } + ~CountedSubclass() + { + ++g_destructionCountSubclass; + } +}; + +class UnrelatedCounted : public RefObject +{ +public: + UnrelatedCounted() + { + ++g_creationCountUnrelated; + } + ~UnrelatedCounted() + { + ++g_destructionCountUnrelated; + } +}; +} + +/** + * Test that a default constructed pointer is null and harmless. + */ +int UtcDaliIntrusivePtrIntrusivePtr(void) +{ + tet_infoline( "Testing Dali::IntrusivePtr::IntrusivePtr()" ); + + g_creationCount = g_destructionCount = 0; + + IntrusivePtr counted; + DALI_TEST_EQUALS( g_creationCount, 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION ); + // Test the pointer is null + DALI_TEST_EQUALS( counted.Get(), (Counted*) 0, TEST_LOCATION ); + DALI_TEST_EQUALS( &(*counted), (Counted*) 0, TEST_LOCATION ); + // Check destruction of the null smart pointer does nothing: + counted = IntrusivePtr(); + DALI_TEST_EQUALS( g_creationCount, 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliIntrusivePtrIntrusivePtrTP(void) +{ + tet_infoline( "Testing Dali::IntrusivePtr::IntrusivePtr(T*)" ); + + g_creationCount = g_destructionCount = 0; + + IntrusivePtr counted( new Counted ); + DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION ); + counted = 0; + DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCount, 1u, TEST_LOCATION ); + + END_TEST; +} + +// Class is too simple for a negative case to be created: int UtcDaliIntrusiveIntrusivePtrTN(void) + +int UtcDaliIntrusivePtrIntrusivePtrIntrusivePtrUP(void) +{ + tet_infoline( "Testing Dali::IntrusivePtr::IntrusivePtr(IntrusivePtr const &)" ); + + g_creationCount = g_destructionCount = g_creationCountSubclass = g_destructionCountSubclass = 0; + + IntrusivePtr countedSubclass( new CountedSubclass ); + DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_creationCountSubclass, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCountSubclass, 0u, TEST_LOCATION ); + + IntrusivePtr counted( countedSubclass ); + DALI_TEST_EQUALS( counted->ReferenceCount(), 2, TEST_LOCATION ); + + // Make loads more references: + std::vector< IntrusivePtr > intrusivePtrs; + for( int i = 0; i < REPEAT; ++i ) + { + intrusivePtrs.push_back( IntrusivePtr( countedSubclass ) ); + } + DALI_TEST_EQUALS( counted->ReferenceCount(), 2 + REPEAT, TEST_LOCATION ); + + DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_creationCountSubclass, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION ); + + END_TEST; +} + +// The negative version of this test would fail at compile time: +// int UtcDaliIntrusivePtrIntrusivePtrIntrusivePtrUN(void) + +int UtcDaliIntrusivePtrIntrusivePtrIntrusivePtrP(void) +{ + tet_infoline( "Testing Dali::IntrusivePtr::IntrusivePtr(IntrusivePtr const &)" ); + + // Pass a pointer to a constructed second object: + // Pass a pointer to null: + + g_creationCount = g_destructionCount = 0; + + IntrusivePtr counted( new Counted ); + DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( counted->ReferenceCount(), 1, TEST_LOCATION ); + + IntrusivePtr counted2( counted ); + DALI_TEST_EQUALS( counted->ReferenceCount(), 2, TEST_LOCATION ); + DALI_TEST_EQUALS( counted.Get(), counted2.Get(), TEST_LOCATION ); + + // Make loads more references: + std::vector< IntrusivePtr > intrusivePtrs; + for( int i = 0; i < REPEAT; ++i ) + { + intrusivePtrs.push_back( IntrusivePtr( counted ) ); + } + DALI_TEST_EQUALS( counted->ReferenceCount(), 2 + REPEAT, TEST_LOCATION ); + + DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION ); + + intrusivePtrs.clear(); + + DALI_TEST_EQUALS( counted->ReferenceCount(), 2, TEST_LOCATION ); + + DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION ); + + counted.Reset(); + DALI_TEST_EQUALS( counted2->ReferenceCount(), 1, TEST_LOCATION ); + counted2.Reset(); + + DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCount, 1u, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliIntrusivePtrGetP(void) +{ + tet_infoline( "Testing Dali::IntrusivePtr::Get()" ); + + IntrusivePtr counted( new Counted ); + DALI_TEST_CHECK( counted.Get() != 0 ); + DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( counted->ReferenceCount(), 1, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliIntrusivePtrGetN(void) +{ + tet_infoline( "Testing Dali::IntrusivePtr::Get()" ); + + g_creationCount = 0; + + IntrusivePtr counted( 0 ); + DALI_TEST_CHECK( counted.Get() == 0 ); + DALI_TEST_EQUALS( g_creationCount, 0u, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliIntrusivePtrArrowOperatorP(void) +{ + tet_infoline( "Positive Test for Dali::IntrusivePtr::operator->()" ); + + IntrusivePtr counted( new Counted ); + DALI_TEST_CHECK( (counted.operator->()) != 0 ); + DALI_TEST_EQUALS( counted->ReferenceCount(), 1, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliIntrusivePtrArrowOperatorN(void) +{ + tet_infoline( "Negative Test for Dali::IntrusivePtr::operator->()" ); + + IntrusivePtr counted; + DALI_TEST_CHECK( (counted.operator->()) == 0 ); + + END_TEST; +} + +int UtcDaliIntrusivePtrIndirectionOperatorP(void) +{ + tet_infoline( "Positive Test for Dali::IntrusivePtr::operator*()" ); + + IntrusivePtr counted( new Counted ); + DALI_TEST_CHECK( &(counted.operator*()) != 0 ); + DALI_TEST_EQUALS( (*counted).ReferenceCount(), 1, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliIntrusivePtrIndirectionOperatorN(void) +{ + tet_infoline( "Negative Test for Dali::IntrusivePtr::operator*()" ); + + IntrusivePtr counted; + DALI_TEST_CHECK( &(counted.operator*()) == 0 ); + + END_TEST; +} + +int UtcDaliIntrusivePtrResetP(void) +{ + tet_infoline( "Positive Test for Dali::IntrusivePtr::Reset()" ); + + IntrusivePtr counted( new Counted ); + DALI_TEST_CHECK( counted.Get() != 0 ); + counted.Reset(); + DALI_TEST_CHECK( counted.Get() == 0 ); + + END_TEST; +} + +int UtcDaliIntrusivePtrResetN(void) +{ + tet_infoline( "Negative Test for Dali::IntrusivePtr::Reset()" ); + + IntrusivePtr counted; + Counted* firstGet = counted.Get(); + counted.Reset(); + DALI_TEST_EQUALS( counted.Get(), firstGet, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliIntrusivePtrResetTP(void) +{ + tet_infoline( "Positive Test for Dali::IntrusivePtr::Reset(T*)" ); + + g_creationCount = g_destructionCount = 0; + + IntrusivePtr counted( new Counted ); + + IntrusivePtr counted2( new Counted ); + + DALI_TEST_EQUALS( counted->ReferenceCount(), 1, TEST_LOCATION ); + DALI_TEST_EQUALS( counted2->ReferenceCount(), 1, TEST_LOCATION ); + + counted.Reset( counted2.Get() ); + + DALI_TEST_EQUALS( counted->ReferenceCount(), 2, TEST_LOCATION ); + DALI_TEST_EQUALS( counted2->ReferenceCount(), 2, TEST_LOCATION ); + + DALI_TEST_EQUALS( counted.Get(), counted2.Get(), TEST_LOCATION ); + + DALI_TEST_EQUALS( g_creationCount, 2u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCount, 1u, TEST_LOCATION ); + + counted2.Reset( (Counted*) 0 ); + counted.Reset( counted2.Get() ); + DALI_TEST_EQUALS( g_destructionCount, 2u, TEST_LOCATION ); + + // Check that reseting nulls is harmless: + counted2.Reset( counted.Get() ); + counted.Reset( counted2.Get() ); + + DALI_TEST_EQUALS( g_destructionCount, 2u, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliIntrusivePtrResetTN(void) +{ + tet_infoline( "Negative Test for Dali::IntrusivePtr::Reset(T*)" ); + + g_creationCount = g_destructionCount = 0; + + IntrusivePtr counted( new Counted ); + + counted.Reset( (Counted*) 0 ); + + DALI_TEST_EQUALS( counted.Get(), (Counted*) 0, TEST_LOCATION ); + DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( g_destructionCount, 1u, TEST_LOCATION ); + + END_TEST; +} + + + +int UtcDaliIntrusivePtrOperatorBooleanTypeP(void) +{ + tet_infoline( "Positive Test for Dali::IntrusivePtr::operator Booleantype()" ); + + IntrusivePtr counted( new Counted ); + DALI_TEST_CHECK( counted.operator BooleanType() != 0 ); + DALI_TEST_CHECK( counted ); + + typedef void (IntrusivePtr::*BoolIdiomFunc)() const; + BoolIdiomFunc func = static_cast( counted.operator BooleanType() ); + ((counted).*func)(); // purely for test coverage + + counted.Reset(); + DALI_TEST_CHECK( counted.operator BooleanType() == 0 ); + + END_TEST; +} + +int UtcDaliIntrusivePtrOperatorBooleanTypeN(void) +{ + tet_infoline( "Negative Test for Dali::IntrusivePtr::operator Booleantype()" ); + + IntrusivePtr counted; + DALI_TEST_CHECK( counted.operator BooleanType() == 0 ); + DALI_TEST_CHECK( !counted ); + END_TEST; +} + +/** Equality of two different types*/ +int UtcDaliIntrusivePtrOperatorEqualTU(void) +{ + tet_infoline( "Test for Dali::IntrusivePtr::operator ==(T, U)" ); + + IntrusivePtr counted1( new Counted ); + IntrusivePtr countedSubclass1( new CountedSubclass ); + IntrusivePtr countedSubclass2( new CountedSubclass ); + IntrusivePtr counted2( countedSubclass2 ); + + DALI_TEST_EQUALS( operator==( counted1, countedSubclass1 ), false, TEST_LOCATION ); + DALI_TEST_EQUALS( operator==( counted2, countedSubclass2 ), true, TEST_LOCATION ); + END_TEST; +} + +/** Inequality of two different types*/ +int UtcDaliIntrusivePtrOperatorNotEqualTU(void) +{ + tet_infoline( "Test for Dali::IntrusivePtr::operator !=(T, U)" ); + + IntrusivePtr counted1( new Counted ); + IntrusivePtr countedSubclass1( new CountedSubclass ); + IntrusivePtr countedSubclass2( new CountedSubclass ); + IntrusivePtr counted2( countedSubclass2 ); + + DALI_TEST_EQUALS( operator!=( counted1, countedSubclass1 ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( operator!=( counted2, countedSubclass2 ), false, TEST_LOCATION ); + END_TEST; +} + +/** Equality of two different types where right hand side is a raw pointer */ +int UtcDaliIntrusivePtrOperatorEqualRightPointerTU(void) +{ + tet_infoline( "Test for Dali::IntrusivePtr::operator ==(T, U*)" ); + + IntrusivePtr counted1( new Counted ); + IntrusivePtr countedSubclass1( new CountedSubclass ); + IntrusivePtr countedSubclass2( new CountedSubclass ); + IntrusivePtr counted2( countedSubclass2 ); + + DALI_TEST_EQUALS( operator==( counted1, countedSubclass1.Get() ), false, TEST_LOCATION ); + DALI_TEST_EQUALS( operator==( counted2, countedSubclass2.Get() ), true, TEST_LOCATION ); + END_TEST; +} + +/** Inequality of two different types where the right hand side is a raw pointer */ +int UtcDaliIntrusivePtrOperatorNotEqualRightPointerTU(void) +{ + tet_infoline( "Test for Dali::IntrusivePtr::operator !=(T, U*)" ); + + IntrusivePtr counted1( new Counted ); + IntrusivePtr countedSubclass1( new CountedSubclass ); + IntrusivePtr countedSubclass2( new CountedSubclass ); + IntrusivePtr counted2( countedSubclass2 ); + + DALI_TEST_EQUALS( operator!=( counted1, countedSubclass1.Get() ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( operator!=( counted2, countedSubclass2.Get() ), false, TEST_LOCATION ); + END_TEST; +} + +/** Equality of two different types where left hand side is a raw pointer */ +int UtcDaliIntrusivePtrOperatorEqualLeftPointerTU(void) +{ + tet_infoline( "Test for Dali::IntrusivePtr::operator ==(T*, U)" ); + + IntrusivePtr counted1( new Counted ); + IntrusivePtr countedSubclass1( new CountedSubclass ); + IntrusivePtr countedSubclass2( new CountedSubclass ); + IntrusivePtr counted2( countedSubclass2 ); + + DALI_TEST_EQUALS( operator==( counted1.Get(), countedSubclass1 ), false, TEST_LOCATION ); + DALI_TEST_EQUALS( operator==( counted2.Get(), countedSubclass2 ), true, TEST_LOCATION ); + END_TEST; +} + +/** Inequality of two different types where the left hand side is a raw pointer */ +int UtcDaliIntrusivePtrOperatorNotEqualLeftPointerTU(void) +{ + tet_infoline( "Test for Dali::IntrusivePtr::operator !=(T*, U)" ); + + IntrusivePtr counted1( new Counted ); + IntrusivePtr countedSubclass1( new CountedSubclass ); + IntrusivePtr countedSubclass2( new CountedSubclass ); + IntrusivePtr counted2( countedSubclass2 ); + + DALI_TEST_EQUALS( operator!=( counted1.Get(), countedSubclass1 ), true, TEST_LOCATION ); + DALI_TEST_EQUALS( operator!=( counted2.Get(), countedSubclass2 ), false, TEST_LOCATION ); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-KeyEvent.cpp b/automated-tests/src/dali/utc-Dali-KeyEvent.cpp new file mode 100644 index 0000000..0ffb592 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-KeyEvent.cpp @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +#include + +using namespace Dali; + +void utc_dali_key_event_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_key_event_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +// Key Event Test references +const static int SHIFT_MODIFIER = 0x1; +const static int CTRL_MODIFIER = 0x2; +const static int ALT_MODIFIER = 0x4; +const static int SHIFT_AND_CTRL_MODIFIER = SHIFT_MODIFIER | CTRL_MODIFIER; +const static int SHIFT_AND_ALT_MODIFIER = SHIFT_MODIFIER | ALT_MODIFIER; +const static int CTRL_AND_ALT_MODIFIER = CTRL_MODIFIER | ALT_MODIFIER; + +const static char* TEST_STRING_1 = "alpha"; + + +// Stores data that is populated in the callback and will be read by the TET cases +struct SignalData +{ + SignalData() + : functorCalled(false) + {} + + void Reset() + { + functorCalled = false; + + receivedKeyEvent.keyModifier = 0; + receivedKeyEvent.keyPressedName.clear(); + receivedKeyEvent.keyPressed.clear(); + + keyedActor.Reset(); + } + + bool functorCalled; + KeyEvent receivedKeyEvent; + Actor keyedActor; +}; + +// Functor that sets the data when called +struct KeyEventReceivedFunctor +{ + KeyEventReceivedFunctor( SignalData& data ) : signalData( data ) { } + + bool operator()( Actor actor, const KeyEvent& keyEvent ) + { + signalData.functorCalled = true; + signalData.receivedKeyEvent = keyEvent; + signalData.keyedActor = actor; + + return true; + } + + SignalData& signalData; +}; + +} // anon namespace + +int UtcDaliKeyEventConstructor(void) +{ + TestApplication application; // Reset all test adapter return codes + + KeyEvent event(TEST_STRING_1,"i", 99, SHIFT_MODIFIER, 0, KeyEvent::Down); // set name to test, key string to i and modifier to shift + + DALI_TEST_EQUALS(TEST_STRING_1, event.keyPressedName, TEST_LOCATION); // check key name + DALI_TEST_EQUALS("i", event.keyPressed, TEST_LOCATION); // check key string + DALI_TEST_EQUALS(99, event.keyCode, TEST_LOCATION); // check keyCode + DALI_TEST_EQUALS(SHIFT_MODIFIER, event.keyModifier, TEST_LOCATION); // check modifier + DALI_TEST_EQUALS(KeyEvent::Down, event.state, TEST_LOCATION); // check state + END_TEST; +} + +// Positive test case for a method +int UtcDaliKeyEventIsShiftModifier(void) +{ + TestApplication application; // Reset all test adapter return codes + + KeyEvent event; + DALI_TEST_EQUALS(0, event.keyModifier, TEST_LOCATION); + + event.keyModifier = SHIFT_MODIFIER; // Set to Shift Modifier + + DALI_TEST_EQUALS(SHIFT_MODIFIER, event.keyModifier, TEST_LOCATION); // check able to set + + DALI_TEST_EQUALS(true, event.IsShiftModifier(), TEST_LOCATION); // check IsShiftModifier + + END_TEST; +} + +// Positive test case for a method +int UtcDaliKeyEventIsCtrlModifier(void) +{ + TestApplication application; // Reset all test adapter return codes + + KeyEvent event; + DALI_TEST_EQUALS(0, event.keyModifier, TEST_LOCATION); + + event.keyModifier = CTRL_MODIFIER; // Set to Ctrl Modifier + + DALI_TEST_EQUALS(CTRL_MODIFIER, event.keyModifier, TEST_LOCATION); // check able to set + + DALI_TEST_EQUALS(true, event.IsCtrlModifier(), TEST_LOCATION); // check IsCtrlModifier + END_TEST; +} + +// Positive test case for a method +int UtcDaliKeyEventIsAltModifier(void) +{ + TestApplication application; // Reset all test adapter return codes + + KeyEvent event; + DALI_TEST_EQUALS(0, event.keyModifier, TEST_LOCATION); + + event.keyModifier = ALT_MODIFIER; // Set to Alt Modifier + + DALI_TEST_EQUALS(ALT_MODIFIER, event.keyModifier, TEST_LOCATION); // check able to set + + DALI_TEST_EQUALS(true, event.IsAltModifier(), TEST_LOCATION); // IsAltModifier + END_TEST; +} + +// Positive fail test case for a method +int UtcDaliKeyEventIsNotShiftModifier(void) +{ + TestApplication application; // Reset all test adapter return codes + + KeyEvent event("i","i", 0, CTRL_MODIFIER, 0, KeyEvent::Down); + + DALI_TEST_EQUALS(CTRL_MODIFIER, event.keyModifier, TEST_LOCATION); // check different modifier used + + DALI_TEST_EQUALS(false, event.IsShiftModifier(), TEST_LOCATION); + END_TEST; +} + +// Positive fail test case for a method +int UtcDaliKeyEventIsNotCtrlModifier(void) +{ + TestApplication application; // Reset all test adapter return codes + + KeyEvent event("i","i", 0, ALT_MODIFIER, 0, KeyEvent::Up); + + DALI_TEST_EQUALS(ALT_MODIFIER, event.keyModifier, TEST_LOCATION); // check different modifier used + + DALI_TEST_EQUALS(false, event.IsCtrlModifier(), TEST_LOCATION); + END_TEST; +} + +// Positive fail test case for a method +int UtcDaliKeyEventIsNotAltModifier(void) +{ + TestApplication application; // Reset all test adapter return codes + + KeyEvent event("i","i", 0, SHIFT_MODIFIER, 0, KeyEvent::Up); + + DALI_TEST_EQUALS(SHIFT_MODIFIER, event.keyModifier, TEST_LOCATION); // check different modifier used + + DALI_TEST_EQUALS(false, event.IsAltModifier(), TEST_LOCATION); + END_TEST; +} + +// Positive test case for a method +int UtcDaliKeyEventANDModifer(void) +{ + TestApplication application; // Reset all test adapter return codes + + KeyEvent event("i","i", 0, SHIFT_AND_CTRL_MODIFIER, 0, KeyEvent::Down); + DALI_TEST_EQUALS(true, event.IsCtrlModifier() & event.IsShiftModifier(), TEST_LOCATION); + + event.keyModifier = SHIFT_MODIFIER; + + DALI_TEST_EQUALS(false, event.IsCtrlModifier() & event.IsShiftModifier(), TEST_LOCATION); + END_TEST; +} + +// Positive test case for a method +int UtcDaliKeyEventORModifer(void) +{ + TestApplication application; // Reset all test adapter return codes + + KeyEvent event("i","i", 0, SHIFT_AND_CTRL_MODIFIER, 0, KeyEvent::Down); + DALI_TEST_EQUALS(true, event.IsCtrlModifier() | event.IsAltModifier(), TEST_LOCATION); + + event.keyModifier = SHIFT_MODIFIER; + + DALI_TEST_EQUALS(false, event.IsCtrlModifier() & event.IsAltModifier(), TEST_LOCATION); + END_TEST; +} + +// Positive test case for a method +int UtcDaliKeyEventState(void) +{ + TestApplication application; // Reset all test adapter return codes + + KeyEvent event("i","i", 0, SHIFT_AND_CTRL_MODIFIER, 0, KeyEvent::Down); + DALI_TEST_EQUALS(true, event.IsCtrlModifier() | event.IsAltModifier(), TEST_LOCATION); + + event.keyModifier = SHIFT_MODIFIER; + + DALI_TEST_EQUALS(false, event.IsCtrlModifier() & event.IsAltModifier(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliIntegrationKeyEvent(void) +{ + TestApplication application; + + { + Integration::KeyEvent keyEvent; + DALI_TEST_EQUALS( keyEvent.type, Integration::Event::Key, TEST_LOCATION ); + DALI_TEST_CHECK( keyEvent.keyName == std::string() ); + DALI_TEST_CHECK( keyEvent.keyString == std::string() ); + DALI_TEST_EQUALS( keyEvent.keyCode, -1, TEST_LOCATION ); + DALI_TEST_EQUALS( keyEvent.keyModifier, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( keyEvent.time, 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( keyEvent.state, Integration::KeyEvent::Down, TEST_LOCATION); + } + + { + const std::string keyName("keyName"); + const std::string keyString("keyString"); + const int keyCode(333); + const int keyModifier(312); + const unsigned long timeStamp(132); + const Integration::KeyEvent::State keyState(Integration::KeyEvent::Up); + + Integration::KeyEvent keyEvent(keyName, keyString, keyCode, keyModifier, timeStamp, keyState); + DALI_TEST_EQUALS( keyEvent.type, Integration::Event::Key, TEST_LOCATION ); + DALI_TEST_CHECK( keyEvent.keyName == keyName ); + DALI_TEST_CHECK( keyEvent.keyString == keyString ); + DALI_TEST_EQUALS( keyEvent.keyCode, keyCode, TEST_LOCATION ); + DALI_TEST_EQUALS( keyEvent.keyModifier, keyModifier, TEST_LOCATION ); + DALI_TEST_EQUALS( keyEvent.time, timeStamp, TEST_LOCATION ); + DALI_TEST_EQUALS( keyEvent.state, keyState, TEST_LOCATION); + } + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Layer.cpp b/automated-tests/src/dali/utc-Dali-Layer.cpp new file mode 100644 index 0000000..ee8c51d --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Layer.cpp @@ -0,0 +1,581 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include + +#include + +#include + +using namespace Dali; + +void layer_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void layer_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +int UtcDaliLayerNew(void) +{ + TestApplication application; + Layer layer = Layer::New(); + + DALI_TEST_CHECK(layer); + END_TEST; +} + +int UtcDaliLayerDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Layer::DownCast()"); + + Layer actor1 = Layer::New(); + Actor anActor = Actor::New(); + anActor.Add(actor1); + + Actor child = anActor.GetChildAt(0); + Layer layer = DownCast< Layer >(child); + + DALI_TEST_CHECK(layer); + END_TEST; +} + +int UtcDaliLayerDownCast2(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Layer::DownCast()"); + + Actor actor1 = Actor::New(); + Actor anActor = Actor::New(); + anActor.Add(actor1); + + Actor child = anActor.GetChildAt(0); + Layer layer = DownCast< Layer >(child); + DALI_TEST_CHECK(!layer); + + Actor unInitialzedActor; + layer = Layer::DownCast( unInitialzedActor ); + DALI_TEST_CHECK(!layer); + END_TEST; +} + + +int UtcDaliLayerGetDepth(void) +{ + tet_infoline("Testing Dali::Layer::GetDepth()"); + TestApplication application; + Layer layer1 = Layer::New(); + Layer layer2 = Layer::New(); + + // layers are not on stage + DALI_TEST_EQUALS(layer1.GetDepth(), 0u, TEST_LOCATION); + DALI_TEST_EQUALS(layer2.GetDepth(), 0u, TEST_LOCATION); + + // root depth is 0 + Layer root = Stage::GetCurrent().GetLayer( 0 ); + DALI_TEST_EQUALS(root.GetDepth(), 0u, TEST_LOCATION); + + Stage::GetCurrent().Add(layer1); + Stage::GetCurrent().Add(layer2); + + DALI_TEST_EQUALS( root.GetDepth(), 0u, TEST_LOCATION); + DALI_TEST_EQUALS(layer1.GetDepth(), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(layer2.GetDepth(), 2u, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLayerRaise(void) +{ + tet_infoline("Testing Dali::Layer::Raise()"); + TestApplication application; + Layer layer1 = Layer::New(); + Layer layer2 = Layer::New(); + + Stage::GetCurrent().Add(layer1); + Stage::GetCurrent().Add(layer2); + DALI_TEST_EQUALS(layer1.GetDepth(), 1u, TEST_LOCATION); + + layer1.Raise(); + DALI_TEST_EQUALS(layer1.GetDepth(), 2u, TEST_LOCATION); + + // get root + Layer root = Stage::GetCurrent().GetLayer( 0 ); + DALI_TEST_EQUALS( root.GetDepth(), 0u, TEST_LOCATION); + root.Raise(); + DALI_TEST_EQUALS( root.GetDepth(), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(layer1.GetDepth(), 2u, TEST_LOCATION); + DALI_TEST_EQUALS(layer2.GetDepth(), 0u, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLayerLower(void) +{ + tet_infoline("Testing Dali::Layer::Lower()"); + TestApplication application; + Layer layer1 = Layer::New(); + Layer layer2 = Layer::New(); + + Stage::GetCurrent().Add(layer1); + Stage::GetCurrent().Add(layer2); + DALI_TEST_EQUALS(layer2.GetDepth(), 2u, TEST_LOCATION); + + layer2.Lower(); + DALI_TEST_EQUALS(layer2.GetDepth(), 1u, TEST_LOCATION); + + // get root + Layer root = Stage::GetCurrent().GetLayer( 0 ); + root.Lower(); + DALI_TEST_EQUALS( root.GetDepth(), 0u, TEST_LOCATION); + layer2.Lower(); + DALI_TEST_EQUALS( root.GetDepth(), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(layer2.GetDepth(), 0u, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLayerRaiseToTop(void) +{ + tet_infoline("Testing Dali::Layer::RaiseToTop()"); + TestApplication application; + Layer layer1 = Layer::New(); + Layer layer2 = Layer::New(); + Layer layer3 = Layer::New(); + + Stage::GetCurrent().Add(layer1); + Stage::GetCurrent().Add(layer2); + Stage::GetCurrent().Add(layer3); + Layer root = Stage::GetCurrent().GetLayer( 0 ); + + DALI_TEST_EQUALS( root.GetDepth(), 0u, TEST_LOCATION); + DALI_TEST_EQUALS(layer1.GetDepth(), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(layer2.GetDepth(), 2u, TEST_LOCATION); + DALI_TEST_EQUALS(layer3.GetDepth(), 3u, TEST_LOCATION); + + layer1.RaiseToTop(); + DALI_TEST_EQUALS(layer1.GetDepth(), 3u, TEST_LOCATION); + + root.RaiseToTop(); + DALI_TEST_EQUALS( root.GetDepth(), 3u, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLayerLowerToBottom(void) +{ + tet_infoline("Testing Dali::Layer::LowerToBottom()"); + TestApplication application; + Layer layer1 = Layer::New(); + Layer layer2 = Layer::New(); + Layer layer3 = Layer::New(); + + Stage::GetCurrent().Add(layer1); + Stage::GetCurrent().Add(layer2); + Stage::GetCurrent().Add(layer3); + + DALI_TEST_EQUALS(layer1.GetDepth(), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(layer2.GetDepth(), 2u, TEST_LOCATION); + DALI_TEST_EQUALS(layer3.GetDepth(), 3u, TEST_LOCATION); + + layer3.LowerToBottom(); + DALI_TEST_EQUALS(layer3.GetDepth(), 0u, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLayerSetClipping(void) +{ + tet_infoline("Testing Dali::Layer::SetClipping()"); + TestApplication application; + + Layer layer = Layer::New(); + DALI_TEST_CHECK(!layer.IsClipping()); + + layer.SetClipping(true); + DALI_TEST_CHECK(layer.IsClipping()); + END_TEST; +} + +int UtcDaliLayerIsClipping(void) +{ + tet_infoline("Testing Dali::Layer::IsClipping()"); + TestApplication application; + + Layer layer = Layer::New(); + DALI_TEST_CHECK(!layer.IsClipping()); + END_TEST; +} + +int UtcDaliLayerSetClippingBox(void) +{ + tet_infoline("Testing Dali::Layer::SetClippingBox()"); + TestApplication application; + + ClippingBox testBox(5,6, 77,83); + + Layer layer = Layer::New(); + DALI_TEST_CHECK(layer.GetClippingBox() != testBox); + + layer.SetClippingBox(5,6, 77,83); + DALI_TEST_CHECK(layer.GetClippingBox() == testBox); + END_TEST; +} + +int UtcDaliLayerGetClippingBox(void) +{ + tet_infoline("Testing Dali::Layer::GetClippingBox()"); + TestApplication application; + + Layer layer = Layer::New(); + DALI_TEST_CHECK(layer.GetClippingBox() == ClippingBox(0,0,0,0)); + END_TEST; +} + +static int gTestSortFunctionCalled; + +static float TestSortFunction(const Vector3& /*position*/) +{ + ++gTestSortFunctionCalled; + return 0.0f; +} + +int UtcDaliLayerSetSortFunction(void) +{ + tet_infoline("Testing Dali::Layer::SetSortFunction()"); + TestApplication application; + BufferImage img = BufferImage::New( 1,1 ); + // create two transparent actors so there is something to sort + ImageActor actor = ImageActor::New( img ); + ImageActor actor2 = ImageActor::New( img ); + actor.SetSize(1,1); + actor.SetColor( Vector4(1, 1, 1, 0.5f ) ); // 50% transparent + actor2.SetSize(1,1); + actor2.SetColor( Vector4(1, 1, 1, 0.5f ) ); // 50% transparent + + // add to stage + Stage::GetCurrent().Add( actor ); + Stage::GetCurrent().Add( actor2 ); + + Layer root = Stage::GetCurrent().GetLayer( 0 ); + gTestSortFunctionCalled = 0; + root.SetSortFunction(TestSortFunction); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( gTestSortFunctionCalled > 0 ); + END_TEST; +} + + +int UtcDaliLayerRaiseAbove(void) +{ + tet_infoline("Testing Dali::Layer::RaiseAbove()"); + TestApplication application; + Layer layer = Layer::New(); + // try to raise above root layer + Layer root = Stage::GetCurrent().GetLayer( 0 ); + layer.RaiseAbove( root ); + // layer depth is zero as its not on stage + DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION ); + // add to stage + Stage::GetCurrent().Add( layer ); + layer.RaiseAbove( root ); + DALI_TEST_EQUALS( layer.GetDepth(), 1u, TEST_LOCATION ); + root.RaiseAbove( layer ); + DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION ); + layer.RaiseAbove( layer ); + DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION ); + + // make another layer on the stage + Layer layer2 = Layer::New(); + Stage::GetCurrent().Add( layer2 ); + layer.RaiseAbove( layer2 ); + DALI_TEST_GREATER( layer.GetDepth(), layer2.GetDepth(), TEST_LOCATION ); + layer2.RaiseAbove( layer ); + DALI_TEST_GREATER( layer2.GetDepth(), layer.GetDepth(), TEST_LOCATION ); + root.RaiseAbove( layer2 ); + DALI_TEST_GREATER( root.GetDepth(), layer2.GetDepth(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliLayerRaiseBelow(void) +{ + tet_infoline("Testing Dali::Layer::RaiseBelow()"); + TestApplication application; + Layer layer = Layer::New(); + // try to lower below root layer + Layer root = Stage::GetCurrent().GetLayer( 0 ); + layer.LowerBelow( root ); + // layer depth is zero as its not on stage + DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION ); + // add to stage + Stage::GetCurrent().Add( layer ); + DALI_TEST_EQUALS( layer.GetDepth(), 1u, TEST_LOCATION ); + layer.LowerBelow( root ); + DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION ); + root.LowerBelow( layer ); + DALI_TEST_EQUALS( layer.GetDepth(), 1u, TEST_LOCATION ); + layer.LowerBelow( layer ); + DALI_TEST_EQUALS( layer.GetDepth(), 1u, TEST_LOCATION ); + + // make another layer on the stage + Layer layer2 = Layer::New(); + Stage::GetCurrent().Add( layer2 ); + layer.LowerBelow( layer2 ); + DALI_TEST_GREATER( layer2.GetDepth(), layer.GetDepth(), TEST_LOCATION ); + layer2.LowerBelow( layer ); + DALI_TEST_GREATER( layer.GetDepth(), layer2.GetDepth(), TEST_LOCATION ); + root.LowerBelow( layer2 ); + DALI_TEST_GREATER( layer2.GetDepth(), root.GetDepth(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliLayerMoveAbove(void) +{ + tet_infoline("Testing Dali::Layer::MoveAbove()"); + TestApplication application; + Layer layer = Layer::New(); + // try to raise above root layer + Layer root = Stage::GetCurrent().GetLayer( 0 ); + layer.MoveAbove( root ); + // layer depth is zero as its not on stage + DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION ); + root.MoveAbove( layer ); + // root depth is zero as layer is not on stage + DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION ); + // add to stage + Stage::GetCurrent().Add( layer ); + layer.MoveAbove( root ); + DALI_TEST_EQUALS( layer.GetDepth(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( root.GetDepth(), 0u, TEST_LOCATION ); + root.MoveAbove( layer ); + DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( root.GetDepth(), 1u, TEST_LOCATION ); + + // make another layer on the stage + Layer layer2 = Layer::New(); + Stage::GetCurrent().Add( layer2 ); + layer.MoveAbove( layer2 ); + DALI_TEST_EQUALS( layer.GetDepth(), layer2.GetDepth() + 1u, TEST_LOCATION ); + layer2.MoveAbove( root ); + DALI_TEST_EQUALS( layer2.GetDepth(), root.GetDepth() + 1u, TEST_LOCATION ); + root.MoveAbove( layer ); + DALI_TEST_EQUALS( root.GetDepth(), layer.GetDepth() + 1u, TEST_LOCATION ); + + Layer layer3 = Layer::New(); + Stage::GetCurrent().Add( layer3 ); + DALI_TEST_EQUALS( layer3.GetDepth(), 3u, TEST_LOCATION ); + root.MoveAbove( layer3 ); + DALI_TEST_EQUALS( root.GetDepth(), 3u, TEST_LOCATION ); + DALI_TEST_EQUALS( layer3.GetDepth(), 2u, TEST_LOCATION ); + DALI_TEST_EQUALS( Stage::GetCurrent().GetLayer( 0 ).GetDepth(), 0u, TEST_LOCATION ); + layer3.MoveAbove( Stage::GetCurrent().GetLayer( 0 ) ); + DALI_TEST_EQUALS( layer3.GetDepth(), 1u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliLayerMoveBelow(void) +{ + tet_infoline("Testing Dali::Layer::MoveBelow()"); + TestApplication application; + Layer layer = Layer::New(); + // try to raise above root layer + Layer root = Stage::GetCurrent().GetLayer( 0 ); + layer.MoveBelow( root ); + // layer depth is zero as its not on stage + DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION ); + root.MoveBelow( layer ); + // root depth is zero as layer is not on stage + DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION ); + // add to stage + Stage::GetCurrent().Add( layer ); + layer.MoveBelow( root ); + DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( root.GetDepth(), 1u, TEST_LOCATION ); + root.MoveBelow( layer ); + DALI_TEST_EQUALS( layer.GetDepth(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( root.GetDepth(), 0u, TEST_LOCATION ); + + // make another layer on the stage + Layer layer2 = Layer::New(); + Stage::GetCurrent().Add( layer2 ); + layer.MoveBelow( layer2 ); + DALI_TEST_EQUALS( layer.GetDepth(), layer2.GetDepth() - 1u, TEST_LOCATION ); + layer2.MoveBelow( root ); + DALI_TEST_EQUALS( layer2.GetDepth(), root.GetDepth() - 1u, TEST_LOCATION ); + root.MoveBelow( layer ); + DALI_TEST_EQUALS( root.GetDepth(), layer.GetDepth() - 1u, TEST_LOCATION ); + + Layer layer3 = Layer::New(); + Stage::GetCurrent().Add( layer3 ); + DALI_TEST_EQUALS( layer3.GetDepth(), 3u, TEST_LOCATION ); + root.MoveBelow( layer3 ); + DALI_TEST_EQUALS( root.GetDepth(), 2u, TEST_LOCATION ); + DALI_TEST_EQUALS( layer3.GetDepth(), 3u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliLayerDefaultProperties(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Layer DefaultProperties"); + + Layer actor = Layer::New(); + + std::vector indices; + indices.push_back(Layer::Property::CLIPPING_ENABLE); + indices.push_back(Layer::Property::CLIPPING_BOX); + indices.push_back(Layer::Property::BEHAVIOR); + + DALI_TEST_CHECK(actor.GetPropertyCount() == ( Actor::New().GetPropertyCount() + indices.size() ) ); + + for(std::vector::iterator iter = indices.begin(); iter != indices.end(); ++iter) + { + DALI_TEST_CHECK( *iter == actor.GetPropertyIndex(actor.GetPropertyName(*iter)) ); + DALI_TEST_CHECK( actor.IsPropertyWritable(*iter) ); + DALI_TEST_CHECK( !actor.IsPropertyAnimatable(*iter) ); + DALI_TEST_CHECK( actor.GetPropertyType(*iter) == actor.GetPropertyType(*iter) ); // just checking call succeeds + } + + // set/get one of them + actor.SetClippingBox(0,0,0,0); + + ClippingBox testBox(10,20,30,40); + DALI_TEST_CHECK(actor.GetClippingBox() != testBox); + + actor.SetProperty(Layer::Property::CLIPPING_BOX, Property::Value(Rect(testBox))); + + DALI_TEST_CHECK(Property::RECTANGLE == actor.GetPropertyType(Layer::Property::CLIPPING_BOX)); + + Property::Value v = actor.GetProperty(Layer::Property::CLIPPING_BOX); + + DALI_TEST_CHECK(v.Get >() == testBox); + + // set the same boundaries, but through a clipping box object + actor.SetClippingBox( testBox ); + + DALI_TEST_CHECK( actor.GetClippingBox() == testBox ); + + + Property::Value behavior = actor.GetProperty(Layer::Property::BEHAVIOR); + DALI_TEST_CHECK( std::strcmp( behavior.Get().c_str(), "LAYER_2D") ); + + END_TEST; +} + +int UtcDaliLayerSetDepthTestDisabled(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Layer::SetDepthTestDisabled() "); + + Layer actor = Layer::New(); + DALI_TEST_CHECK( actor.IsDepthTestDisabled() ); + + actor.SetBehavior( Layer::LAYER_3D ); + DALI_TEST_CHECK( !actor.IsDepthTestDisabled() ); + + actor.SetDepthTestDisabled( true ); + DALI_TEST_CHECK( actor.IsDepthTestDisabled() ); + END_TEST; +} + +int UtcDaliLayerCreateDestroy(void) +{ + tet_infoline("Testing Dali::Layer::CreateDestroy() "); + Layer* layer = new Layer; + DALI_TEST_CHECK( layer ); + delete layer; + END_TEST; +} + +int UtcDaliLayerPropertyIndices(void) +{ + TestApplication application; + Actor basicActor = Actor::New(); + Layer layer = Layer::New(); + + Property::IndexContainer indices; + layer.GetPropertyIndices( indices ); + DALI_TEST_CHECK( indices.Size() > basicActor.GetPropertyCount() ); + DALI_TEST_EQUALS( indices.Size(), layer.GetPropertyCount(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliLayerTouchConsumed(void) +{ + TestApplication application; + Layer layer = Layer::New(); + + DALI_TEST_EQUALS( layer.IsTouchConsumed(), false, TEST_LOCATION ); + layer.SetTouchConsumed( true ); + DALI_TEST_EQUALS( layer.IsTouchConsumed(), true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliLayerHoverConsumed(void) +{ + TestApplication application; + Layer layer = Layer::New(); + + DALI_TEST_EQUALS( layer.IsHoverConsumed(), false, TEST_LOCATION ); + layer.SetHoverConsumed( true ); + DALI_TEST_EQUALS( layer.IsHoverConsumed(), true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliLayerClippingGLCalls(void) +{ + TestApplication application; + const TestGlAbstraction::ScissorParams& glScissorParams( application.GetGlAbstraction().GetScissorParams() ); + Stage stage( Stage::GetCurrent() ); + + ClippingBox testBox( 5, 6, 77, 83 ); + Layer layer = Stage::GetCurrent().GetRootLayer(); + layer.SetClipping( true ); + layer.SetClippingBox( testBox ); + + // Add at least one renderable actor so the GL calls are actually made + BufferImage img = BufferImage::New( 1,1 ); + Actor actor = ImageActor::New( img ); + stage.Add( actor ); + + // flush the queue and render once + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( testBox.x, glScissorParams.x, TEST_LOCATION ); + DALI_TEST_EQUALS( testBox.y, stage.GetSize().height - glScissorParams.y - testBox.height, TEST_LOCATION ); // GL Coordinates are from bottom left + DALI_TEST_EQUALS( testBox.width, glScissorParams.width, TEST_LOCATION ); + DALI_TEST_EQUALS( testBox.height, glScissorParams.height, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliLayerBehaviour(void) +{ + TestApplication application; + Layer layer = Layer::New(); + + DALI_TEST_EQUALS( layer.GetBehavior(), Dali::Layer::LAYER_2D, TEST_LOCATION ); + layer.SetBehavior( Dali::Layer::LAYER_3D ); + DALI_TEST_EQUALS( layer.GetBehavior(), Dali::Layer::LAYER_3D, TEST_LOCATION ); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-LocklessBuffer.cpp b/automated-tests/src/dali/utc-Dali-LocklessBuffer.cpp new file mode 100644 index 0000000..46f1dc2 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-LocklessBuffer.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include + +using namespace Dali; + +namespace +{ + +static bool ReadTest(Integration::LocklessBuffer& buf, const unsigned char exp[], size_t size) +{ + const unsigned char *res = buf.Read(); + for (size_t i=0; i + +#include +#include +#include + +using namespace Dali; + +void utc_dali_long_press_gesture_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_long_press_gesture_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +// Positive test case for a method +int UtcDaliLongPressGestureConstructor(void) +{ + TestApplication application; // Reset all test adapter return codes + + LongPressGesture gesture( Gesture::Started ); + DALI_TEST_EQUALS(1u, gesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::LongPress, gesture.type, TEST_LOCATION); + + // Test Copy constructor + gesture.numberOfTouches = 5u; + + LongPressGesture gesture2(gesture); + DALI_TEST_EQUALS(5u, gesture2.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::LongPress, gesture2.type, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, gesture2.state, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureAssignment(void) +{ + // Test Assignment operator + LongPressGesture gesture( Gesture::Started ); + DALI_TEST_EQUALS(1u, gesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::LongPress, gesture.type, TEST_LOCATION); + + gesture.numberOfTouches = 5u; + + LongPressGesture gesture2( Gesture::Finished ); + DALI_TEST_EQUALS(Gesture::Finished, gesture2.state, TEST_LOCATION); + gesture2 = gesture; + DALI_TEST_EQUALS(5u, gesture2.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::LongPress, gesture2.type, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, gesture2.state, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureDynamicAllocation(void) +{ + LongPressGesture* gesture = new LongPressGesture( Gesture::Started ); + DALI_TEST_EQUALS(1u, gesture->numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::LongPress, gesture->type, TEST_LOCATION); + delete gesture; + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp new file mode 100644 index 0000000..6c7ba81 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp @@ -0,0 +1,1454 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; + +void utc_dali_long_press_gesture_detector_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_long_press_gesture_detector_cleanup(void) +{ + test_return_value = TET_PASS; +} + +/////////////////////////////////////////////////////////////////////////////// +namespace +{ + +// Stores data that is populated in the callback and will be read by the TET cases +struct SignalData +{ + SignalData() + : functorCalled( false ), + voidFunctorCalled( false ), + receivedGesture( Gesture::Clear ), + pressedActor() + {} + + void Reset() + { + functorCalled = false; + voidFunctorCalled = false; + + receivedGesture.numberOfTouches = 0u; + receivedGesture.screenPoint = Vector2(0.0f, 0.0f); + receivedGesture.localPoint = Vector2(0.0f, 0.0f); + + pressedActor.Reset(); + } + + bool functorCalled; + bool voidFunctorCalled; + LongPressGesture receivedGesture; + Actor pressedActor; +}; + +// Functor that sets the data when called +struct GestureReceivedFunctor +{ + GestureReceivedFunctor(SignalData& data) : signalData(data) { } + + void operator()(Actor actor, const LongPressGesture& longPress) + { + signalData.functorCalled = true; + signalData.receivedGesture = longPress; + signalData.pressedActor = actor; + } + + void operator()() + { + signalData.voidFunctorCalled = true; + } + + SignalData& signalData; +}; + +// Functor that removes the gestured actor from stage +struct UnstageActorFunctor : public GestureReceivedFunctor +{ + UnstageActorFunctor( SignalData& data, Gesture::State& stateToUnstage ) + : GestureReceivedFunctor( data ), + stateToUnstage( stateToUnstage ) + { + } + + void operator()( Actor actor, const LongPressGesture& longPress ) + { + GestureReceivedFunctor::operator()( actor, longPress ); + + if ( longPress.state == stateToUnstage ) + { + Stage::GetCurrent().Remove( actor ); + } + } + + Gesture::State& stateToUnstage; +}; + +// Functor for receiving a touch event +struct TouchEventFunctor +{ + bool operator()(Actor actor, const TouchEvent& touch) + { + //For line coverage + unsigned int points = touch.GetPointCount(); + if( points > 0) + { + const TouchPoint& touchPoint = touch.GetPoint(0); + tet_printf("Touch Point state = %d\n", touchPoint.state); + } + return false; + } +}; + +// Generate a LongPressGestureEvent to send to Core +Integration::LongPressGestureEvent GenerateLongPress( + Gesture::State state, + unsigned int numberOfTouches, + Vector2 point) +{ + Integration::LongPressGestureEvent longPress( state ); + + longPress.numberOfTouches = numberOfTouches; + longPress.point = point; + + return longPress; +} + +} // anon namespace + +/////////////////////////////////////////////////////////////////////////////// + + +// Positive test case for a method +int UtcDaliLongPressGestureDetectorConstructorP(void) +{ + TestApplication application; + + LongPressGestureDetector detector; + DALI_TEST_CHECK(!detector); + END_TEST; +} + +int UtcDaliLongPressGestureDetectorCopyConstructorP(void) +{ + TestApplication application; + + LongPressGestureDetector detector = LongPressGestureDetector::New();; + + LongPressGestureDetector copy( detector ); + DALI_TEST_CHECK( detector ); + END_TEST; +} + +int UtcDaliLongPressGestureDetectorAssignmentOperatorP(void) +{ + TestApplication application; + + LongPressGestureDetector detector; + detector = LongPressGestureDetector::New();; + + LongPressGestureDetector copy; + copy = detector; + DALI_TEST_CHECK( detector ); + + DALI_TEST_CHECK( detector == copy ); + END_TEST; +} + +int UtcDaliLongPressGestureDetectorNew(void) +{ + TestApplication application; + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + DALI_TEST_CHECK(detector); + DALI_TEST_EQUALS(1u, detector.GetMinimumTouchesRequired(), TEST_LOCATION); + DALI_TEST_EQUALS(1u, detector.GetMaximumTouchesRequired(), TEST_LOCATION); + + LongPressGestureDetector detector2 = LongPressGestureDetector::New(5u); + DALI_TEST_CHECK(detector2); + DALI_TEST_EQUALS(5u, detector2.GetMinimumTouchesRequired(), TEST_LOCATION); + DALI_TEST_EQUALS(5u, detector2.GetMaximumTouchesRequired(), TEST_LOCATION); + + LongPressGestureDetector detector3 = LongPressGestureDetector::New(5u, 7u); + DALI_TEST_CHECK(detector2); + DALI_TEST_EQUALS(5u, detector3.GetMinimumTouchesRequired(), TEST_LOCATION); + DALI_TEST_EQUALS(7u, detector3.GetMaximumTouchesRequired(), TEST_LOCATION); + + //Scoped test to test destructor + { + LongPressGestureDetector detector4 = LongPressGestureDetector::New(); + DALI_TEST_CHECK(detector4); + } + + // Attach an actor and emit a touch event on the actor to ensure complete line coverage + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + detector.Attach(actor); + + TouchEventFunctor touchFunctor; + actor.TouchedSignal().Connect(&application, touchFunctor); + + Integration::TouchEvent touchEvent(1); + TouchPoint point(1, TouchPoint::Down, 20.0f, 20.0f); + touchEvent.AddPoint(point); + application.ProcessEvent(touchEvent); + + // Render and notify + application.SendNotification(); + application.Render(); + + // For line coverage, Initialise default constructor + TouchEvent touchEvent2; + END_TEST; +} + +int UtcDaliLongPressGestureDetectorDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::LongPressGestureDetector::DownCast()"); + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + + BaseHandle object(detector); + + LongPressGestureDetector detector2 = LongPressGestureDetector::DownCast(object); + DALI_TEST_CHECK(detector2); + + LongPressGestureDetector detector3 = DownCast< LongPressGestureDetector >(object); + DALI_TEST_CHECK(detector3); + + BaseHandle unInitializedObject; + LongPressGestureDetector detector4 = LongPressGestureDetector::DownCast(unInitializedObject); + DALI_TEST_CHECK(!detector4); + + LongPressGestureDetector detector5 = DownCast< LongPressGestureDetector >(unInitializedObject); + DALI_TEST_CHECK(!detector5); + + GestureDetector detector6 = LongPressGestureDetector::New(); + LongPressGestureDetector detector7 = LongPressGestureDetector::DownCast(detector6); + DALI_TEST_CHECK(detector7); + END_TEST; +} + +int UtcDaliLongPressGestureSetTouchesRequired01(void) +{ + TestApplication application; + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + + unsigned int touches = 3; + + DALI_TEST_CHECK(touches != detector.GetMinimumTouchesRequired()); + DALI_TEST_CHECK(touches != detector.GetMaximumTouchesRequired()); + + detector.SetTouchesRequired(touches); + + DALI_TEST_EQUALS(touches, detector.GetMinimumTouchesRequired(), TEST_LOCATION); + DALI_TEST_EQUALS(touches, detector.GetMaximumTouchesRequired(), TEST_LOCATION); + + // Attach an actor and change the required touches + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + TestGestureManager& gestureManager = application.GetGestureManager(); + gestureManager.Initialize(); + + detector.SetTouchesRequired(4); + + // Gesture detection should have been updated only + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + // Reset values + gestureManager.Initialize(); + + // Create a second gesture detector that requires even less maximum touches + LongPressGestureDetector secondDetector = LongPressGestureDetector::New(); + secondDetector.Attach(actor); + + // Gesture detection should have been updated + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureSetTouchesRequired02(void) +{ + TestApplication application; + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + + unsigned int min = 3; + unsigned int max = 5; + + DALI_TEST_CHECK(min != detector.GetMinimumTouchesRequired()); + DALI_TEST_CHECK(max != detector.GetMaximumTouchesRequired()); + + detector.SetTouchesRequired(min, max); + + DALI_TEST_EQUALS(min, detector.GetMinimumTouchesRequired(), TEST_LOCATION); + DALI_TEST_EQUALS(max, detector.GetMaximumTouchesRequired(), TEST_LOCATION); + + // Attach an actor and change the maximum touches + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + TestGestureManager& gestureManager = application.GetGestureManager(); + gestureManager.Initialize(); + + detector.SetTouchesRequired(4, 5); + + // Gesture detection should have been updated only + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + // Reset values + gestureManager.Initialize(); + + // Create a second gesture detector that requires even less maximum touches + LongPressGestureDetector secondDetector = LongPressGestureDetector::New(); + secondDetector.Attach(actor); + + // Gesture detection should have been updated + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureGetMinimumTouchesRequired(void) +{ + TestApplication application; + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + DALI_TEST_EQUALS(1u, detector.GetMinimumTouchesRequired(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureGetMaximumTouchesRequired(void) +{ + TestApplication application; + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + DALI_TEST_EQUALS(1u, detector.GetMaximumTouchesRequired(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureSignalReceptionNegative(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Do a long press outside actor's area + application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, Vector2(112.0f, 112.0f ) ) ); + application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, Vector2(112.0f, 112.0f ) ) ); + application.ProcessEvent( GenerateLongPress( Gesture::Finished, 1u, Vector2(112.0f, 112.0f ) ) ); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureSignalReceptionPositive(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Do a long press inside actor's area + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 50.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 50.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(50.0f, 50.0f), data.receivedGesture.localPoint, 0.1, TEST_LOCATION); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 50.0f))); + END_TEST; +} + +int UtcDaliLongPressGestureSignalReceptionDetach(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start long press within the actor's area + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(20.0f, 20.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(20.0f, 20.0f), data.receivedGesture.localPoint, 0.1, TEST_LOCATION); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(20.0f, 20.0f))); + + // repeat the long press within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 50.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 50.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(50.0f, 50.0f), data.receivedGesture.localPoint, 0.1, TEST_LOCATION); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 50.0f))); + + // Detach actor + detector.DetachAll(); + + // Ensure we are no longer signalled + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(20.0f, 20.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 50.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureSignalReceptionActorDestroyedDuringLongPress(void) +{ + TestApplication application; + + SignalData data; + GestureReceivedFunctor functor(data); + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.DetectedSignal().Connect(&application, functor); + + // Actor lifetime is scoped + { + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + detector.Attach(actor); + + // Start long press within the actor's area + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(20.0f, 20.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Remove the actor from stage and reset the data + Stage::GetCurrent().Remove(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + } + + // Actor should now have been destroyed + + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureSignalReceptionRotatedActor(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Do a long press + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(5.0f, 5.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(5.0f, 5.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(5.0f, 5.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(5.0f, 5.0f), data.receivedGesture.screenPoint, 0.1, TEST_LOCATION); + + // Rotate actor again and render + actor.SetOrientation(Dali::Degree(180.0f), Vector3::ZAXIS); + application.SendNotification(); + application.Render(); + + // Do another long press, should still receive event + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(5.0f, 5.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(5.0f, 5.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(5.0f, 5.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(5.0f, 5.0f), data.receivedGesture.screenPoint, 0.1, TEST_LOCATION); + + // Rotate actor again and render + actor.SetOrientation(Dali::Degree(90.0f), Vector3::YAXIS); + application.SendNotification(); + application.Render(); + + // Do a long press, inside where the actor used to be, Should not receive the event + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(70.0f, 70.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(70.0f, 70.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(70.0f, 70.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureSignalReceptionChildHit(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + parent.SetSize(100.0f, 100.0f); + parent.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(parent); + + // Set child to completely cover parent. + // Change rotation of child to be different from parent so that we can check if our local coordinate + // conversion of the parent actor is correct. + Actor child = Actor::New(); + child.SetSize(100.0f, 100.0f); + child.SetAnchorPoint(AnchorPoint::CENTER); + child.SetParentOrigin(ParentOrigin::CENTER); + child.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS); + parent.Add(child); + + TouchEventFunctor touchFunctor; + child.TouchedSignal().Connect(&application, touchFunctor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(parent); + detector.DetectedSignal().Connect(&application, functor); + + // Do long press - hits child area but parent should still receive it + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 50.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 50.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 50.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, parent == data.pressedActor, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(50.0f, 50.0f), data.receivedGesture.screenPoint, 0.01f, TEST_LOCATION); + + // Attach child and generate same touch points + // (Also proves that you can detach and then re-attach another actor) + detector.Attach(child); + detector.Detach(parent); + + // Do an entire long press, only check finished value + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(51.0f, 51.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(51.0f, 51.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(51.0f, 51.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, child == data.pressedActor, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(51.0f, 51.0f), data.receivedGesture.screenPoint, 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureSignalReceptionAttachDetachMany(void) +{ + TestApplication application; + + Actor first = Actor::New(); + first.SetSize(100.0f, 100.0f); + first.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(first); + + Actor second = Actor::New(); + second.SetSize(100.0f, 100.0f); + second.SetX(100.0f); + second.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(second); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(first); + detector.Attach(second); + detector.DetectedSignal().Connect(&application, functor); + + // LongPress within second actor's area + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(120.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(120.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(120.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, second == data.pressedActor, TEST_LOCATION); + + // LongPress within first actor's area + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(20.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(20.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, first == data.pressedActor, TEST_LOCATION); + + // Detach the second actor + detector.Detach(second); + + // second actor shouldn't receive event + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(120.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(120.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(120.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // first actor should continue receiving event + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(20.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(20.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureSignalReceptionActorBecomesUntouchable(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // LongPress in actor's area + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Actor becomes invisible - actor should not receive the next long press + actor.SetVisible(false); + + // Render and notify + application.SendNotification(); + application.Render(); + + // LongPress in the same area, shouldn't receive event + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureSignalReceptionMultipleGestureDetectors(void) +{ + TestApplication application; + Dali::TestGestureManager& gestureManager = application.GetGestureManager(); + + Actor first = Actor::New(); + first.SetSize(100.0f, 100.0f); + first.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(first); + + Actor second = Actor::New(); + second.SetSize(100.0f, 100.0f); + second.SetAnchorPoint(AnchorPoint::TOP_LEFT); + second.SetX(100.0f); + first.Add(second); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + LongPressGestureDetector firstDetector = LongPressGestureDetector::New(); + firstDetector.Attach(first); + firstDetector.DetectedSignal().Connect(&application, functor); + + // secondDetector is scoped + { + // Reset gestureManager statistics + gestureManager.Initialize(); + + LongPressGestureDetector secondDetector = LongPressGestureDetector::New(); + secondDetector.SetTouchesRequired(2); + secondDetector.Attach(second); + secondDetector.DetectedSignal().Connect(&application, functor); + + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + // LongPress within second actor's area + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 2u, Vector2(150.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 2u, Vector2(150.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 2u, Vector2(150.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, second == data.pressedActor, TEST_LOCATION); + + // LongPress continues as single touch gesture - we should not receive any gesture + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(150.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(150.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(150.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Single touch long press starts - first actor should receive gesture + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, first == data.pressedActor, TEST_LOCATION); + + // long press changes to double-touch - we shouldn't receive event + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 2u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 2u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 2u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Reset gesture manager statistics + gestureManager.Initialize(); + } + + // secondDetector has now been deleted. Gesture detection should have been updated only + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureSignalReceptionMultipleDetectorsOnActor(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to one detector + SignalData firstData; + GestureReceivedFunctor firstFunctor(firstData); + LongPressGestureDetector firstDetector = LongPressGestureDetector::New(); + firstDetector.Attach(actor); + firstDetector.DetectedSignal().Connect(&application, firstFunctor); + + // Attach actor to another detector + SignalData secondData; + GestureReceivedFunctor secondFunctor(secondData); + LongPressGestureDetector secondDetector = LongPressGestureDetector::New(); + secondDetector.Attach(actor); + secondDetector.DetectedSignal().Connect(&application, secondFunctor); + + // LongPress in actor's area - both detector's functors should be called + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureSignalReceptionDifferentPossible(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // LongPress possible in actor's area. + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Move actor somewhere else + actor.SetPosition( 100.0f, 100.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit Started event, we should not receive the long press. + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // LongPress possible in empty area. + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Move actor in to the long press position. + actor.SetPosition( 0.0f, 0.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit Started event, we should not receive the long press. + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Normal long press in actor's area for completeness. + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureEmitIncorrectStateClear(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Try a Clear state + try + { + application.ProcessEvent(GenerateLongPress(Gesture::Clear, 1u, Vector2(50.0f, 10.0f))); + tet_result(TET_FAIL); + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_ASSERT( e, "false", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliLongPressGestureEmitIncorrectStateContinuing(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Try a Continuing state + try + { + application.ProcessEvent(GenerateLongPress(Gesture::Continuing, 1u, Vector2(50.0f, 10.0f))); + tet_result(TET_FAIL); + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_ASSERT( e, "false", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliLongPressGestureRepeatedState(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Two possibles + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // ... Send some finished states, still no signal + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Send two Started states, should be signalled + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Send two cancelled states, should not be signalled + application.ProcessEvent(GenerateLongPress(Gesture::Cancelled, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + application.ProcessEvent(GenerateLongPress(Gesture::Cancelled, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGesturePossibleCancelled(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Send a possible followed by a cancel, we should not be signalled + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + application.ProcessEvent(GenerateLongPress(Gesture::Cancelled, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureDetachAfterStarted(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Emit initial signal + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Detach actor + detector.Detach(actor); + + // Emit Finished, no signal + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureActorUnstaged(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // State to remove actor in. + Gesture::State stateToUnstage( Gesture::Started ); + + // Attach actor to detector + SignalData data; + UnstageActorFunctor functor( data, stateToUnstage ); + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Emit signals + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Re-add actor to stage + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Change state to Gesture::Continuing to remove + stateToUnstage = Gesture::Finished; + + // Emit signals + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + tet_result( TET_PASS ); // If we get here then we have handled actor stage removal gracefully. + END_TEST; +} + +int UtcDaliLongPressGestureActorStagedAndDestroyed(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Create and add a second actor so that GestureDetector destruction does not come into play. + Actor dummyActor( Actor::New() ); + dummyActor.SetSize( 100.0f, 100.0f ); + dummyActor.SetPosition( 100.0f, 100.0f ); + dummyActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(dummyActor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // State to remove actor in. + Gesture::State stateToUnstage( Gesture::Started ); + + // Attach actor to detector + SignalData data; + UnstageActorFunctor functor( data, stateToUnstage ); + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.Attach(dummyActor); + detector.DetectedSignal().Connect( &application, functor ); + + // Here we are testing a Started actor which is removed in the Started callback, but then added back + // before we get a finished state. As we were removed from the stage, even if we're at the same + // position, we should still not be signalled. + + // Emit signals + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Re add to the stage, we should not be signalled + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Continue signal emission + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Here we delete an actor in started, we should not receive any subsequent signalling. + + // Emit signals + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Delete actor as well + actor.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Continue signal emission + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliLongPressGestureSystemOverlay(void) +{ + TestApplication application; + Dali::Integration::Core& core = application.GetCore(); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Do a long press inside actor's area + Vector2 screenCoords( 50.0f, 50.0f ); + application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, screenCoords ) ); + application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, screenCoords ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliLongPressGestureBehindTouchableSystemOverlay(void) +{ + TestApplication application; + Dali::Integration::Core& core = application.GetCore(); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + // SystemOverlay actor + Actor systemOverlayActor = Actor::New(); + systemOverlayActor.SetSize(100.0f, 100.0f); + systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add(systemOverlayActor); + + // Stage actor + Actor stageActor = Actor::New(); + stageActor.SetSize(100.0f, 100.0f); + stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(stageActor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set system-overlay actor to touchable + TouchEventData touchData; + TouchEventDataFunctor touchFunctor( touchData ); + systemOverlayActor.TouchedSignal().Connect(&application, touchFunctor); + + // Set stage actor to receive the gesture + SignalData data; + GestureReceivedFunctor functor(data); + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(stageActor); + detector.DetectedSignal().Connect(&application, functor); + + // Start long press within the two actors' area + Vector2 screenCoords( 50.0f, 50.0f ); + application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, screenCoords ) ); + application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, screenCoords ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION ); + + data.Reset(); + touchData.Reset(); + + // Do touch in the same area + application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoords ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliLongPressGestureTouchBehindGesturedSystemOverlay(void) +{ + TestApplication application; + Dali::Integration::Core& core = application.GetCore(); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + // SystemOverlay actor + Actor systemOverlayActor = Actor::New(); + systemOverlayActor.SetSize(100.0f, 100.0f); + systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add(systemOverlayActor); + + // Stage actor + Actor stageActor = Actor::New(); + stageActor.SetSize(100.0f, 100.0f); + stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(stageActor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set stage actor to touchable + TouchEventData touchData; + TouchEventDataFunctor touchFunctor( touchData ); + stageActor.TouchedSignal().Connect(&application, touchFunctor); + + // Set system-overlay actor to have the gesture + SignalData data; + GestureReceivedFunctor functor(data); + + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(systemOverlayActor); + detector.DetectedSignal().Connect(&application, functor); + + // Start long press within the two actors' area + Vector2 screenCoords( 50.0f, 50.0f ); + application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, screenCoords ) ); + application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, screenCoords ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION ); + + data.Reset(); + touchData.Reset(); + + // Do touch in the same area + application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoords ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliLongPressGestureLayerConsumesTouch(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Add a detector + SignalData data; + GestureReceivedFunctor functor(data); + LongPressGestureDetector detector = LongPressGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Add a layer to overlap the actor + Layer layer = Layer::New(); + layer.SetSize(100.0f, 100.0f); + layer.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add( layer ); + layer.RaiseToTop(); + + // Render and notify + application.SendNotification(); + application.Render(); + + Vector2 screenCoords( 50.0f, 50.0f ); + + // Emit signals, should receive + application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, screenCoords ) ); + application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, screenCoords ) ); + application.ProcessEvent( GenerateLongPress( Gesture::Finished, 1u, screenCoords ) ); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Set layer to consume all touch + layer.SetTouchConsumed( true ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit the same signals again, should not receive + application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, screenCoords ) ); + application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, screenCoords ) ); + application.ProcessEvent( GenerateLongPress( Gesture::Finished, 1u, screenCoords ) ); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-MathUtils.cpp b/automated-tests/src/dali/utc-Dali-MathUtils.cpp new file mode 100644 index 0000000..d8a5b4e --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-MathUtils.cpp @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_math_utils_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_math_utils_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliMathUtilsIsPowerOfTwo(void) +{ + Dali::TestApplication testApp; + DALI_TEST_EQUALS(IsPowerOfTwo(0), false, TEST_LOCATION); + + DALI_TEST_EQUALS(IsPowerOfTwo(1), true, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(2), true, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(3), false, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(4), true, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(5), false, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(6), false, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(7), false, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(8), true, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(255), false, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(256), true, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(257), false, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(511), false, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(512), true, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(513), false, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(768), false, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(1023), false, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(1024), true, TEST_LOCATION); + DALI_TEST_EQUALS(IsPowerOfTwo(1025), false, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliMathUtilsNextPowerOfTwoP(void) +{ + Dali::TestApplication testApp; + + DALI_TEST_EQUALS(NextPowerOfTwo(0), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(1), 1u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(2), 2u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(3), 4u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(4), 4u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(5), 8u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(6), 8u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(7), 8u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(8), 8u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(255), 256u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(256), 256u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(257), 512u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(511), 512u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(512), 512u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(513), 1024u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(768), 1024u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(1023), 1024u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(1024), 1024u, TEST_LOCATION); + DALI_TEST_EQUALS(NextPowerOfTwo(1025), 2048u, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMathUtilsNextPowerOfTwoN(void) +{ + Dali::TestApplication testApp; + + try + { + NextPowerOfTwo( (1u << (sizeof(unsigned) * 8 - 1)) + 1); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "Return type cannot represent the next power of two greater than the argument.", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + END_TEST; +} + +int UtcDaliMathUtilsClampP(void) +{ + Dali::TestApplication testApp; + + //floats + DALI_TEST_EQUALS(Clamp(-1.0f, 0.0f, 1.0f), 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Clamp(0.0f, -1.0f, 1.0f), 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Clamp(1.0f, 0.0f, 1.0f), 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Clamp(2.0f, 0.0f, 1.0f), 1.0f, TEST_LOCATION); + + // integers + DALI_TEST_EQUALS(Clamp(-10, 0, 10), 0, TEST_LOCATION); + DALI_TEST_EQUALS(Clamp(0, -10, 10), 0, TEST_LOCATION); + DALI_TEST_EQUALS(Clamp(20, 0, 10), 10, TEST_LOCATION); + + float value=-10.0f, min=-2.0f, max=4.0f; + ClampInPlace(value, min, max); + DALI_TEST_EQUALS(value, min, 0.001, TEST_LOCATION); + + value = 10.0f; + ClampInPlace(value, min, max); + DALI_TEST_EQUALS(value, max, 0.001, TEST_LOCATION); + + value = 3.0f; + ClampInPlace(value, min, max); + DALI_TEST_EQUALS(value, 3.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMathUtilsClampInPlaceP(void) +{ + Dali::TestApplication testApp; + + float value=-10.0f, min=-2.0f, max=4.0f; + ClampInPlace(value, min, max); + DALI_TEST_EQUALS(value, min, 0.001, TEST_LOCATION); + + value = 10.0f; + ClampInPlace(value, min, max); + DALI_TEST_EQUALS(value, max, 0.001, TEST_LOCATION); + + value = 3.0f; + ClampInPlace(value, min, max); + DALI_TEST_EQUALS(value, 3.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMathUtilsLerpP(void) +{ + Dali::TestApplication testApp; + + float offset=0.0f, low=-2.0f, high=4.0f; + DALI_TEST_EQUALS(Lerp(offset, low, high), low, 0.001, TEST_LOCATION); + offset = 1.0f; + DALI_TEST_EQUALS(Lerp(offset, low, high), high, 0.001, TEST_LOCATION); + offset = 0.5f; + DALI_TEST_EQUALS(Lerp(offset, low, high), 1.0f, 0.001, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliMathUtilsGetRangedEpsilonP(void) +{ + Dali::TestApplication testApp; + + DALI_TEST_EQUALS(GetRangedEpsilon(0.05f, 0.02f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(0.05f, 0.02f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(0.05f, 0.099f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(0.099f, 0.02f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(0.05f, 0.5f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(0.99f, 0.5f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(0.99f, 0.98f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(1.05f, 0.99f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(1.99f, 1.05f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + + DALI_TEST_EQUALS(GetRangedEpsilon(2.0f, 1.99f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(0.05f, 2.0f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(1.0f, 3.0f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(9.99f, 0.5f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(9.99f, 1.5f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(9.99f, 9.99f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(9.99f, 10.0f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(19.99f, 10.0f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + + DALI_TEST_EQUALS(GetRangedEpsilon(20.0f, 10.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(20.0f, 30.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(80.0f, 90.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(180.0f, 190.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(185.0f, 190.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(199.0f, 199.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION); + + DALI_TEST_EQUALS(GetRangedEpsilon(200.0f, 190.0f), Dali::Math::MACHINE_EPSILON_1000, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(0.005f, 1999.0f), Dali::Math::MACHINE_EPSILON_1000, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(2000.0f, 190.0f), Dali::Math::MACHINE_EPSILON_10000, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(0.005f, 19999.0f), Dali::Math::MACHINE_EPSILON_10000, TEST_LOCATION); + + DALI_TEST_EQUALS(GetRangedEpsilon(1e07f, 0.99e09f), Dali::Math::MACHINE_EPSILON_10000, TEST_LOCATION); + + + DALI_TEST_EQUALS(GetRangedEpsilon(-0.05f, -0.02f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-0.05f, -0.02f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-0.05f, -0.099f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-0.099f, - 0.02f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-0.05f, -0.5f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-0.99f, -0.5f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-0.99f, -0.98f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-1.05f, -0.99f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-1.99f, -1.05f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + + DALI_TEST_EQUALS(GetRangedEpsilon(-2.0f, - 1.99f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-0.05f, -2.0f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-1.0f, - 3.0f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-9.99f, -0.5f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-9.99f, -1.5f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-9.99f, -9.99f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-9.99f, -10.0f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-19.99f, -10.0f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + + DALI_TEST_EQUALS(GetRangedEpsilon(-20.0f, -10.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-20.0f, -30.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-80.0f, -90.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-180.0f, -190.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-185.0f, -190.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-199.0f, -199.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION); + + DALI_TEST_EQUALS(GetRangedEpsilon(-200.0f, -190.0f), Dali::Math::MACHINE_EPSILON_1000, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-0.005f, -1999.0f), Dali::Math::MACHINE_EPSILON_1000, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-2000.0f, -190.0f), Dali::Math::MACHINE_EPSILON_10000, TEST_LOCATION); + DALI_TEST_EQUALS(GetRangedEpsilon(-0.005f, -19999.0f), Dali::Math::MACHINE_EPSILON_10000, TEST_LOCATION); + + DALI_TEST_EQUALS(GetRangedEpsilon(-1e07f, -0.99e09f), Dali::Math::MACHINE_EPSILON_10000, TEST_LOCATION); + + + END_TEST; +} + +int UtcDaliMathUtilsWrapInDomainP(void) +{ + Dali::TestApplication testApp; + + DALI_TEST_EQUALS(WrapInDomain(0.0f, 0.0f, 0.0f), 0.0f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(WrapInDomain(-5.0f, 0.0f, 0.0f), 0.0f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(WrapInDomain(5.0f, 0.0f, 0.0f), 0.0f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(WrapInDomain(0.0f, 0.0f, 10.0f), 0.0f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(WrapInDomain(-5.0f, 0.0f, 10.0f), 5.0f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(WrapInDomain(5.0f, 0.0f, 10.0f), 5.0f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(WrapInDomain(-2.5f, 0.0f, 10.0f), 7.5f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(WrapInDomain(2.5f, 0.0f, 10.0f), 2.5f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(WrapInDomain(2.5f, 0.0f, 1.0f), 0.5f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(WrapInDomain(2.5f, -2.0f, -1.0f), -1.5f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + DALI_TEST_EQUALS(WrapInDomain(-2.9f, -2.0f, -1.0f), -1.9f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(WrapInDomain(-1.1f, -2.0f, -1.0f), -1.1f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMathUtilsShortestDistanceInDomainP(void) +{ + Dali::TestApplication testApp; + + DALI_TEST_EQUALS(ShortestDistanceInDomain(1.0f, 8.0f, 0.0f, 10.0f), -3.0f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(ShortestDistanceInDomain(5.0f, 8.0f, 0.0f, 10.0f), 3.0f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(ShortestDistanceInDomain(5.0f, 8.0f, 4.0f, 9.0f), -2.0f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(ShortestDistanceInDomain(8.0f, 5.0f, 4.0f, 9.0f), 2.0f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(ShortestDistanceInDomain(0.65f, 0.1f, -1.0f, 1.0f), -0.55f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(ShortestDistanceInDomain(0.95f, -0.9f, -1.0f, 1.0f), 0.15f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + DALI_TEST_EQUALS(ShortestDistanceInDomain(0.0f, -0.9f, -1.0f, 1.0f), -0.9f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMathUtilsEqualsZeroP(void) +{ + float v=0.0f; + + DALI_TEST_CHECK(EqualsZero(v)); + + v = Math::PI; + v -= (Math::PI_2 * 2.0f); + DALI_TEST_CHECK(EqualsZero(v)); + + END_TEST; +} + +int UtcDaliMathUtilsEquals01P(void) +{ + float w=100.0f; + float x=w+1e-8f; + DALI_TEST_CHECK( Equals(w, x, GetRangedEpsilon( w, x )) ); + END_TEST; +} + +int UtcDaliMathUtilsEquals02P(void) +{ + float w=100.0f; + float x=w+1e-8f; + DALI_TEST_CHECK( Equals(w, x) ); + END_TEST; +} + +int UtcDaliMathUtilsRoundP(void) +{ + Dali::TestApplication testApp; + + DALI_TEST_EQUALS(Round(1.00001, 4), 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Round(0.99999f, 4), 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Round(-1.00001, 4), -1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Round(-0.99999f, 4), -1.0f, TEST_LOCATION); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Matrix.cpp b/automated-tests/src/dali/utc-Dali-Matrix.cpp new file mode 100644 index 0000000..cd2525f --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Matrix.cpp @@ -0,0 +1,802 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include + +using namespace Dali; + + +void utc_dali_matrix_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_matrix_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +int UtcDaliMatrixConstructor01P(void) +{ + Matrix m2(false); + + bool initialised = true; + { + float* els = m2.AsFloat(); + for(size_t idx=0; idx<16; ++idx, ++els) + { + if(*els != 0.0f) + initialised = false; + } + } + + DALI_TEST_EQUALS(initialised, false, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliMatrixConstructor02P(void) +{ + float r[] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f}; + Matrix m(r); + + float* els = m.AsFloat(); + float* init = r; + bool initialised = true; + for(size_t idx=0; idx<16; ++idx, ++els, ++init) + { + if(*els != *init) + initialised = false; + } + DALI_TEST_EQUALS(initialised, true, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliMatrixConstructor03P(void) +{ + float r[] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f}; + + Matrix ma(r); + Matrix mb(ma); + + float* els = ma.AsFloat(); + float* init = mb.AsFloat(); + bool initialised = true; + for(size_t idx=0; idx<16; ++idx, ++els, ++init) + { + if(*els != *init) + initialised = false; + } + DALI_TEST_EQUALS(initialised, true, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliMatrixConstructor04P(void) +{ + Quaternion q(Quaternion::IDENTITY); + Matrix m(q); + DALI_TEST_EQUALS(Matrix(Matrix::IDENTITY), m, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrixAssignP(void) +{ + Matrix a(Matrix::IDENTITY); + Matrix b = a; + DALI_TEST_EQUALS(a, b, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrixAssign02P(void) +{ + Matrix a(Matrix::IDENTITY); + a = a; // self assign does the do nothing branch + DALI_TEST_EQUALS(Matrix(Matrix::IDENTITY), a, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrixSetIdentityP(void) +{ + float els[] = { 0.0f, 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f, 7.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f }; + Matrix m(els); + m.SetIdentity(); + + DALI_TEST_EQUALS(m, Matrix::IDENTITY, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrixSetIdentityAndScaleP(void) +{ + float els[] = { 0.0f, 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f, 7.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f }; + Matrix m(els); + m.SetIdentityAndScale(Vector3(4.0f, 4.0f, 4.0f)); + + float els2[] = { 4.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 4.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 4.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; + Matrix r(els2); + + DALI_TEST_EQUALS(m, r, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrixInvertTransformP(void) +{ + for (int i=0;i<1000;++i) + { + float f = i; + Vector3 axis(cosf(f*0.001f), cosf(f*0.02f), cosf(f*0.03f)); + axis.Normalize(); + Vector3 center(f, cosf(f) * 100.0f, cosf(f*0.5f) * 50.0f); + + Matrix m0; + m0.SetIdentity(); + m0.SetTransformComponents( Vector3::ONE, Quaternion(Radian(1.0f), axis), center ); + + Matrix m1; + m0.InvertTransform(m1); + + Matrix m2( false ); + Matrix::Multiply( m2, m0, m1 ); + + DALI_TEST_EQUALS(m2, Matrix::IDENTITY, 0.001f, TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliMatrixInvertTransformN(void) +{ + std::string exceptionString( "EqualsZero( mMatrix[3] ) && EqualsZero( mMatrix[7] ) && EqualsZero( mMatrix[11] ) && Equals( mMatrix[15], 1.0f" ); + try + { + float els[] = { 0.0f, 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f, 7.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f }; + Matrix m(els); + + Matrix it; + m.InvertTransform(it); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, exceptionString, TEST_LOCATION ); + } + + try + { + float els[] = { 0.0f, 1.0f, 2.0f, 0.0f, + 4.0f, 5.0f, 6.0f, 7.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f }; + Matrix m(els); + + Matrix it; + m.InvertTransform(it); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, exceptionString, TEST_LOCATION ); + } + + try + { + float els[] = { 0.0f, 1.0f, 2.0f, 0.0f, + 4.0f, 5.0f, 6.0f, 0.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f }; + Matrix m(els); + + Matrix it; + m.InvertTransform(it); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, exceptionString, TEST_LOCATION ); + } + + try + { + float els[] = { 0.0f, 1.0f, 2.0f, 0.0f, + 4.0f, 5.0f, 6.0f, 0.0f, + 8.0f, 9.0f, 10.0f, 0.0f, + 12.0f, 13.0f, 14.0f, 15.0f }; + Matrix m(els); + + Matrix it; + m.InvertTransform(it); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, exceptionString, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliMatrixInvert01P(void) +{ + // We're going to invert a whole load of different matrices to make sure we don't + // fail on particular orientations. + for (int i=0;i<1000;++i) + { + float f = i; + Vector3 axis(cosf(f*0.001f), cosf(f*0.02f), cosf(f*0.03f)); + axis.Normalize(); + Vector3 center(f, cosf(f) * 100.0f, cosf(f*0.5f) * 50.0f); + + Matrix m0; + m0.SetIdentity(); + m0.SetTransformComponents( Vector3::ONE, Quaternion(Radian(1.0f), axis), center ); + + Matrix m1(m0); + m1.Invert(); + + Matrix m2( false ); + Matrix::Multiply( m2, m0, m1 ); + + DALI_TEST_EQUALS(m2, Matrix::IDENTITY, 0.001f, TEST_LOCATION); + + m1.Invert(); // doube invert - should be back to m0 + + DALI_TEST_EQUALS(m0, m1, 0.001f, TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliMatrixInvert02P(void) +{ + Matrix m1 = Matrix::IDENTITY; + m1.SetXAxis(Vector3(0.0f, 0.0f, 0.0f)); + DALI_TEST_EQUALS(m1.Invert(), false, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrixTransposeP(void) +{ + float floats[] = + { 0.0f, 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f, 7.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f + }; + + Matrix m(floats); + m.Transpose(); + + bool success = true; + + for (int x=0;x<4;++x) + { + for (int y=0;y<4;++y) + { + success &= (m.AsFloat()[x+y*4] == floats[x*4+y]); + } + } + + DALI_TEST_CHECK(success); + END_TEST; +} + +int UtcDaliMatrixGetXAxisP(void) +{ + float els[] = { 0.0f, 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f, 7.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f }; + Matrix m(els); + + DALI_TEST_CHECK(m.GetXAxis() == Vector3(0.0f, 1.0f, 2.0f)); + END_TEST; +} + +int UtcDaliMatrixGetYAxisP(void) +{ + float els[] = { 0.0f, 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f, 7.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f }; + Matrix m(els); + + DALI_TEST_CHECK(m.GetYAxis() == Vector3(4.0f, 5.0f, 6.0f)); + END_TEST; +} + +int UtcDaliMatrixGetZAxisP(void) +{ + float els[] = { 0.0f, 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f, 7.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f }; + Matrix m(els); + + DALI_TEST_CHECK(m.GetZAxis() == Vector3(8.0f, 9.0f, 10.0f)); + END_TEST; +} + +int UtcDaliMatrixSetXAxisP(void) +{ + Matrix m; + Vector3 v(2.0f, 3.0f, 4.0f); + m.SetXAxis(v); + + DALI_TEST_CHECK(m.GetXAxis() == v); + END_TEST; +} + +int UtcDaliMatrixSetYAxisP(void) +{ + Matrix m; + Vector3 v(2.0f, 3.0f, 4.0f); + m.SetYAxis(v); + + DALI_TEST_CHECK(m.GetYAxis() == v); + END_TEST; +} + +int UtcDaliMatrixSetZAxisP(void) +{ + Matrix m; + Vector3 v(2.0f, 3.0f, 4.0f); + m.SetZAxis(v); + + DALI_TEST_CHECK(m.GetZAxis() == v); + END_TEST; +} + +int UtcDaliMatrixGetTranslationP(void) +{ + float els[] = { 0.0f, 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f, 7.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f }; + Matrix m(els); + + DALI_TEST_EQUALS(m.GetTranslation(), Vector4(12.0f, 13.0f, 14.0f, 15.0f), TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrixGetTranslation3P(void) +{ + float els[] = { 0.0f, 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f, 7.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f }; + Matrix m(els); + + DALI_TEST_EQUALS(m.GetTranslation3(), Vector3(12.0f, 13.0f, 14.0f), TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrixSetTranslationP(void) +{ + Matrix m; + Vector4 v(2.0f, 3.0f, 4.0f, 5.0f); + m.SetTranslation(v); + + DALI_TEST_CHECK(m.GetTranslation() == v); + END_TEST; +} + +int UtcDaliMatrixSetTranslation3P(void) +{ + Matrix m; + Vector3 v(2.0f, 3.0f, 4.0f); + m.SetTranslation(v); + + DALI_TEST_CHECK(m.GetTranslation3() == v); + END_TEST; +} + +int UtcDaliMatrixOrthoNormalize0P(void) +{ + // OrthoNormalise fixes floating point errors from matrix rotations + Matrix m; + m.SetIdentity(); + + for (int i=0;i<1000;++i) + { + float f = i; + Vector3 axis(cosf(f*0.001f), cosf(f*0.02f), cosf(f*0.03f)); + axis.Normalize(); + + m.SetTransformComponents( Vector3::ONE, Quaternion(Radian(1.0f), axis), Vector3::ZERO ); + m.OrthoNormalize(); + } + + bool success = true; + success &= fabsf(m.GetXAxis().Dot(m.GetYAxis())) < 0.001f; + success &= fabsf(m.GetYAxis().Dot(m.GetXAxis())) < 0.001f; + success &= fabsf(m.GetZAxis().Dot(m.GetYAxis())) < 0.001f; + + success &= fabsf(m.GetXAxis().Length() - 1.0f) < 0.001f; + success &= fabsf(m.GetYAxis().Length() - 1.0f) < 0.001f; + success &= fabsf(m.GetZAxis().Length() - 1.0f) < 0.001f; + + DALI_TEST_CHECK(success); + END_TEST; +} + +int UtcDaliMatrixOrthoNormalize1P(void) +{ + // OrthoNormalize is not flipping the axes and is maintaining the translation + for (int i=0;i<1000;++i) + { + float f = i; + Vector3 axis(cosf(f*0.001f), cosf(f*0.02f), cosf(f*0.03f)); + axis.Normalize(); + Vector3 center(10.0f, 15.0f, 5.0f); + + Matrix m0; + m0.SetIdentity(); + m0.SetTransformComponents( Vector3::ONE, Quaternion(Radian(1.0f), axis), center ); + + Matrix m1(m0); + m1.OrthoNormalize(); + + DALI_TEST_EQUALS(m0.GetXAxis(), m1.GetXAxis(), 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(m0.GetYAxis(), m1.GetYAxis(), 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(m0.GetZAxis(), m1.GetZAxis(), 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(m0.GetTranslation(), m1.GetTranslation(), 0.001f, TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliMatrixConstAsFloatP(void) +{ + float r[] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f}; + const Matrix m(r); + + const float* els = m.AsFloat(); + const float* init = r; + bool initialised = true; + for(size_t idx=0; idx<16; ++idx, ++els, ++init) + { + if(*els != *init) + initialised = false; + } + DALI_TEST_EQUALS(initialised, true, TEST_LOCATION); + + + END_TEST; +} + +int UtcDaliMatrixAsFloatP(void) +{ + float r[] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f}; + Matrix m(r); + + float* els = m.AsFloat(); + float* init = r; + bool initialised = true; + for(size_t idx=0; idx<16; ++idx, ++els, ++init) + { + if(*els != *init) + initialised = false; + } + DALI_TEST_EQUALS(initialised, true, TEST_LOCATION); + + + END_TEST; +} + +int UtcDaliMatrixMultiplyP(void) +{ + Matrix m1 = Matrix::IDENTITY; + + float els[] = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.707f, 0.707f, 0.0f, + 0.0f, -0.707f, 0.707f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; + Matrix result(els); + + Quaternion q(Radian(Degree(45.0f)), Vector3::XAXIS); + Matrix m2(false); + Matrix::Multiply(m2, m1, q); + + DALI_TEST_EQUALS(m2, result, 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrixOperatorMultiply01P(void) +{ + Vector4 v1(2.0f, 5.0f, 4.0f, 0.0f); + + float els[] = {2.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 3.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 4.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; + Matrix m1(els); + + Vector4 v2 = m1 * v1; + Vector4 r1(4.0f, 15.0f, 16.0f, 0.0f); + DALI_TEST_EQUALS(v2, r1, 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrixOperatorMultiply02P(void) +{ + TestApplication application; + + Vector3 position ( 30.f, 40.f, 50.f); + + Matrix m1(false); + m1.SetIdentity(); + m1.SetTranslation(-position); + + Vector4 positionV4(position); + positionV4.w=1.0f; + Vector4 output = m1 * positionV4; + + output.w = 0.0f; + DALI_TEST_EQUALS(output, Vector4::ZERO, 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrixOperatorEqualsP(void) +{ + Matrix m1 = Matrix::IDENTITY; + + float els[] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; + Matrix r2(els); + DALI_TEST_EQUALS(m1 == r2, true, TEST_LOCATION); + + float *f = m1.AsFloat(); + for(size_t i=0; i<16; i++) + { + f[15-i] = 1.2f; + DALI_TEST_EQUALS(m1 == r2, false, TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliMatrixOperatorNotEqualsP(void) +{ + Matrix m1 = Matrix::IDENTITY; + float els[] = {2.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 3.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 4.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; + Matrix r1(els); + + DALI_TEST_CHECK(m1 != r1); + DALI_TEST_CHECK(!(m1 != m1)); + END_TEST; +} + +int UtcDaliMatrixSetTransformComponents01P(void) +{ + // Create an arbitrary vector + for( float x=-1.0f; x<=1.0f; x+=0.1f ) + { + for( float y=-1.0f; y<1.0f; y+=0.1f ) + { + for( float z=-1.0f; z<1.0f; z+=0.1f ) + { + Vector3 vForward(x, y, z); + vForward.Normalize(); + + for( float angle = 5.0f; angle <= 360.0f; angle += 15.0f) + { + Quaternion rotation1(Radian(Degree(angle)), vForward); + + Matrix m1(rotation1); + Matrix result1(false); + Vector3 vForward3(vForward.x, vForward.y, vForward.z); + result1.SetTransformComponents( Vector3::ONE, Quaternion(Radian(Degree(angle)), vForward3), Vector3::ZERO ); + + DALI_TEST_EQUALS(m1, result1, 0.001, TEST_LOCATION); + + Matrix m2(false); + m2.SetTransformComponents(vForward, Quaternion::IDENTITY, Vector3::ZERO); + + Matrix result2a(Matrix::IDENTITY); + result2a.SetXAxis(result2a.GetXAxis() * vForward[0]); + result2a.SetYAxis(result2a.GetYAxis() * vForward[1]); + result2a.SetZAxis(result2a.GetZAxis() * vForward[2]); + + DALI_TEST_EQUALS(m2, result2a, 0.001, TEST_LOCATION); + + Matrix m3(false); + m3.SetTransformComponents(vForward, rotation1, Vector3::ZERO); + + Matrix result3(Matrix::IDENTITY); + result3.SetXAxis(result3.GetXAxis() * vForward[0]); + result3.SetYAxis(result3.GetYAxis() * vForward[1]); + result3.SetZAxis(result3.GetZAxis() * vForward[2]); + + Matrix::Multiply(result3, result3, m1); + DALI_TEST_EQUALS(m3, result3, 0.001, TEST_LOCATION); + } + } + } + } + END_TEST; +} + +int UtcDaliMatrixSetInverseTransformComponent01P(void) +{ + // Create an arbitrary vector + for( float x=-1.0f; x<=1.0f; x+=0.1f ) + { + for( float y=-1.0f; y<1.0f; y+=0.1f ) + { + for( float z=-1.0f; z<1.0f; z+=0.1f ) + { + Vector3 vForward(x, y, z); + vForward.Normalize(); + + { + Quaternion rotation1(Quaternion::IDENTITY); // test no rotation branch + Vector3 scale1(2.0f, 3.0f, 4.0f); + Vector3 position1(1.0f, 2.0f, 3.0f); + + Matrix m1(false); + m1.SetTransformComponents(scale1, rotation1, position1); + + Matrix m2(false); + m2.SetInverseTransformComponents(scale1, rotation1, position1); + + Matrix result; + Matrix::Multiply(result, m1, m2); + + DALI_TEST_EQUALS(result, Matrix::IDENTITY, 0.001, TEST_LOCATION); + } + } + } + } + END_TEST; +} + +int UtcDaliMatrixSetInverseTransformComponent02P(void) +{ + // Create an arbitrary vector + for( float x=-1.0f; x<=1.0f; x+=0.1f ) + { + for( float y=-1.0f; y<1.0f; y+=0.1f ) + { + for( float z=-1.0f; z<1.0f; z+=0.1f ) + { + Vector3 vForward(x, y, z); + vForward.Normalize(); + + for( float angle = 5.0f; angle <= 360.0f; angle += 15.0f) + { + Quaternion rotation1(Radian(Degree(angle)), vForward); + Matrix rotationMatrix(rotation1); // TEST RELIES ON THIS METHOD WORKING!!! + + Vector3 position1(5.0f, -6.0f, 7.0f); + + Matrix m1(false); + m1.SetTransformComponents( Vector3::ONE, rotation1, position1 ); + + Matrix m2(false); + m2.SetInverseTransformComponents( rotationMatrix.GetXAxis(), + rotationMatrix.GetYAxis(), + rotationMatrix.GetZAxis(), + position1 ); + + Matrix result; + Matrix::Multiply(result, m1, m2); + + DALI_TEST_EQUALS(result, Matrix::IDENTITY, 0.001, TEST_LOCATION); + } + } + } + } + END_TEST; +} + +int UtcDaliMatrixGetTransformComponents01P(void) +{ + Matrix m2(Matrix::IDENTITY.AsFloat()); + Vector3 pos2; + Vector3 scale2; + Quaternion q2; + m2.GetTransformComponents(pos2, q2, scale2); + DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 0.0f), pos2, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(Vector3(1.0f, 1.0f, 1.0f), scale2, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(Quaternion(), q2, 0.001, TEST_LOCATION); + END_TEST; +} + + +int UtcDaliMatrixGetTransformComponents02P(void) +{ + // Create an arbitrary vector + for( float x=-1.0f; x<=1.0f; x+=0.1f ) + { + for( float y=-1.0f; y<1.0f; y+=0.1f ) + { + for( float z=-1.0f; z<1.0f; z+=0.1f ) + { + Vector3 vForward(x, y, z); + vForward.Normalize(); + + for( float angle = 5.0f; angle <= 360.0f; angle += 15.0f) + { + Quaternion rotation1(Radian(Degree(angle)), vForward); + Vector3 scale1(2.0f, 3.0f, 4.0f); + Vector3 position1(1.0f, 2.0f, 3.0f); + + Matrix m1(false); + m1.SetTransformComponents(scale1, rotation1, position1); + + Vector3 position2; + Quaternion rotation2; + Vector3 scale2; + m1.GetTransformComponents(position2, rotation2, scale2); + + DALI_TEST_EQUALS(position1, position2, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(scale1, scale2, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(rotation1, rotation2, 0.001, TEST_LOCATION); + } + } + } + } + END_TEST; +} + +int UtcDaliMatrixGetTransformComponents03P(void) +{ + Matrix m2; // zero branch + Vector3 pos2; + Vector3 scale2; + Quaternion q2; + m2.GetTransformComponents(pos2, q2, scale2); + DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 0.0f), pos2, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 0.0f), scale2, 0.001, TEST_LOCATION); + // DALI_TEST_EQUALS(Quaternion(), q2, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrixOStreamOperator(void) +{ + std::ostringstream oss; + + Matrix matrix; + matrix.SetIdentity(); + + oss << matrix; + + std::string expectedOutput = "[ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ]"; + + DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Matrix3.cpp b/automated-tests/src/dali/utc-Dali-Matrix3.cpp new file mode 100644 index 0000000..c96859d --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Matrix3.cpp @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + + +using namespace Dali; + +void utc_dali_matrix3_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_matrix3_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +Matrix3 m1( + -18.6f, 1.88e-09f, -6.85e-09f, + 0.0f,13.2f, 13.2f, + -1.36e-08f,13.2f, -13.2f); + +Matrix3 m2( + -18.6f,6.91e-06f, 6.76e-06f, + 8.04e-09f,13.2f, 13.2f, + 3.01e-06f,13.2f, -13.2f); + +Matrix3 m3( + 6.24f,-12.4f, -12.4f, + -17.6f,-4.46f, -4.37f, + -0.0641f,13.2f, -13.2f); + +Matrix3 m4( + -16.3f,6.42f, 6.38f, + 9.05f,11.6f, 11.4f, + -0.0371f,13.1f, -13.3f); + +Matrix3 m5( + -2.43f,13.2f, 12.9f, + 18.5f,1.92f, 1.51f, + -0.257f,13.0f, -13.4f); + +Matrix3 m6( + -2.43f, -13.2f, -200.9f, + 18.5f, 1.92f, 1.51f, + 0.257f, 13.0f, 13.4f); + + +Matrix3 i1( + -0.05, -0.00, 0.00, + -0.00, 0.04, 0.04, + 0.00, 0.04, -0.04); + +Matrix3 i2( + -0.05, 0.00, -0.00, + 0.00, 0.04, 0.04, + 0.00, 0.04, -0.04); + +Matrix3 i3( + 0.02, -0.05, -0.00, + -0.04, -0.01, 0.04, + -0.04, -0.01, -0.04); + +Matrix3 i4( + -0.05, 0.03, -0.00, + 0.02, 0.03, 0.04, + 0.02, 0.03, -0.04); + +Matrix3 i5( + -0.01, 0.05, -0.00, + 0.04, 0.01, 0.04, + 0.04, 0.00, -0.04); + + + +Matrix3 t1( + -18.6f, 0.0f, -1.36e-08f, + 1.88e-09f,13.2f, 13.2f, + -6.85e-09f,13.2f, -13.2f); + +Matrix3 t2( + -18.6f,8.04e-09f, 3.01e-06f, + 6.91e-06f,13.2f, 13.2f, + 6.76e-06f,13.2f, -13.2f); + +Matrix3 t3( + 6.24f,-17.6f, -0.0641f, + -12.4f,-4.46f, 13.2f, + -12.4f, -4.37f, -13.2f); + +Matrix3 t4( + -16.3f,9.05f, -0.0371f, + 6.42f, 11.6f, 13.1f, + 6.38f,11.4f, -13.3f); + +Matrix3 t5( + -2.43f,18.5f, -0.257f, + 13.2f, 1.92f, 13.0f, + 12.9f, 1.51f, -13.4f); + + + +Matrix3* matrices[5] = { &m1, &m2, &m3, &m4, &m5 }; +Matrix3* inverseMatrices[5] = { &i1, &i2, &i3, &i4, &i5 }; +Matrix3* transposeMatrices[5] = { &t1, &t2, &t3, &t4, &t5 }; + +} // anonymous namespace + +int UtcDaliMatrix3FromMatrix(void) +{ + float els0[] = { 0.0f, 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f, 7.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f}; + Matrix m0(els0); + Matrix3 m1(0.0f, 1.0f, 2.0f, + 4.0f, 5.0f, 6.0f, + 8.0f, 9.0f, 10.0f); + + Matrix3 m2(m0); + + DALI_TEST_EQUALS(m1, m2, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrix3OperatorAssign01(void) +{ + float els0[] = { 0.0f, 1.0f, 2.0f, 3.0f, + 4.0f, 5.0f, 6.0f, 7.0f, + 8.0f, 9.0f, 10.0f, 11.0f, + 12.0f, 13.0f, 14.0f, 15.0f}; + Matrix m0(els0); + + Matrix3 m1(0.0f, 1.0f, 2.0f, + 4.0f, 5.0f, 6.0f, + 8.0f, 9.0f, 10.0f); + + Matrix3 m2; + m2 = m0; + m2 = m2; // Test branch + + DALI_TEST_EQUALS(m1, m2, 0.001, TEST_LOCATION); + END_TEST; +} + + +int UtcDaliMatrix3OperatorAssign02(void) +{ + Matrix3 m0(0.0f, 1.0f, 2.0f, + 4.0f, 5.0f, 6.0f, + 8.0f, 9.0f, 10.0f); + + Matrix3 m1(0.0f, 1.0f, 2.0f, + 4.0f, 5.0f, 6.0f, + 8.0f, 9.0f, 10.0f); + + Matrix3 m2; + m2 = m0; + + DALI_TEST_EQUALS(m1, m2, 0.001, TEST_LOCATION); + END_TEST; +} + + + +// AsFloat +int UtcDaliMatrix3AsFloat(void) +{ + float values[] = {0.0f, 1.0f, 2.0f, + 4.0f, 5.0f, 6.0f, + 8.0f, 9.0f, 10.0f }; + + Matrix3 m1(values[0], values[1], values[2], values[3],values[4], values[5], values[6], values[7],values[8]); + + for (int i=0;i<9;++i) + { + DALI_TEST_EQUALS(m1.AsFloat()[i], values[i], TEST_LOCATION); + } + END_TEST; +} + + +// Invert works +int UtcDaliMatrix3Invert(void) +{ + // We're going to invert a whole load of different matrices to make sure we don't + // fail on particular orientations. + for (int i=0;i<5;++i) + { + Matrix3 m = *matrices[i]; + Matrix3 inverseResult1 = *inverseMatrices[i]; + + // Convert to Mat4, perform inverse, and convert back to Mat3 + float* mf = m.AsFloat(); + float els[] = { mf[0], mf[1], mf[2], 0.0f, + mf[3], mf[4], mf[5], 0.0f, + mf[6], mf[7], mf[8], 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; + Matrix mat4(els); + mat4.Invert(); + Matrix3 inverseResult2 = mat4; + + Matrix3 mInv = m; + mInv.Invert(); + + DALI_TEST_EQUALS(mInv, inverseResult1, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(mInv, inverseResult2, 0.01f, TEST_LOCATION); + + Matrix3 m2 = mInv; + m2.Invert(); // double invert - should be back to m + + DALI_TEST_EQUALS(m, m2, 0.01f, TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliMatrix3Transpose(void) +{ + for (int i=0;i<5;++i) + { + Matrix3 m0 = *matrices[i]; + Matrix3 trans = *transposeMatrices[i]; + + Matrix3 m1 = m0; + m1.Transpose(); + + DALI_TEST_EQUALS(m1, trans, 0.001f, TEST_LOCATION); + + Matrix3 m2 = m1; + m2.Transpose(); + + DALI_TEST_EQUALS(m0, m2, 0.001f, TEST_LOCATION); + } + END_TEST; +} + +// SetIdentity +int UtcDaliMatrix3SetIdentity(void) +{ + Matrix3 m( 0.0f, 1.0f, 2.0f, + 4.0f, 5.0f, 6.0f, + 8.0f, 9.0f, 10.0f); + m.SetIdentity(); + + DALI_TEST_EQUALS(m, Matrix3::IDENTITY, 0.001f, TEST_LOCATION); + END_TEST; +} + + +int UtcDaliMatrix3Scale(void) +{ + Matrix3 m1( 0.0f, 1.0f, 2.0f, + 4.0f, 5.0f, 6.0f, + 8.0f, 9.0f, 10.0f); + + Matrix3 m2( 0.0f, 3.0f, 6.0f, + 12.0f, 15.0f, 18.0f, + 24.0f, 27.0f, 30.0f); + + m1.Scale(3.0f); + + DALI_TEST_EQUALS(m1, m2, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrix3Magnitude(void) +{ + Matrix3 m1( 0.0f, 1.0f, -2.0f, + 3.0f, -4.0f, 5.0f, + -6.0f, 7.0f, 8.0f); + + DALI_TEST_EQUALS(Matrix3::IDENTITY.Magnitude(), 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(m1.Magnitude(), 12.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + + + +int UtcDaliMatrix3ScaleInverseTranspose(void) +{ + Matrix3* matrices[6] = { &m1, &m2, &m3, &m4, &m5, &m6 }; + + + for (int i=0;i<6;++i) + { + Matrix3 m0 = *matrices[i]; + + Matrix3 m1 = m0; + m1.Invert(); + m1.Transpose(); + m1.Scale(3.0f/(m1.Magnitude())); + + Matrix3 m2 = m0; + m2.ScaledInverseTranspose(); + + DALI_TEST_EQUALS(m1, m2, 0.001f, TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliMatrix3OStreamOperator(void) +{ + std::ostringstream oss; + + Matrix3 matrix( 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f ); + + oss << matrix; + + std::string expectedOutput = "[ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]"; + + DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrix3Multiply(void) +{ + Matrix3 m1( 0.0f, 3.0f, 6.0f, + 12.0f, 15.0f, 18.0f, + 24.0f, 27.0f, 30.0f); + + Matrix3 m2( 0.0f, 1.0f, 0.0f, + -1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f); + + Matrix3 m3( -3.0f, 0.0f, 6.0f, + -15.0f, 12.0f, 18.0f, + -27.0f, 24.0f, 30.0f); + + Matrix3 result; + Matrix3::Multiply(result, m1, m2); + + DALI_TEST_EQUALS(m3, result, 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliMatrix3EqualityOperator(void) +{ + Matrix3 m1( 0.0f, 3.0f, 6.0f, + 12.0f, 15.0f, 18.0f, + 24.0f, 27.0f, 30.0f); + + Matrix3 m2( 0.0f, 3.0f, 6.0f, + 12.0f, 15.0f, 18.0f, + 24.0f, 27.0f, 30.0f); + + DALI_TEST_CHECK(m1 == m2); + END_TEST; +} + +int UtcDaliMatrix3InequalityOperator(void) +{ + Matrix3 m1( 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f); + + Matrix3 m2( 0.0f, 3.0f, 6.0f, + 12.0f, 15.0f, 18.0f, + 24.0f, 27.0f, 30.0f); + + DALI_TEST_CHECK(m1 != m2); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-MeshMaterial.cpp b/automated-tests/src/dali/utc-Dali-MeshMaterial.cpp new file mode 100644 index 0000000..67eeb02 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-MeshMaterial.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +#include + +void mesh_material_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void mesh_material_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +namespace +{ + +Material ConstructMaterial( const std::string& vertexShader, + const std::string& fragmentShader, + float opacity ) +{ + Shader shader = Shader::New( vertexShader, fragmentShader ); + Material customMaterial = Material::New(shader); + Vector4 color = Color::WHITE; + color.a = opacity; + customMaterial.SetProperty(Material::Property::COLOR, color); + return customMaterial; +} + +void TestBlending( TestApplication& application, Material material, float actorOpacity, BlendingMode::Type blendingMode, bool expectedBlend ) +{ + // Generate geometry & renderers + //Mesh mesh = Mesh::New(meshData); + + application.SendNotification(); + application.Render(0); + application.Render(); + application.SendNotification(); + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + //material.SetBlendMode(blendingMode); + actor.SetOpacity(actorOpacity); + + TraceCallStack& cullFaceTrace = application.GetGlAbstraction().GetCullFaceTrace(); + cullFaceTrace.Enable(true); + application.SendNotification(); + application.Render(); + //DALI_TEST_EQUALS( BlendEnabled( cullFaceTrace ), expectedBlend, TEST_LOCATION ); +} + +} // anonymous namespace + + +/** + * Test cases + * + * Check construction of mesh objects + * Check downcast of mesh objects (+ve & -ve) + * Check staging of mesh objects + * + * Check staging of some mesh objects but not all + * Create geometry with no verts - ensure it asserts + * Create an element based geometry with no indices - ensure it asserts + * Create a renderer without a material - ensure nothing renders + * Create a render with a material, ensure the material can be changed + * Create a render with a material&Sampler, ensure the sampler can be changed + * Create a render with a material, sampler, ensure the sampler's texture can be changed + * Create a render with a material, sampler, ensure that removing the sampler works + * + * Blend tests: + * 1 Set Material with translucent color, actor color opaque, Set Use image alpha to true + * Expect blending + * 2 Set material to translucent, set use image alpha to false, set actor opacity to 1.0f + * Expect no blending + * 3 Set material to opaque, set use image alpha to true, set actor opacity to 1.0f + * Expect no blending + * 4 Set material to have image with alpha, set use image alpha to true, set actor opacity to 1.0f + * Expect blending + * 5 Set material to have image with alpha, set use image alpha to false, set actor opacity to 1.0f + * Expect no blending + * 6 Set material to have image without alpha, set use image alpha to true, set actor opacity to 1.0f + * Expect no blending + * 7 Set material to have framebuffer with alpha, set use image alpha to true, set actor opacity to 1.0f + * Expect blending + * 8 Set material to have image with alpha, set use image alpha to false, set actor opacity to 0.5f + * Expect blending + * 9 Set material to have image with no alpha, set material opacity to 0.5, set use image alpha to true, set actor opacity to 1.0f + * Expect blending + * + * Check defaults of renderer + * + * Bounding box of geometry? + * + * Check rendered vertex buffer is the right size for the initial property buffer + * + * Check PropertyBuffer set via SetData can be read thru property system + * Check PropertyBuffer property setters / getters + * Check vertex PropertyBuffer set via properties renders as expected + * Check Index propertyBuffer set via properties renders as expected + * + * Check geometry type renders correctly as the matching GL draw call and type + * + * Check attributes change when rendering different actors with different + * vertex formats (utc-Dali-Context.cpp) + * + * utc-Dali-Material.cpp + * Check material color affects output - see shader uniform + * + * Check material sampler's image load/release policies affect rendering correctly. + */ diff --git a/automated-tests/src/dali/utc-Dali-NativeImage.cpp b/automated-tests/src/dali/utc-Dali-NativeImage.cpp new file mode 100644 index 0000000..1f080a7 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-NativeImage.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; + +void utc_dali_native_image_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_native_image_cleanup(void) +{ + test_return_value = TET_PASS; +} + +IntrusivePtr Creator() +{ + return TestNativeImage::New(10,10); +} + +int UtcDaliIntrusivePtrTestNativeImage(void) +{ + UtcCoverageIntrusivePtr pointer; + + pointer.Check(Creator); + + END_TEST; +} + +int UtcDaliNativeImageNew(void) +{ + TestApplication application; + + tet_infoline("UtcDaliNativeImageNew - NativeImage::New(NativeImageInterface&)"); + + // invoke default handle constructor + NativeImage image; + TestNativeImagePointer nativeImage = TestNativeImage::New(16, 16); + + DALI_TEST_CHECK( !image ); + + // initialise handle + image = NativeImage::New(*(nativeImage.Get())); + + DALI_TEST_CHECK( image ); + END_TEST; +} + +int UtcDaliNativeImageCopyConstructor(void) +{ + TestApplication application; + + tet_infoline("UtcDaliNativeImageCopyConstructor - NativeImage::NativeImage( const NativeImage& )"); + + NativeImage image1; + DALI_TEST_CHECK( !image1 ); + + TestNativeImagePointer nativeImage = TestNativeImage::New(16, 16); + image1 = NativeImage::New(*(nativeImage.Get())); + NativeImage image2( image1 ); + + DALI_TEST_CHECK( image2 ); + DALI_TEST_EQUALS( image1, image2, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliNativeImageDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Image::DownCast()"); + + TestNativeImagePointer nativeImage = TestNativeImage::New(16, 16); + NativeImage image = NativeImage::New(*(nativeImage.Get())); + + BaseHandle object(image); + + NativeImage image2 = NativeImage::DownCast(object); + DALI_TEST_CHECK(image2); + + NativeImage image3 = DownCast< NativeImage >(object); + DALI_TEST_CHECK(image3); + + BaseHandle unInitializedObject; + NativeImage image4 = NativeImage::DownCast(unInitializedObject); + DALI_TEST_CHECK(!image4); + + NativeImage image5 = DownCast< NativeImage >(unInitializedObject); + DALI_TEST_CHECK(!image5); + + Image image6 = NativeImage::New(*(nativeImage.Get())); + NativeImage image7 = NativeImage::DownCast(image6); + DALI_TEST_CHECK(image7); + END_TEST; +} + +int UtcDaliNativeImageCreateGlTextureN(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::NativeImage::GenerateGlTexture()" ); + + NativeImage image; + try + { + image.CreateGlTexture(); + tet_printf( "Assertion test failed - no Exception\n" ); + tet_result( TET_FAIL ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "image &&", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliNativeImageCreateGlTextureP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::NativeImage::GenerateGlTexture()" ); + + TestNativeImagePointer imageInterface = TestNativeImage::New( 16, 16 ); + NativeImage image = NativeImage::New( *(imageInterface.Get()) ); + DALI_TEST_CHECK( image ); + + image.CreateGlTexture(); + + application.SendNotification(); + application.Render(16); + + DALI_TEST_EQUALS( imageInterface->mExtensionCreateCalls, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( imageInterface->mTargetTextureCalls, 1, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliNativeImageContextLoss(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::NativeImage behaviour through a context lost/regained cycle." ); + + // Build an image that is expected to have a GL texture created for it and + // recreated in a GL context recovery: + TestNativeImagePointer eagerImageInterface = TestNativeImage::New( 16, 16 ); + NativeImage eagerImage = NativeImage::New( *(eagerImageInterface.Get()) ); + DALI_TEST_CHECK( eagerImage ); + + // Build a regular lazy-allocated image for comparison: + TestNativeImagePointer lazyImageInterface = TestNativeImage::New( 16, 16 ); + NativeImage lazyImage = NativeImage::New( *(lazyImageInterface.Get()) ); + DALI_TEST_CHECK( lazyImage ); + + eagerImage.CreateGlTexture(); + + application.SendNotification(); + application.Render(16); + + // Cycle through a context loss and regain, asserting that the texture is + // not reallocated if it already existed before the cycle and is never allocated + // throughout the cycle if of the regular lazy kind: + + // Call render thread context destroyed / created functions: + application.ResetContext(); + + // Call event thread function: + application.GetCore().RecoverFromContextLoss(); + + // Run update/render loop + application.SendNotification(); + application.Render(16); + + DALI_TEST_EQUALS( eagerImageInterface->mExtensionCreateCalls, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( eagerImageInterface->mTargetTextureCalls, 1, TEST_LOCATION ); + + DALI_TEST_EQUALS( lazyImageInterface->mExtensionCreateCalls, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( lazyImageInterface->mTargetTextureCalls, 0, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliNativeImageExtensionP(void) +{ + TestApplication application; + tet_infoline( "Testing Dali::NativeImage::GenerateGlTexture()" ); + + TestNativeImagePointer testNativeImage = TestNativeImage::New( 16, 16 ); + DALI_TEST_CHECK( testNativeImage ); + + DALI_TEST_CHECK( NULL == testNativeImage->GetExtension() ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-NinePatchImages.cpp b/automated-tests/src/dali/utc-Dali-NinePatchImages.cpp new file mode 100644 index 0000000..eea7054 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-NinePatchImages.cpp @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +namespace { + +Integration::Bitmap* CreateBitmap( unsigned int imageHeight, unsigned int imageWidth, unsigned int initialColor, Pixel::Format pixelFormat ) +{ + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, imageWidth,imageHeight,imageWidth,imageHeight ); + unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat ); + + memset( pixbuffer, initialColor , imageHeight*imageWidth*bytesPerPixel); + + return bitmap; +} + +void InitialiseRegionsToZeroAlpha( Integration::Bitmap* image, unsigned int imageWidth, unsigned int imageHeight, Pixel::Format pixelFormat ) +{ + PixelBuffer* pixbuffer = image->GetBuffer(); + unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat ); + + for ( unsigned int row = 0; row < imageWidth; ++row ) + { + unsigned int pixelOffset = (row*bytesPerPixel); + pixbuffer[pixelOffset+3] = 0x00; + pixelOffset += ( imageHeight-1 ) * imageWidth * bytesPerPixel; + pixbuffer[pixelOffset+3] = 0x00; + } + + for ( unsigned int column = 0; column < imageHeight; ++column ) + { + unsigned int pixelOffset = (column*imageWidth*bytesPerPixel); + pixbuffer[pixelOffset+3] = 0x00; + pixelOffset += (imageWidth-1)*bytesPerPixel; + pixbuffer[pixelOffset+3] = 0x00; + } +} + +void AddStretchRegionsToImage( Integration::Bitmap* image, unsigned int imageWidth, unsigned int imageHeight, const Vector4& requiredStretchBorder , Pixel::Format pixelFormat ) +{ + PixelBuffer* pixbuffer = image->GetBuffer(); + unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat ); + + for ( unsigned int column = requiredStretchBorder.x; column < imageWidth - requiredStretchBorder.z; ++column ) + { + unsigned int pixelOffset = (column*bytesPerPixel); + pixbuffer[pixelOffset] = 0x00; + pixbuffer[pixelOffset+1] = 0x00; + pixbuffer[pixelOffset+2] = 0x00; + pixbuffer[pixelOffset+3] = 0xFF; + } + + for ( unsigned int row = requiredStretchBorder.y; row < imageHeight - requiredStretchBorder.w; ++row ) + { + unsigned int pixelOffset = (row*imageWidth*bytesPerPixel); + pixbuffer[pixelOffset] = 0x00; + pixbuffer[pixelOffset+1] = 0x00; + pixbuffer[pixelOffset+2] = 0x00; + pixbuffer[pixelOffset+3] = 0xFF; + } +} + +void AddChildRegionsToImage( Integration::Bitmap* image, unsigned int imageWidth, unsigned int imageHeight, const Vector4& requiredChildRegion, Pixel::Format pixelFormat ) +{ + PixelBuffer* pixbuffer = image->GetBuffer(); + unsigned int bytesPerPixel = GetBytesPerPixel( pixelFormat ); + + Integration::Bitmap::PackedPixelsProfile* srcProfile = image->GetPackedPixelsProfile(); + unsigned int bufferStride = srcProfile->GetBufferStride(); + + // Add bottom child region + for ( unsigned int column = requiredChildRegion.x; column < imageWidth - requiredChildRegion.z; ++column ) + { + unsigned int pixelOffset = (column*bytesPerPixel); + pixelOffset += ( imageHeight-1 ) * bufferStride; + pixbuffer[pixelOffset] = 0x00; + pixbuffer[pixelOffset+1] = 0x00; + pixbuffer[pixelOffset+2] = 0x00; + pixbuffer[pixelOffset+3] = 0xFF; + } + + // Add right child region + for ( unsigned int row = requiredChildRegion.y; row < imageHeight - requiredChildRegion.w; ++row ) + { + unsigned int pixelOffset = row*bufferStride + (imageWidth-1)*bytesPerPixel; + pixbuffer[pixelOffset] = 0x00; + pixbuffer[pixelOffset+1] = 0x00; + pixbuffer[pixelOffset+2] = 0x00; + pixbuffer[pixelOffset+3] = 0xFF; + } +} + +NinePatchImage CustomizeNinePatch( TestApplication& application, + unsigned int ninePatchImageWidth, + unsigned int ninePatchImageHeight, + const Vector4& requiredStretchBorder, + bool addChildRegion = false, + Vector4 requiredChildRegion = Vector4::ZERO ) +{ + TestPlatformAbstraction& platform = application.GetPlatform(); + + Pixel::Format pixelFormat = Pixel::RGBA8888; + + tet_infoline("Create Bitmap"); + platform.SetClosestImageSize(Vector2( ninePatchImageWidth, ninePatchImageHeight)); + Integration::Bitmap* bitmap = CreateBitmap( ninePatchImageWidth, ninePatchImageHeight, 0xFF, pixelFormat ); + + tet_infoline("Clear border regions"); + InitialiseRegionsToZeroAlpha( bitmap, ninePatchImageWidth, ninePatchImageHeight, pixelFormat ); + + tet_infoline("Add Stretch regions to Bitmap"); + AddStretchRegionsToImage( bitmap, ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder, pixelFormat ); + + if( addChildRegion ) + { + tet_infoline("Add Child regions to Bitmap"); + AddChildRegionsToImage( bitmap, ninePatchImageWidth, ninePatchImageHeight, requiredChildRegion, pixelFormat ); + } + + tet_infoline("Getting resource"); + Integration::ResourcePointer resourcePtr(bitmap); + platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr ); + + Image image = ResourceImage::New( "blah.#.png" ); + + tet_infoline("Assign image to ImageActor"); + ImageActor imageActor = ImageActor::New( image ); + Stage::GetCurrent().Add( imageActor ); + + tet_infoline("Downcast Image to a nine-patch image\n"); + NinePatchImage ninePatchImage = NinePatchImage::DownCast( image ); + + return ninePatchImage; + +} + +} // namespace + +int UtcDaliNinePatchImageNew(void) +{ + TestApplication application; + tet_infoline("UtcDaliNinePatchImageNew - NinePatchImage::New(const std::string&)"); + + // invoke default handle constructor + NinePatchImage image; + + DALI_TEST_CHECK( !image ); + + // initialise handle + image = NinePatchImage::New("blah.#.png"); + + DALI_TEST_CHECK( image ); + END_TEST; +} + +int UtcDaliNinePatchImageDowncast(void) +{ + TestApplication application; + tet_infoline("UtcDaliNinePatchImageDowncast - NinePatchImage::DownCast(BaseHandle)"); + + NinePatchImage image = NinePatchImage::New("blah.#.png"); + + BaseHandle object(image); + + NinePatchImage image2 = NinePatchImage::DownCast(object); + DALI_TEST_CHECK(image2); + + NinePatchImage image3 = DownCast< NinePatchImage >(object); + DALI_TEST_CHECK(image3); + + BaseHandle unInitializedObject; + NinePatchImage image4 = NinePatchImage::DownCast(unInitializedObject); + DALI_TEST_CHECK(!image4); + + NinePatchImage image5 = DownCast< NinePatchImage >(unInitializedObject); + DALI_TEST_CHECK(!image5); + + Image image6 = NinePatchImage::New("blah.#.png"); + NinePatchImage image7 = NinePatchImage::DownCast(image6); + DALI_TEST_CHECK(image7); + END_TEST; +} + +int UtcDaliNinePatchImageCopyConstructor(void) +{ + TestApplication application; + + tet_infoline("UtcDaliNinePatchImageCopyConstructor - NinePatchImage::NinePatchImage( const NinePatchImage& )"); + + NinePatchImage image1; + DALI_TEST_CHECK( !image1 ); + + image1 = NinePatchImage::New("blah.#.png"); + NinePatchImage image2( image1 ); + + DALI_TEST_CHECK( image2 ); + DALI_TEST_EQUALS( image1, image2, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliNinePatchImageGetStrechBorders(void) +{ + TestApplication application; + tet_infoline("UtcDaliNinePatchImageGetStrechBorders - NinePatchImage::GetStretchBorders()"); + + /* Stretch region left(2) top(2) right (2) bottom (2) + * ss + * OOOOOO + * OOOOOOc + * sOOooOOc + * sOOooOOc + * OOOOOOc + * OOOOOO + * cccc + */ + + const unsigned int ninePatchImageHeight = 8; + const unsigned int ninePatchImageWidth = 8; + const Vector4 requiredStretchBorder( 3, 3, 3, 3); + + NinePatchImage ninePatchImage = CustomizeNinePatch( application,ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder ); + DALI_TEST_CHECK( ninePatchImage ); + + if ( ninePatchImage ) + { + tet_infoline("Get Stretch regions from NinePatch"); + Vector4 stretchBorders = ninePatchImage.GetStretchBorders(); + tet_printf("stretchBorders left(%f) right(%f) top(%f) bottom(%f)\n", stretchBorders.x, stretchBorders.z, stretchBorders.y, stretchBorders.w ); + DALI_TEST_CHECK( stretchBorders == requiredStretchBorder ); + } + else + { + tet_infoline("Image not NinePatch"); + test_return_value = TET_FAIL; + } + + END_TEST; +} + +int UtcDaliNinePatchImageGetChildRectangle(void) +{ + TestApplication application; + tet_infoline("UtcDaliNinePatchImageGetChildRectangle - NinePatchImage::GetChildRectangle()"); + + /* Child region x(2) y(2) width (4) height (4) + * + * ss + * OOOOOO + * OOOOOOc + * sOOooOOc + * sOOooOOc + * OOOOOOc + * OOOOOO + * cccc + */ + + const unsigned int ninePatchImageHeight = 8; + const unsigned int ninePatchImageWidth = 8; + const Vector4 requiredChildRegion( 2, 2, 2, 2 ); + const Vector4 requiredStretchBorder( 3, 3, 3, 3); + + NinePatchImage ninePatchImage = CustomizeNinePatch( application,ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder, true, requiredChildRegion ); + DALI_TEST_CHECK( ninePatchImage ); + + if ( ninePatchImage ) + { + tet_infoline("Get Child regions from NinePatch"); + Rect childRectangle = ninePatchImage.GetChildRectangle(); + tet_printf("childRectange x(%d) y(%d) width(%d) height(%d)\n", childRectangle.x, childRectangle.y, childRectangle.width, childRectangle.height ); + Rect childRegion(requiredChildRegion.x, requiredChildRegion.y, ninePatchImageWidth - requiredChildRegion.x - requiredChildRegion.z, ninePatchImageHeight - requiredChildRegion.y - requiredChildRegion.w ); + DALI_TEST_CHECK( childRegion == childRectangle ); + } + else + { + tet_infoline("Image not NinePatch"); + test_return_value = TET_FAIL; + } + + END_TEST; +} + +int UtcDaliNinePatchImageCreateCroppedBufferImage(void) +{ + TestApplication application; + tet_infoline("UtcDaliNinePatchImageCreateCroppedBufferImage - NinePatchImage::CreateCroppedBufferImage()"); + + const unsigned int ninePatchImageHeight = 8; + const unsigned int ninePatchImageWidth = 8; + const Vector4 requiredStretchBorder( 1,1,1,1); + + NinePatchImage ninePatchImage = CustomizeNinePatch( application,ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder ); + DALI_TEST_CHECK( ninePatchImage ); + + if ( ninePatchImage ) + { + BufferImage newImage = ninePatchImage.CreateCroppedBufferImage(); + DALI_TEST_CHECK( newImage ); + + DALI_TEST_EQUALS( newImage.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION ); + + DALI_TEST_EQUALS( newImage.GetBufferSize(), 144u/* 36*4 */, TEST_LOCATION ); + } + else + { + tet_infoline("Image not NinePatch"); + test_return_value = TET_FAIL; + } + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-ObjectRegistry.cpp b/automated-tests/src/dali/utc-Dali-ObjectRegistry.cpp new file mode 100644 index 0000000..d49b266 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-ObjectRegistry.cpp @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +namespace +{ + +// Functors to test whether Object created/destroyed signal is emitted for different types of Objects + +struct TestObjectDestroyedCallback +{ + TestObjectDestroyedCallback(bool& signalReceived, Dali::RefObject*& objectPointer) + : mSignalVerified(signalReceived), + mObjectPointer(objectPointer) + { + } + + void operator()(const Dali::RefObject* objectPointer) + { + tet_infoline("Verifying TestObjectDestroyedCallback()"); + + if(objectPointer == mObjectPointer) + { + mSignalVerified = true; + } + } + + bool& mSignalVerified; + Dali::RefObject*& mObjectPointer; +}; + +struct TestActorCallback +{ + TestActorCallback(bool& signalReceived) + : mSignalVerified(signalReceived) + { + } + + void operator()(BaseHandle object) + { + tet_infoline("Verifying TestActorCallback()"); + Actor actor = Actor::DownCast(object); + if(actor) + { + mSignalVerified = true; + } + } + + bool& mSignalVerified; +}; + +struct TestCameraActorCallback +{ + TestCameraActorCallback(bool& signalReceived) + : mSignalVerified(signalReceived) + { + } + void operator()(BaseHandle object) + { + tet_infoline("Verifying TestCameraActorCallback()"); + CameraActor actor = CameraActor::DownCast(object); + if(actor) + { + mSignalVerified = true; + } + } + bool& mSignalVerified; +}; + +struct TestImageActorCallback +{ + TestImageActorCallback(bool& signalReceived) + : mSignalVerified(signalReceived) + { + } + void operator()(BaseHandle object) + { + tet_infoline("Verifying TestImageActorCallback()"); + ImageActor actor = ImageActor::DownCast(object); + if(actor) + { + mSignalVerified = true; + } + } + bool& mSignalVerified; +}; + +struct TestLayerCallback +{ + TestLayerCallback(bool& signalReceived) + : mSignalVerified(signalReceived) + { + } + void operator()(BaseHandle object) + { + tet_infoline("Verifying TestLayerCallback()"); + Layer actor = Layer::DownCast(object); + if(actor) + { + mSignalVerified = true; + } + } + bool& mSignalVerified; +}; + +struct TestAnimationCallback +{ + TestAnimationCallback(bool& signalReceived) + : mSignalVerified(signalReceived) + { + } + void operator()(BaseHandle object) + { + tet_infoline("Verifying TestAnimationCallback()"); + Animation actor = Animation::DownCast(object); + if(actor) + { + mSignalVerified = true; + } + } + bool& mSignalVerified; +}; + +struct TestShaderEffectCallback +{ + TestShaderEffectCallback(bool& signalReceived) + : mSignalVerified(signalReceived) + { + } + void operator()(BaseHandle object) + { + tet_infoline("Verifying TestShaderEffectCallback()"); + ShaderEffect actor = ShaderEffect::DownCast(object); + if(actor) + { + mSignalVerified = true; + } + } + bool& mSignalVerified; +}; + + +} // anonymous namespace + + + + +int UtcDaliObjectRegistryGet(void) +{ + TestApplication application; + + ObjectRegistry registry; // like this for ctor code coverage + registry= Stage::GetCurrent().GetObjectRegistry(); + + DALI_TEST_CHECK( registry ); + END_TEST; +} + +int UtcDaliObjectRegistryCopyConstructor(void) +{ + TestApplication application; + + ObjectRegistry myRegistry; + ObjectRegistry anotherRegistry( myRegistry ); + + DALI_TEST_EQUALS( myRegistry, anotherRegistry, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliObjectRegistrySignalActorCreated(void) +{ + tet_infoline("Testing GetObjectRegistry()"); + TestApplication application; + ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry(); + DALI_TEST_CHECK( registry ); + + bool verified = false; + TestActorCallback test(verified); + + Dali::RefObject* objectPointer = NULL; + TestObjectDestroyedCallback test2(verified, objectPointer); + + registry.ObjectCreatedSignal().Connect(&application, test); + registry.ObjectDestroyedSignal().Connect(&application, test2); + + { + Actor actor = Actor::New(); + DALI_TEST_CHECK( test.mSignalVerified ); + + verified = false; + objectPointer = actor.GetObjectPtr(); + } + DALI_TEST_CHECK( test.mSignalVerified ); + END_TEST; +} + +int UtcDaliObjectRegistrySignalCameraCreated(void) +{ + TestApplication application; + + ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry(); + + bool verified = false; + TestCameraActorCallback test(verified); + + Dali::RefObject* objectPointer = NULL; + TestObjectDestroyedCallback test2(verified, objectPointer); + + registry.ObjectCreatedSignal().Connect(&application, test); + registry.ObjectDestroyedSignal().Connect(&application, test2); + + { + CameraActor actor = CameraActor::New(); + DALI_TEST_CHECK( test.mSignalVerified ); + + verified = false; + objectPointer = actor.GetObjectPtr(); + } + DALI_TEST_CHECK( test.mSignalVerified ); + END_TEST; +} + +int UtcDaliObjectRegistrySignalImageActorCreated(void) +{ + TestApplication application; + ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry(); + + static const char* TestImageFilename = "icon_wrt.png"; + Image image = ResourceImage::New(TestImageFilename); + + bool verified = false; + TestImageActorCallback test(verified); + + Dali::RefObject* objectPointer = NULL; + TestObjectDestroyedCallback test2(verified, objectPointer); + + registry.ObjectCreatedSignal().Connect(&application, test); + registry.ObjectDestroyedSignal().Connect(&application, test2); + + { + ImageActor actor = ImageActor::New(image); + DALI_TEST_CHECK( test.mSignalVerified ); + + verified = false; + objectPointer = actor.GetObjectPtr(); + } + DALI_TEST_CHECK( test.mSignalVerified ); + END_TEST; +} + +int UtcDaliObjectRegistrySignalLayerCreated(void) +{ + TestApplication application; + ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry(); + + bool verified = false; + TestLayerCallback test(verified); + + Dali::RefObject* objectPointer = NULL; + TestObjectDestroyedCallback test2(verified, objectPointer); + + registry.ObjectCreatedSignal().Connect(&application, test); + registry.ObjectDestroyedSignal().Connect(&application, test2); + + { + Layer actor = Layer::New(); + DALI_TEST_CHECK( test.mSignalVerified ); + + verified = false; + objectPointer = actor.GetObjectPtr(); + } + DALI_TEST_CHECK( test.mSignalVerified ); + END_TEST; +} + +int UtcDaliObjectRegistrySignalAnimationCreated(void) +{ + TestApplication application; + ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry(); + + bool verified = false; + TestAnimationCallback test(verified); + + Dali::RefObject* objectPointer = NULL; + TestObjectDestroyedCallback test2(verified, objectPointer); + + registry.ObjectCreatedSignal().Connect(&application, test); + registry.ObjectDestroyedSignal().Connect(&application, test2); + + { + Animation animation = Animation::New(1.0f); + DALI_TEST_CHECK( test.mSignalVerified ); + + verified = false; + objectPointer = animation.GetObjectPtr(); + } + DALI_TEST_CHECK( test.mSignalVerified ); + END_TEST; +} + +int UtcDaliObjectRegistrySignalShaderEffectCreated(void) +{ + TestApplication application; + ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry(); + + static const char* VertexSource = + "void main()\n" + "{\n" + " gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\n" + " vTexCoord = aTexCoord;\n" + "}\n"; + + static const char* FragmentSource = + "void main()\n" + "{\n" + " gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n" + "}\n"; + + bool verified = false; + TestShaderEffectCallback test(verified); + + Dali::RefObject* objectPointer = NULL; + TestObjectDestroyedCallback test2(verified, objectPointer); + + registry.ObjectCreatedSignal().Connect(&application, test); + registry.ObjectDestroyedSignal().Connect(&application, test2); + + { + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( test.mSignalVerified ); + + verified = false; + objectPointer = effect.GetObjectPtr(); + } + DALI_TEST_CHECK( test.mSignalVerified ); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-PanGesture.cpp b/automated-tests/src/dali/utc-Dali-PanGesture.cpp new file mode 100644 index 0000000..b830f9d --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-PanGesture.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_pan_gesture_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_pan_gesture_cleanup(void) +{ + test_return_value = TET_PASS; +} + + + +int UtcDaliPanGestureConstructor(void) +{ + TestApplication application; // Reset all test adapter return codes + + PanGesture gesture; + DALI_TEST_EQUALS(Gesture::Clear, gesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, gesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pan, gesture.type, TEST_LOCATION); + + PanGesture gesture2(Gesture::Started); + DALI_TEST_EQUALS(Gesture::Started, gesture2.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, gesture2.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pan, gesture2.type, TEST_LOCATION); + + PanGesture gesture3(Gesture::Continuing); + DALI_TEST_EQUALS(Gesture::Continuing, gesture3.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, gesture3.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pan, gesture3.type, TEST_LOCATION); + + PanGesture gesture4(Gesture::Finished); + DALI_TEST_EQUALS(Gesture::Finished, gesture4.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, gesture4.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pan, gesture4.type, TEST_LOCATION); + + // Test copy constructor + gesture4.numberOfTouches = 3u; + + PanGesture pan(gesture4); + DALI_TEST_EQUALS(Gesture::Finished, pan.state, TEST_LOCATION); + DALI_TEST_EQUALS(3u, pan.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pan, pan.type, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureAssignment(void) +{ + // Test Assignment operator + PanGesture gesture(Gesture::Started); + DALI_TEST_EQUALS(Gesture::Started, gesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, gesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pan, gesture.type, TEST_LOCATION); + + PanGesture gesture2(Gesture::Continuing); + DALI_TEST_EQUALS(Gesture::Continuing, gesture2.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, gesture2.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pan, gesture2.type, TEST_LOCATION); + + gesture2.numberOfTouches = 3u; + + gesture = gesture2; + DALI_TEST_EQUALS(Gesture::Continuing, gesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(3u, gesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pan, gesture.type, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureGetSpeed(void) +{ + PanGesture gesture(Gesture::Started); + DALI_TEST_EQUALS(0.0f, gesture.GetSpeed(), TEST_LOCATION); + + gesture.velocity = Vector2(3.0f, -4.0f); + + DALI_TEST_EQUALS(5.0f, gesture.GetSpeed(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureGetDistance(void) +{ + PanGesture gesture(Gesture::Started); + DALI_TEST_EQUALS(0.0f, gesture.GetDistance(), TEST_LOCATION); + + gesture.displacement = Vector2(-30.0f, -40.0f); + + DALI_TEST_EQUALS(50.0f, gesture.GetDistance(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureGetScreenSpeed(void) +{ + PanGesture gesture(Gesture::Started); + DALI_TEST_EQUALS(0.0f, gesture.GetScreenSpeed(), TEST_LOCATION); + + gesture.screenVelocity = Vector2(3.0f, -4.0f); + + DALI_TEST_EQUALS(5.0f, gesture.GetScreenSpeed(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureGetScreenDistance(void) +{ + PanGesture gesture(Gesture::Started); + DALI_TEST_EQUALS(0.0f, gesture.GetScreenDistance(), TEST_LOCATION); + + gesture.screenDisplacement = Vector2(-30.0f, -40.0f); + + DALI_TEST_EQUALS(50.0f, gesture.GetScreenDistance(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureDynamicAllocation(void) +{ + PanGesture* gesture = new PanGesture( Gesture::Started ); + DALI_TEST_EQUALS(Gesture::Started, gesture->state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, gesture->numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pan, gesture->type, TEST_LOCATION); + delete gesture; + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp new file mode 100644 index 0000000..4943ce6 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp @@ -0,0 +1,2517 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; + +void utc_dali_pan_gesture_detector_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_pan_gesture_detector_cleanup(void) +{ + test_return_value = TET_PASS; +} + +/////////////////////////////////////////////////////////////////////////////// +namespace +{ +const int PAN_EVENT_TIME_DELTA = 8; +const int PAN_GESTURE_UPDATE_COUNT = 50; + +// Stores data that is populated in the callback and will be read by the test cases +struct SignalData +{ + SignalData() + : functorCalled(false), + voidFunctorCalled(false), + receivedGesture(Gesture::Clear) + {} + + void Reset() + { + functorCalled = false; + voidFunctorCalled = false; + + receivedGesture.state = Gesture::Clear; + receivedGesture.velocity = Vector2(0.0f, 0.0f); + receivedGesture.displacement = Vector2(0.0f, 0.0f); + receivedGesture.position = Vector2(0.0f, 0.0f); + receivedGesture.screenPosition = Vector2(0.0f, 0.0f); + receivedGesture.numberOfTouches = 0; + + pannedActor.Reset(); + } + + bool functorCalled; + bool voidFunctorCalled; + PanGesture receivedGesture; + Actor pannedActor; +}; + +// Functor that sets the data when called +struct GestureReceivedFunctor +{ + GestureReceivedFunctor(SignalData& data) : signalData(data) { } + + void operator()(Actor actor, const PanGesture& pan) + { + signalData.functorCalled = true; + signalData.receivedGesture = pan; + signalData.pannedActor = actor; + } + + void operator()() + { + signalData.voidFunctorCalled = true; + } + + SignalData& signalData; +}; + +// Functor that removes the gestured actor from stage +struct UnstageActorFunctor : public GestureReceivedFunctor +{ + UnstageActorFunctor( SignalData& data, Gesture::State& stateToUnstage ) + : GestureReceivedFunctor( data ), + stateToUnstage( stateToUnstage ) + { + } + + void operator()( Actor actor, const PanGesture& pan ) + { + GestureReceivedFunctor::operator()( actor, pan ); + + if ( pan.state == stateToUnstage ) + { + Stage::GetCurrent().Remove( actor ); + } + } + + Gesture::State& stateToUnstage; +}; + +// Functor for receiving a touch event +struct TouchEventFunctor +{ + bool operator()(Actor actor, const TouchEvent& touch) + { + return false; + } +}; + +// Data for constraints +struct ConstraintData +{ + ConstraintData() + : called(false) + { + } + + Vector2 screenPosition; + Vector2 screenDisplacement; + Vector2 screenVelocity; + Vector2 localPosition; + Vector2 localDisplacement; + Vector2 localVelocity; + bool called; + + void Reset() + { + screenPosition = screenDisplacement = screenVelocity = localPosition = localDisplacement = localVelocity = Vector2::ZERO; + called = false; + } +}; + +// Constraint used with panning properties +struct PanConstraint +{ + PanConstraint( ConstraintData& data ) : constraintData(data) { } + + void operator()( Vector3& current, const PropertyInputContainer& inputs ) + { + constraintData.screenPosition = inputs[0]->GetVector2(); + constraintData.screenDisplacement = inputs[1]->GetVector2(); + constraintData.screenVelocity = inputs[2]->GetVector2(); + constraintData.localPosition = inputs[3]->GetVector2(); + constraintData.localDisplacement = inputs[4]->GetVector2(); + constraintData.localVelocity = inputs[5]->GetVector2(); + constraintData.called = true; + current = Vector3::ZERO; + } + + ConstraintData& constraintData; +}; + +// Generate a PanGestureEvent to send to Core +Integration::PanGestureEvent GeneratePan( + Gesture::State state, + Vector2 previousPosition, + Vector2 currentPosition, + unsigned long timeDelta, + unsigned int numberOfTouches = 1, + unsigned int time = 1u) +{ + Integration::PanGestureEvent pan(state); + + pan.previousPosition = previousPosition; + pan.currentPosition = currentPosition; + pan.timeDelta = timeDelta; + pan.numberOfTouches = numberOfTouches; + pan.time = time; + + return pan; +} + +// Generate a PanGesture +PanGesture GeneratePan( unsigned int time, + Gesture::State state, + Vector2 screenPosition, + Vector2 localPosition, + Vector2 screenDisplacement = Vector2::ONE, + Vector2 localDisplacement = Vector2::ONE, + Vector2 screenVelocity = Vector2::ONE, + Vector2 localVelocity = Vector2::ONE, + unsigned int numberOfTouches = 1 ) +{ + PanGesture pan( state ); + + pan.time = time; + + pan.screenPosition = screenPosition; + pan.position = localPosition; + + pan.screenDisplacement = screenDisplacement; + pan.displacement = localDisplacement; + + pan.screenVelocity = screenVelocity; + pan.velocity = localVelocity; + + pan.numberOfTouches = numberOfTouches; + + return pan; +} + +/** + * Helper to generate PanGestureEvent + * + * @param[in] application Application instance + * @param[in] state The Gesture State + * @param[in] pos The current position of touch. + */ +static void SendPan(TestApplication& application, Gesture::State state, const Vector2& pos) +{ + static Vector2 last; + static int LastTime = 0; + + if( (state == Gesture::Started) || + (state == Gesture::Possible) ) + { + last.x = pos.x; + last.y = pos.y; + } + + application.ProcessEvent(GeneratePan(state, last, pos, PAN_EVENT_TIME_DELTA)); + + last.x = pos.x; + last.y = pos.y; + LastTime += PAN_EVENT_TIME_DELTA; +} + +static Vector2 PerformSwipeGestureSwipe(TestApplication& application, Vector2 start, Vector2 direction, int frames, bool finish = true) +{ + // Now do a pan starting from (start) and heading (direction) + Vector2 pos(start); + SendPan(application, Gesture::Possible, pos); + SendPan(application, Gesture::Started, pos); + application.SendNotification(); + application.Render(); + + for(int i = 0;i(object); + DALI_TEST_CHECK(detector3); + + BaseHandle unInitializedObject; + PanGestureDetector detector4 = PanGestureDetector::DownCast(unInitializedObject); + DALI_TEST_CHECK(!detector4); + + PanGestureDetector detector5 = DownCast< PanGestureDetector >(unInitializedObject); + DALI_TEST_CHECK(!detector5); + + GestureDetector detector6 = PanGestureDetector::New(); + PanGestureDetector detector7 = PanGestureDetector::DownCast(detector6); + DALI_TEST_CHECK(detector7); + END_TEST; +} + +int UtcDaliPanGestureSetMinimumTouchesRequired(void) +{ + TestApplication application; + + PanGestureDetector detector = PanGestureDetector::New(); + + unsigned int min = 2; + + DALI_TEST_CHECK(min != detector.GetMinimumTouchesRequired()); + + detector.SetMinimumTouchesRequired(min); + + DALI_TEST_EQUALS(min, detector.GetMinimumTouchesRequired(), TEST_LOCATION); + + // Attach an actor and change the minimum touches + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + TestGestureManager& gestureManager = application.GetGestureManager(); + gestureManager.Initialize(); + + detector.SetMinimumTouchesRequired(3); + + // Gesture detection should have been updated only + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + // Reset values + gestureManager.Initialize(); + + // Create a second gesture detector that requires even less minimum touches + PanGestureDetector secondDetector = PanGestureDetector::New(); + secondDetector.Attach(actor); + + // Gesture detection should have been updated only + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSetMaximumTouchesRequired(void) +{ + TestApplication application; + + PanGestureDetector detector = PanGestureDetector::New(); + + unsigned int max = 3; + + DALI_TEST_CHECK(max != detector.GetMaximumTouchesRequired()); + + detector.SetMaximumTouchesRequired(max); + + DALI_TEST_EQUALS(max, detector.GetMaximumTouchesRequired(), TEST_LOCATION); + + // Attach an actor and change the maximum touches + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + TestGestureManager& gestureManager = application.GetGestureManager(); + gestureManager.Initialize(); + + detector.SetMaximumTouchesRequired(4); + + // Gesture detection should have been updated only + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + // Reset values + gestureManager.Initialize(); + + // Create a second gesture detector that requires even less maximum touches + PanGestureDetector secondDetector = PanGestureDetector::New(); + secondDetector.Attach(actor); + + // Gesture detection should NOT have been updated + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureGetMinimumTouchesRequired(void) +{ + TestApplication application; + + PanGestureDetector detector = PanGestureDetector::New(); + DALI_TEST_EQUALS(1u, detector.GetMinimumTouchesRequired(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureGetMaximumTouchesRequired(void) +{ + TestApplication application; + + PanGestureDetector detector = PanGestureDetector::New(); + DALI_TEST_EQUALS(1u, detector.GetMaximumTouchesRequired(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionNegative(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Do a pan outside actor's area + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(110.0f, 110.0f), Vector2(112.0f, 112.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(110.0f, 110.0f), Vector2(112.0f, 112.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Continue pan into actor's area - we should still not receive the signal + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(112.0f, 112.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Stop panning - we should still not receive the signal + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 20.0f), Vector2(12.0f, 12.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionDownMotionLeave(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start pan within the actor's area + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(10.0f, 0.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(1.0f, 0.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(10.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(1.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION); + + // Continue the pan within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(0.0f, -10.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(0.0f, -1.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(10.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(1.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION); + + // Pan Gesture leaves actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 10.0f), Vector2(320.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(300.0f, 0.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(30.0f, 0.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(300.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(30.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION); + + // Gesture ends - we would receive a finished state + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(320.0f, 10.0f), Vector2(310.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(-10.0f, 0.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(-1.0f, 0.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(10.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(1.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionDownMotionUp(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start pan within the actor's area + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(10.0f, 0.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(1.0f, 0.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(10.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(1.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION); + + // Continue the pan within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(0.0f, -10.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(0.0f, -1.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(10.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(1.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION); + + // Gesture ends within actor's area - we would receive a finished state + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(-10.0f, 0.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(-1.0f, 0.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(10.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(1.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionCancelled(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start pan within the actor's area + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION); + + // Continue the pan within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION); + + // The gesture is cancelled + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Cancelled, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Cancelled, data.receivedGesture.state, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionDetach(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start pan within the actor's area + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Continue the pan within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Gesture ends within actor's area + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Detach actor + detector.DetachAll(); + + // Ensure we are no longer signalled + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionDetachWhilePanning(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start pan within the actor's area + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Continue the pan within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Detach actor during the pan, we should not receive the next event + detector.DetachAll(); + + // Gesture ends within actor's area + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionActorDestroyedWhilePanning(void) +{ + TestApplication application; + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.DetectedSignal().Connect(&application, functor); + + // Attach a temporary actor to stop detector being removed from PanGestureProcessor when main actor + // is destroyed. + Actor tempActor = Actor::New(); + tempActor.SetSize(100.0f, 100.0f); + tempActor.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT); + Stage::GetCurrent().Add(tempActor); + detector.Attach(tempActor); + + // Actor lifetime is scoped + { + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + detector.Attach(actor); + + // Start pan within the actor's area + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Continue the pan within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Remove the actor from stage and reset the data + Stage::GetCurrent().Remove(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + } + + // Actor should now have been destroyed + + // Gesture ends within the area where the actor used to be + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionRotatedActor(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Do an entire pan, only check finished value + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10)); + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(22.0f, 12.0f), Vector2(27.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(8.0f, -5.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); // Actor relative + + // Rotate actor again and render a couple of times + actor.SetOrientation(Dali::Degree(180.0f), Vector3::ZAXIS); + application.SendNotification(); + application.Render(); + + // Do an entire pan, only check finished value + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10)); + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(22.0f, 12.0f), Vector2(27.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(-5.0f, -8.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); // Actor relative + + // Rotate actor again and render a couple of times + actor.SetOrientation(Dali::Degree(270.0f), Vector3::ZAXIS); + application.SendNotification(); + application.Render(); + + // Do an entire pan, only check finished value + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10)); + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(22.0f, 12.0f), Vector2(27.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(-8.0f, 5.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); // Actor relative + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionChildHit(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + parent.SetSize(100.0f, 100.0f); + parent.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(parent); + + // Set child to completely cover parent. + // Change rotation of child to be different from parent so that we can check if our local coordinate + // conversion of the parent actor is correct. + Actor child = Actor::New(); + child.SetSize(100.0f, 100.0f); + child.SetAnchorPoint(AnchorPoint::CENTER); + child.SetParentOrigin(ParentOrigin::CENTER); + child.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS); + parent.Add(child); + + TouchEventFunctor touchFunctor; + child.TouchedSignal().Connect(&application, touchFunctor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(parent); + detector.DetectedSignal().Connect(&application, functor); + + // Do an entire pan, only check finished value - hits child area but parent should still receive it + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10)); + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(22.0f, 12.0f), Vector2(27.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, parent == data.pannedActor, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(5.0f, 8.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); // Actor relative + + // Attach child and generate same touch points to yield a different displacement + // (Also proves that you can detach and then re-attach another actor) + detector.Attach(child); + detector.Detach(parent); + + // Do an entire pan, only check finished value + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10)); + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(22.0f, 12.0f), Vector2(27.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, child == data.pannedActor, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(8.0f, -5.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); // Actor relative + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionAttachDetachMany(void) +{ + TestApplication application; + + Actor first = Actor::New(); + first.SetSize(100.0f, 100.0f); + first.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(first); + + Actor second = Actor::New(); + second.SetSize(100.0f, 100.0f); + second.SetX(100.0f); + second.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(second); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(first); + detector.Attach(second); + detector.DetectedSignal().Connect(&application, functor); + + // Start pan within second actor's area + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(110.0f, 20.0f), Vector2(120.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(110.0f, 20.0f), Vector2(120.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, second == data.pannedActor, TEST_LOCATION); + + // Pan moves into first actor's area - second actor should receive the pan + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(120.0f, 20.0f), Vector2(20.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, second == data.pannedActor, TEST_LOCATION); + + // Detach the second actor during the pan, we should not receive the next event + detector.Detach(second); + + // Gesture ends within actor's area + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionActorBecomesUntouchable(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start pan in actor's area + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Pan continues within actor's area + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Actor become invisible - actor should not receive the next pan + actor.SetVisible(false); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Gesture ends within actor's area + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionMultipleGestureDetectors(void) +{ + TestApplication application; + Dali::TestGestureManager& gestureManager = application.GetGestureManager(); + + Actor first = Actor::New(); + first.SetSize(100.0f, 100.0f); + first.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(first); + + Actor second = Actor::New(); + second.SetSize(100.0f, 100.0f); + second.SetAnchorPoint(AnchorPoint::TOP_LEFT); + first.Add(second); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector firstDetector = PanGestureDetector::New(); + firstDetector.Attach(first); + firstDetector.DetectedSignal().Connect(&application, functor); + + // secondDetector is scoped + { + // Reset gestureManager statistics + gestureManager.Initialize(); + + PanGestureDetector secondDetector = PanGestureDetector::New(); + secondDetector.SetMinimumTouchesRequired(2); + secondDetector.SetMaximumTouchesRequired(2); + secondDetector.Attach(second); + secondDetector.DetectedSignal().Connect(&application, functor); + + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + // Start pan within second actor's area + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10, 2)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10, 2)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, second == data.pannedActor, TEST_LOCATION); + + // Two touch pan changes to single touch - we should receive a finished state + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(true, second == data.pannedActor, TEST_LOCATION); + + // Pan continues as single touch gesture - we should not receive any gesture + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 10.0f), Vector2(30.0f, 10.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Pan ends - still no signal + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(30.0f, 10.0f), Vector2(30.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Single touch pan starts - first actor should be panned + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, first == data.pannedActor, TEST_LOCATION); + + // Pan changes to double-touch - we should receive a finished state + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10, 2)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(true, first == data.pannedActor, TEST_LOCATION); + + // Pan continues as double touch gesture - we should not receive any gesture + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 10.0f), Vector2(30.0f, 10.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Pan ends - still no signal + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(30.0f, 10.0f), Vector2(30.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Reset gesture manager statistics + gestureManager.Initialize(); + } + + // secondDetector has now been deleted. Gesture detection should have been updated only + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionMultipleDetectorsOnActor(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + Actor actor2 = Actor::New(); + actor2.SetSize(100.0f, 100.0f); + actor2.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT); + Stage::GetCurrent().Add(actor2); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to one detector + SignalData firstData; + GestureReceivedFunctor firstFunctor(firstData); + PanGestureDetector firstDetector = PanGestureDetector::New(); + firstDetector.Attach(actor); + firstDetector.DetectedSignal().Connect(&application, firstFunctor); + + // Attach actor to another detector + SignalData secondData; + GestureReceivedFunctor secondFunctor(secondData); + PanGestureDetector secondDetector = PanGestureDetector::New(); + secondDetector.Attach(actor); + secondDetector.DetectedSignal().Connect(&application, secondFunctor); + + // Add second actor to second detector, when we remove the actor, this will make sure that this + // gesture detector is not removed from the GestureDetectorProcessor. In this scenario, the + // functor should still not be called (which is what we're also testing). + secondDetector.Attach(actor2); + + // Pan in actor's area - both detector's functors should be called + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION); + + // Pan continues in actor's area - both detector's functors should be called + firstData.Reset(); + secondData.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(10.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION); + + // Detach actor from firstDetector and emit pan on actor, only secondDetector's functor should be called. + firstDetector.Detach(actor); + firstData.Reset(); + secondData.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 20.0f), Vector2(10.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, firstData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION); + + // New pan on actor, only secondDetector has actor attached + firstData.Reset(); + secondData.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, firstData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION); + + // Detach actor from secondDetector + secondDetector.Detach(actor); + firstData.Reset(); + secondData.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(10.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, firstData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(false, secondData.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionMultipleStarted(void) +{ + // Should handle two started events gracefully. + + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Start pan in actor's area + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Send another start in actor's area + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Add a child actor to overlap actor and send another start in actor's area + Actor child = Actor::New(); + child.SetSize(100.0f, 100.0f); + child.SetAnchorPoint(AnchorPoint::CENTER); + child.SetParentOrigin(ParentOrigin::CENTER); + actor.Add(child); + + TouchEventFunctor touchFunctor; + child.TouchedSignal().Connect(&application, touchFunctor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Send another possible and start in actor's area + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Send another start in actor's area + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionEnsureCorrectSignalling(void) +{ + TestApplication application; + + Actor actor1 = Actor::New(); + actor1.SetSize(100.0f, 100.0f); + actor1.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor1); + SignalData data1; + GestureReceivedFunctor functor1(data1); + PanGestureDetector detector1 = PanGestureDetector::New(); + detector1.Attach(actor1); + detector1.DetectedSignal().Connect(&application, functor1); + + Actor actor2 = Actor::New(); + actor2.SetSize(100.0f, 100.0f); + actor2.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT); + actor2.SetParentOrigin(ParentOrigin::BOTTOM_RIGHT); + Stage::GetCurrent().Add(actor2); + SignalData data2; + GestureReceivedFunctor functor2(data2); + PanGestureDetector detector2 = PanGestureDetector::New(); + detector2.Attach(actor2); + detector2.DetectedSignal().Connect(&application, functor2); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Start pan in actor1's area, only data1 should be set + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data1.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(false, data2.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSignalReceptionDifferentPossible(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Gesture possible in actor's area. + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Move actor somewhere else + actor.SetPosition( 100.0f, 100.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit Started event, we should not receive the long press. + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // LongPress possible in empty area. + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Move actor in to the long press position. + actor.SetPosition( 0.0f, 0.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit Started event, we should not receive the long press. + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Normal long press in actor's area for completeness. + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureEmitIncorrectState(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Try a Clear state + try + { + application.ProcessEvent(GeneratePan(Gesture::Clear, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + tet_result(TET_FAIL); + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_ASSERT( e, "false", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliPanGestureActorUnstaged(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // State to remove actor in. + Gesture::State stateToUnstage( Gesture::Started ); + + // Attach actor to detector + SignalData data; + UnstageActorFunctor functor( data, stateToUnstage ); + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Emit signals + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Re-add actor to stage + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Change state to Gesture::Continuing to remove + stateToUnstage = Gesture::Continuing; + + // Emit signals + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Re-add actor to stage + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Change state to Gesture::Finished to remove + stateToUnstage = Gesture::Finished; + + // Emit signals + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + tet_result( TET_PASS ); // If we get here then we have handled actor stage removal gracefully. + END_TEST; +} + +int UtcDaliPanGestureActorStagedAndDestroyed(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Create and add a second actor so that GestureDetector destruction does not come into play. + Actor dummyActor( Actor::New() ); + dummyActor.SetSize( 100.0f, 100.0f ); + dummyActor.SetPosition( 100.0f, 100.0f ); + dummyActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(dummyActor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // State to remove actor in. + Gesture::State stateToUnstage( Gesture::Started ); + + // Attach actor to detector + SignalData data; + UnstageActorFunctor functor( data, stateToUnstage ); + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.Attach(dummyActor); + detector.DetectedSignal().Connect( &application, functor ); + + // Here we are testing a Started actor which is removed in the Started callback, but then added back + // before we get a continuing state. As we were removed from the stage, even if we're at the same + // position, we should still not be signalled. + + // Emit signals + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Re add to the stage, we should not be signalled + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Continue signal emission + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Here we delete an actor in started, we should not receive any subsequent signalling. + + // Emit signals + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Delete actor as well + actor.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Continue signal emission + application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureSystemOverlay(void) +{ + TestApplication application; + Dali::Integration::Core& core = application.GetCore(); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + Vector2 screenCoordsStart( 10.0f, 20.0f ); + Vector2 screenCoordsEnd( 20.0f, 20.0f ); + + // Start pan within the actor's area + application.ProcessEvent( GeneratePan( Gesture::Possible, screenCoordsStart, screenCoordsEnd, 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, screenCoordsStart, screenCoordsEnd, 10 ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPanGestureBehindTouchableSystemOverlay(void) +{ + TestApplication application; + Dali::Integration::Core& core = application.GetCore(); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + // SystemOverlay actor + Actor systemOverlayActor = Actor::New(); + systemOverlayActor.SetSize(100.0f, 100.0f); + systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add(systemOverlayActor); + + // Stage actor + Actor stageActor = Actor::New(); + stageActor.SetSize(100.0f, 100.0f); + stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(stageActor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set system-overlay actor to touchable + TouchEventData touchData; + TouchEventDataFunctor touchFunctor( touchData ); + systemOverlayActor.TouchedSignal().Connect(&application, touchFunctor); + + // Set stage actor to receive the gesture + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(stageActor); + detector.DetectedSignal().Connect(&application, functor); + + Vector2 screenCoordsStart( 10.0f, 20.0f ); + Vector2 screenCoordsEnd( 20.0f, 20.0f ); + + // Start pan within the two actors' area + application.ProcessEvent( GeneratePan( Gesture::Possible, screenCoordsStart, screenCoordsEnd, 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, screenCoordsStart, screenCoordsEnd, 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Finished, screenCoordsStart, screenCoordsEnd, 10 ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION ); + + data.Reset(); + touchData.Reset(); + + // Do touch in the same area + application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoordsStart ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPanGestureTouchBehindGesturedSystemOverlay(void) +{ + TestApplication application; + Dali::Integration::Core& core = application.GetCore(); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + // SystemOverlay actor + Actor systemOverlayActor = Actor::New(); + systemOverlayActor.SetSize(100.0f, 100.0f); + systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add(systemOverlayActor); + + // Stage actor + Actor stageActor = Actor::New(); + stageActor.SetSize(100.0f, 100.0f); + stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(stageActor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set stage actor to touchable + TouchEventData touchData; + TouchEventDataFunctor touchFunctor( touchData ); + stageActor.TouchedSignal().Connect(&application, touchFunctor); + + // Set system-overlay actor to have the gesture + SignalData data; + GestureReceivedFunctor functor(data); + + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach(systemOverlayActor); + detector.DetectedSignal().Connect(&application, functor); + + Vector2 screenCoordsStart( 10.0f, 20.0f ); + Vector2 screenCoordsEnd( 20.0f, 20.0f ); + + // Start pan within the two actors' area + application.ProcessEvent( GeneratePan( Gesture::Possible, screenCoordsStart, screenCoordsEnd, 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, screenCoordsStart, screenCoordsEnd, 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Finished, screenCoordsStart, screenCoordsEnd, 10 ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION ); + + data.Reset(); + touchData.Reset(); + + // Do touch in the same area + application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoordsStart ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPanGestureAngleHandling(void) +{ + TestApplication application; + + PanGestureDetector detector = PanGestureDetector::New(); + DALI_TEST_EQUALS( detector.GetAngleCount(), 0u, TEST_LOCATION ); + + detector.AddAngle( PanGestureDetector::DIRECTION_LEFT, Radian( Math::PI * 0.25 ) ); + DALI_TEST_EQUALS( detector.GetAngleCount(), 1u, TEST_LOCATION ); + bool found = false; + for( size_t i = 0; i < detector.GetAngleCount(); i++) + { + if( detector.GetAngle(i).first == PanGestureDetector::DIRECTION_LEFT ) + { + tet_result( TET_PASS ); + found = true; + break; + } + } + + if(!found ) + { + tet_printf("%s, angle not added\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + + detector.AddAngle( PanGestureDetector::DIRECTION_RIGHT, Radian( Math::PI * 0.25 ) ); + DALI_TEST_EQUALS( detector.GetAngleCount(), 2u, TEST_LOCATION ); + + // Remove something not in the container. + detector.RemoveAngle( PanGestureDetector::DIRECTION_UP ); + DALI_TEST_EQUALS( detector.GetAngleCount(), 2u, TEST_LOCATION ); + + detector.RemoveAngle( PanGestureDetector::DIRECTION_RIGHT ); + DALI_TEST_EQUALS( detector.GetAngleCount(), 1u, TEST_LOCATION ); + for ( size_t i = 0; i < detector.GetAngleCount(); i++) + { + if ( detector.GetAngle(i).first == PanGestureDetector::DIRECTION_RIGHT ) + { + tet_printf("%s, angle not removed\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + break; + } + } + + detector.ClearAngles(); + DALI_TEST_EQUALS( detector.GetAngleCount(), 0u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPanGestureGetAngle(void) +{ + TestApplication application; + + PanGestureDetector detector = PanGestureDetector::New(); + DALI_TEST_EQUALS( detector.GetAngleCount(), 0, TEST_LOCATION ); + + detector.AddAngle( PanGestureDetector::DIRECTION_LEFT ); + DALI_TEST_EQUALS( detector.GetAngleCount(), 1, TEST_LOCATION ); + + detector.AddAngle( PanGestureDetector::DIRECTION_RIGHT ); + DALI_TEST_EQUALS( detector.GetAngleCount(), 2, TEST_LOCATION ); + + detector.AddAngle( PanGestureDetector::DIRECTION_UP ); + DALI_TEST_EQUALS( detector.GetAngleCount(), 3, TEST_LOCATION ); + + detector.AddAngle( PanGestureDetector::DIRECTION_DOWN ); + DALI_TEST_EQUALS( detector.GetAngleCount(), 4, TEST_LOCATION ); + + DALI_TEST_EQUALS( detector.GetAngle(0).first, PanGestureDetector::DIRECTION_LEFT, TEST_LOCATION ); + DALI_TEST_EQUALS( detector.GetAngle(1).first, PanGestureDetector::DIRECTION_RIGHT, TEST_LOCATION ); + DALI_TEST_EQUALS( detector.GetAngle(2).first, PanGestureDetector::DIRECTION_UP, TEST_LOCATION ); + DALI_TEST_EQUALS( detector.GetAngle(3).first, PanGestureDetector::DIRECTION_DOWN, TEST_LOCATION ); + + END_TEST; +} + +inline float RadiansToDegrees( float radian ) +{ + return radian * 180.0f / Math::PI; +} + +int UtcDaliPanGestureAngleOutOfRange(void) +{ + TestApplication application; + + PanGestureDetector detector = PanGestureDetector::New(); + DALI_TEST_EQUALS( detector.GetAngleCount(), 0u, TEST_LOCATION ); + + // + // Angle + // + + detector.AddAngle( Degree(180.0f) ); + DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(-180.0f) ), 0.000001, TEST_LOCATION ); + detector.ClearAngles(); + + detector.AddAngle( Degree(190.0f) ); + DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(-170.0f) ), 0.000001, TEST_LOCATION ); + detector.ClearAngles(); + + detector.AddAngle( Degree(-190.0f) ); + DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(170.0f) ), 0.000001, TEST_LOCATION ); + detector.ClearAngles(); + + detector.AddAngle( Degree(350.0f) ); + DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(-10.0f) ), 0.000001, TEST_LOCATION ); + detector.ClearAngles(); + + detector.AddAngle( Degree(-350.0f) ); + DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(10.0f) ), 0.000001, TEST_LOCATION ); + detector.ClearAngles(); + + detector.AddAngle( Degree(370.0f) ); + DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(10.0f) ), 0.000001, TEST_LOCATION ); + detector.ClearAngles(); + + detector.AddAngle( Degree(-370.0f) ); + DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(-10.0f) ), 0.000001, TEST_LOCATION ); + detector.ClearAngles(); + + // + // Threshold + // + + detector.AddAngle( PanGestureDetector::DIRECTION_RIGHT, Degree( 0.0f ) ); + DALI_TEST_EQUALS( detector.GetAngle(0).second, Radian( Degree(0.0f) ), 0.000001, TEST_LOCATION ); + detector.ClearAngles(); + + detector.AddAngle( PanGestureDetector::DIRECTION_RIGHT, Degree( -10.0f ) ); + DALI_TEST_EQUALS( detector.GetAngle(0).second, Radian( Degree(10.0f) ), 0.000001, TEST_LOCATION ); + detector.ClearAngles(); + + detector.AddAngle( PanGestureDetector::DIRECTION_RIGHT, Degree( -181.0f ) ); + DALI_TEST_EQUALS( detector.GetAngle(0).second, Radian( Degree(180.0f) ), 0.000001, TEST_LOCATION ); + detector.ClearAngles(); + + detector.AddAngle( PanGestureDetector::DIRECTION_RIGHT, Degree( 181.0f ) ); + DALI_TEST_EQUALS( detector.GetAngle(0).second, Radian( Degree(180.0f) ), 0.000001, TEST_LOCATION ); + detector.ClearAngles(); + END_TEST; +} + +int UtcDaliPanGestureAngleProcessing(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + parent.SetSize(100.0f, 100.0f); + parent.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(parent); + + Actor child = Actor::New(); + child.SetSize(100.0f, 100.0f); + child.SetAnchorPoint(AnchorPoint::TOP_LEFT); + parent.Add(child); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Parent detector only requires up pans + PanGestureDetector parentDetector = PanGestureDetector::New(); + parentDetector.Attach( parent ); + parentDetector.AddAngle( PanGestureDetector::DIRECTION_UP, Degree( 30.0f ) ); + SignalData parentData; + GestureReceivedFunctor parentFunctor(parentData); + parentDetector.DetectedSignal().Connect(&application, parentFunctor); + + // Child detector only requires right pans + PanGestureDetector childDetector = PanGestureDetector::New(); + childDetector.Attach( child ); + childDetector.AddAngle( PanGestureDetector::DIRECTION_RIGHT, Degree( 30.0f ) ); + SignalData childData; + GestureReceivedFunctor childFunctor(childData); + childDetector.DetectedSignal().Connect(&application, childFunctor); + + // Generate an Up pan gesture, only parent should receive it. + application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10 ) ); + DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION ); + application.ProcessEvent( GeneratePan( Gesture::Finished, Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) ); + parentData.Reset(); + childData.Reset(); + + // Generate a Right pan gesture, only child should receive it. + application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, Vector2(20.0f, 20.0f), Vector2(30.0f, 20.0f), 10 ) ); + DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, childData.functorCalled, TEST_LOCATION ); + application.ProcessEvent( GeneratePan( Gesture::Finished, Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) ); + parentData.Reset(); + childData.Reset(); + + // Generate a Down pan gesture, no one should receive it. + application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, Vector2(20.0f, 20.0f), Vector2(20.0f, 30.0f), 10 ) ); + DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION ); + application.ProcessEvent( GeneratePan( Gesture::Finished, Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) ); + parentData.Reset(); + childData.Reset(); + + // Generate a Left pan gesture, no one should receive it. + application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, Vector2(20.0f, 20.0f), Vector2(10.0f, 20.0f), 10 ) ); + DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION ); + application.ProcessEvent( GeneratePan( Gesture::Finished, Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) ); + parentData.Reset(); + childData.Reset(); + END_TEST; +} + +int UtcDaliPanGestureDirectionHandling(void) +{ + TestApplication application; + + PanGestureDetector detector = PanGestureDetector::New(); + DALI_TEST_EQUALS( detector.GetAngleCount(), 0u, TEST_LOCATION ); + + detector.AddDirection( PanGestureDetector::DIRECTION_LEFT, Radian( Math::PI * 0.25 ) ); + DALI_TEST_EQUALS( detector.GetAngleCount(), 2u, TEST_LOCATION ); + bool found = false; + for ( size_t i = 0; detector.GetAngleCount(); i++) + { + if ( detector.GetAngle(i).first == PanGestureDetector::DIRECTION_LEFT ) + { + tet_result( TET_PASS ); + found = true; + break; + } + + } + + if (!found ) + { + tet_printf("%s, angle not added\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + + found = false; + for( size_t i = 0; i < detector.GetAngleCount(); i++) + { + if( detector.GetAngle(i).first == PanGestureDetector::DIRECTION_RIGHT ) + { + tet_result( TET_PASS ); + found = true; + break; + } + } + + if(!found ) + { + tet_printf("%s, angle not added\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + + // Remove something not in the container. + detector.RemoveDirection( PanGestureDetector::DIRECTION_UP ); + DALI_TEST_EQUALS( detector.GetAngleCount(), 2u, TEST_LOCATION ); + + detector.RemoveDirection( PanGestureDetector::DIRECTION_RIGHT ); + DALI_TEST_EQUALS( detector.GetAngleCount(), 0u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPanGestureDirectionProcessing(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + parent.SetSize(100.0f, 100.0f); + parent.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(parent); + + Actor child = Actor::New(); + child.SetSize(100.0f, 100.0f); + child.SetAnchorPoint(AnchorPoint::TOP_LEFT); + parent.Add(child); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Parent detector only requires vertical panning + PanGestureDetector parentDetector = PanGestureDetector::New(); + parentDetector.Attach( parent ); + parentDetector.AddDirection( PanGestureDetector::DIRECTION_VERTICAL, Degree( 30.0f ) ); + SignalData parentData; + GestureReceivedFunctor parentFunctor(parentData); + parentDetector.DetectedSignal().Connect(&application, parentFunctor); + + // Child detector only requires horizontal panning + PanGestureDetector childDetector = PanGestureDetector::New(); + childDetector.Attach( child ); + childDetector.AddDirection( PanGestureDetector::DIRECTION_HORIZONTAL, Degree( 30.0f ) ); + SignalData childData; + GestureReceivedFunctor childFunctor(childData); + childDetector.DetectedSignal().Connect(&application, childFunctor); + + // Generate an Up pan gesture, only parent should receive it. + application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10 ) ); + DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION ); + application.ProcessEvent( GeneratePan( Gesture::Finished, Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) ); + parentData.Reset(); + childData.Reset(); + + // Generate a Right pan gesture, only child should receive it. + application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, Vector2(20.0f, 20.0f), Vector2(30.0f, 20.0f), 10 ) ); + DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, childData.functorCalled, TEST_LOCATION ); + application.ProcessEvent( GeneratePan( Gesture::Finished, Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) ); + parentData.Reset(); + childData.Reset(); + + // Generate a Down pan gesture, only parent should receive it. + application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, Vector2(20.0f, 20.0f), Vector2(20.0f, 30.0f), 10 ) ); + DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION ); + application.ProcessEvent( GeneratePan( Gesture::Finished, Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) ); + parentData.Reset(); + childData.Reset(); + + // Generate a Left pan gesture, only child should receive it. + application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, Vector2(20.0f, 20.0f), Vector2(10.0f, 20.0f), 10 ) ); + DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, childData.functorCalled, TEST_LOCATION ); + application.ProcessEvent( GeneratePan( Gesture::Finished, Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) ); + parentData.Reset(); + childData.Reset(); + + // Generate a pan at -45 degrees, no one should receive it. + application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, Vector2(20.0f, 20.0f), Vector2(10.0f, 30.0f), 10 ) ); + DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION ); + application.ProcessEvent( GeneratePan( Gesture::Finished, Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) ); + parentData.Reset(); + childData.Reset(); + + // Generate a pan at 45 degrees, no one should receive it. + application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, Vector2(20.0f, 20.0f), Vector2(30.0f, 30.0f), 10 ) ); + DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION ); + application.ProcessEvent( GeneratePan( Gesture::Finished, Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) ); + parentData.Reset(); + childData.Reset(); + + // Generate a pan at 135 degrees, no one should receive it. + application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, Vector2(20.0f, 20.0f), Vector2(10.0f, 30.0f), 10 ) ); + DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION ); + application.ProcessEvent( GeneratePan( Gesture::Finished, Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) ); + parentData.Reset(); + childData.Reset(); + + // Generate a pan at -135 degrees, no one should receive it. + application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, Vector2(20.0f, 20.0f), Vector2(10.0f, 10.0f), 10 ) ); + DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, childData.functorCalled, TEST_LOCATION ); + application.ProcessEvent( GeneratePan( Gesture::Finished, Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) ); + parentData.Reset(); + childData.Reset(); + END_TEST; +} + +int UtcDaliPanGestureNoPredictionNoSmoothing(void) +{ + TestApplication application; + Integration::SetPanGesturePredictionMode(0); + Integration::SetPanGestureSmoothingMode(0); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Add a pan detector + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach( actor ); + SignalData data; + GestureReceivedFunctor functor( data ); + detector.DetectedSignal().Connect( &application, functor ); + + Property::Index property = actor.RegisterProperty( "Dummy Property", Vector3::ZERO ); + + ConstraintData constraintData; + Constraint constraint = Constraint::New( actor, property, PanConstraint( constraintData ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_POSITION ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_DISPLACEMENT ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_VELOCITY ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_DISPLACEMENT ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_VELOCITY ) ); + constraint.Apply(); + + // Render and notify + application.SendNotification(); + application.Render(); + + Vector2 direction(Vector2::XAXIS * -5.0f); + Vector2 startPosition( 1.0f, 1.0f ); + PerformSwipeGestureSwipe(application, startPosition, direction, PAN_GESTURE_UPDATE_COUNT, true); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.called, true, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.screenPosition, startPosition + (direction * PAN_GESTURE_UPDATE_COUNT), 0.1f, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.localPosition, startPosition + (direction * PAN_GESTURE_UPDATE_COUNT), 0.1f, TEST_LOCATION ); + + constraintData.Reset(); + END_TEST; +} + +int UtcDaliPanGestureNoPredictionSmoothing(void) +{ + TestApplication application; + Integration::SetPanGesturePredictionMode(0); + Integration::SetPanGestureSmoothingMode(1); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Add a pan detector + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach( actor ); + SignalData data; + GestureReceivedFunctor functor( data ); + detector.DetectedSignal().Connect( &application, functor ); + + Property::Index property = actor.RegisterProperty( "Dummy Property", Vector3::ZERO ); + + ConstraintData constraintData; + Constraint constraint = Constraint::New( actor, property, PanConstraint( constraintData ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_POSITION ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_DISPLACEMENT ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_VELOCITY ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_DISPLACEMENT ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_VELOCITY ) ); + constraint.Apply(); + + // Render and notify + application.SendNotification(); + application.Render(); + + Vector2 direction(Vector2::XAXIS * -5.0f); + Vector2 previousPosition( 20.0f, 20.0f ); + Vector2 currentPosition( 20.0f, 10.0f ); + PerformSwipeGestureSwipe(application, Vector2(1.0f, 1.0f), direction, PAN_GESTURE_UPDATE_COUNT, true); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.called, true, TEST_LOCATION ); + // Take into account resampling done when prediction is off. + DALI_TEST_EQUALS( constraintData.screenPosition, Vector2(1.0f, 1.0f) + (direction * (PAN_GESTURE_UPDATE_COUNT - 0.25f)), 0.15f, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.localPosition, Vector2(1.0f, 1.0f) + (direction * (PAN_GESTURE_UPDATE_COUNT - 0.25f)), 0.15f, TEST_LOCATION ); + + constraintData.Reset(); + END_TEST; +} + +int UtcDaliPanGesturePredictionNoSmoothing(void) +{ + TestApplication application; + Integration::SetPanGesturePredictionMode(1); + Integration::SetPanGestureSmoothingMode(0); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Add a pan detector + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach( actor ); + SignalData data; + GestureReceivedFunctor functor( data ); + detector.DetectedSignal().Connect( &application, functor ); + + Property::Index property = actor.RegisterProperty( "Dummy Property", Vector3::ZERO ); + + ConstraintData constraintData; + Constraint constraint = Constraint::New( actor, property, PanConstraint( constraintData ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_POSITION ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_DISPLACEMENT ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_VELOCITY ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_DISPLACEMENT ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_VELOCITY ) ); + constraint.Apply(); + + // Render and notify + application.SendNotification(); + application.Render(); + + Vector2 direction(Vector2::XAXIS * -1.0f); + Vector2 previousPosition( 20.0f, 20.0f ); + Vector2 currentPosition( 20.0f, 10.0f ); + PerformSwipeGestureSwipe(application, Vector2(1.0f, 1.0f), direction, PAN_GESTURE_UPDATE_COUNT, true); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.called, true, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.screenPosition, Vector2(1.0f, 1.0f) + (direction * PAN_GESTURE_UPDATE_COUNT), 10.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.localPosition, Vector2(1.0f, 1.0f) + (direction * PAN_GESTURE_UPDATE_COUNT), 10.0f, TEST_LOCATION ); + + constraintData.Reset(); + END_TEST; +} + +int UtcDaliPanGesturePredictionSmoothing(void) +{ + TestApplication application; + Integration::SetPanGesturePredictionMode(1); + Integration::SetPanGestureSmoothingMode(1); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Add a pan detector + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach( actor ); + SignalData data; + GestureReceivedFunctor functor( data ); + detector.DetectedSignal().Connect( &application, functor ); + + Property::Index property = actor.RegisterProperty( "Dummy Property", Vector3::ZERO ); + + ConstraintData constraintData; + Constraint constraint = Constraint::New( actor, property, PanConstraint( constraintData ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_POSITION ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_DISPLACEMENT ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_VELOCITY ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_DISPLACEMENT ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_VELOCITY ) ); + constraint.Apply(); + + // Render and notify + application.SendNotification(); + application.Render(); + + Vector2 direction(Vector2::XAXIS * -1.0f); + Vector2 previousPosition( 20.0f, 20.0f ); + Vector2 currentPosition( 20.0f, 10.0f ); + PerformSwipeGestureSwipe(application, Vector2(1.0f, 1.0f), direction, PAN_GESTURE_UPDATE_COUNT, true); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.called, true, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.screenPosition, Vector2(1.0f, 1.0f) + (direction * PAN_GESTURE_UPDATE_COUNT), 10.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.localPosition, Vector2(1.0f, 1.0f) + (direction * PAN_GESTURE_UPDATE_COUNT), 10.0f, TEST_LOCATION ); + + constraintData.Reset(); + END_TEST; +} + +int UtcDaliPanGestureSetProperties(void) +{ + TestApplication application; + TestRenderController& renderController( application.GetRenderController() ); + Integration::SetPanGesturePredictionMode(0); + Integration::SetPanGestureSmoothingMode(0); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Add a pan detector + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach( actor ); + SignalData data; + GestureReceivedFunctor functor( data ); + detector.DetectedSignal().Connect( &application, functor ); + + Property::Index property = actor.RegisterProperty( "Dummy Property", Vector3::ZERO ); + + ConstraintData constraintData; + Constraint constraint = Constraint::New( actor, property, PanConstraint( constraintData ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_POSITION ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_DISPLACEMENT ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_VELOCITY ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_DISPLACEMENT ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_VELOCITY ) ); + constraint.Apply(); + + // Render and notify + application.SendNotification(); + application.Render(); + + renderController.Initialize(); + DALI_TEST_EQUALS( renderController.WasCalled( TestRenderController::RequestUpdateFunc ), false, TEST_LOCATION ); + + Vector2 screenPosition( 20.0f, 20.0f ); + Vector2 screenDisplacement( 1.0f, 1.0f ); + Vector2 screenVelocity( 1.3f, 4.0f ); + Vector2 localPosition( 21.0f, 21.0f ); + Vector2 localDisplacement( 0.5f, 0.5f ); + Vector2 localVelocity( 1.5f, 2.5f ); + + PanGestureDetector::SetPanGestureProperties( GeneratePan( 1u, Gesture::Started, screenPosition, localPosition, screenDisplacement, localDisplacement, screenVelocity, localVelocity ) ); + DALI_TEST_EQUALS( renderController.WasCalled( TestRenderController::RequestUpdateFunc ), true, TEST_LOCATION ); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( constraintData.called, true, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.screenPosition, screenPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.localPosition, localPosition, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.screenDisplacement, screenDisplacement, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.localDisplacement, localDisplacement, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.screenVelocity, screenVelocity, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.localVelocity, localVelocity, TEST_LOCATION ); + constraintData.Reset(); + END_TEST; +} + +int UtcDaliPanGestureSetPropertiesAlreadyPanning(void) +{ + TestApplication application; + Integration::SetPanGesturePredictionMode(0); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Add a pan detector + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach( actor ); + SignalData data; + GestureReceivedFunctor functor( data ); + detector.DetectedSignal().Connect( &application, functor ); + + Property::Index property = actor.RegisterProperty( "Dummy Property", Vector3::ZERO ); + + ConstraintData constraintData; + Constraint constraint = Constraint::New( actor, property, PanConstraint( constraintData ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_POSITION ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_DISPLACEMENT ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_VELOCITY ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_DISPLACEMENT ) ); + constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_VELOCITY ) ); + constraint.Apply(); + + // Render and notify + application.SendNotification(); + application.Render(); + + Vector2 previousPosition( 20.0f, 20.0f ); + Vector2 currentPosition( 20.0f, 10.0f ); + application.ProcessEvent( GeneratePan( Gesture::Possible, previousPosition, previousPosition, 10 ) ); + application.ProcessEvent( GeneratePan( Gesture::Started, previousPosition, currentPosition, 10 ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + + Vector2 screenPosition( 100.0f, 20.0f ); + Vector2 localPosition( 110.0f, 110.0f ); + + PanGestureDetector::SetPanGestureProperties( GeneratePan( 1u, Gesture::Started, screenPosition, localPosition ) ); + + // Render and notify + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( constraintData.called, true, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.screenPosition, currentPosition, 0.1, TEST_LOCATION ); + DALI_TEST_EQUALS( constraintData.localPosition, currentPosition, 0.1f, TEST_LOCATION ); + constraintData.Reset(); + END_TEST; +} + +int UtcDaliPanGesturePropertyIndices(void) +{ + TestApplication application; + PanGestureDetector detector = PanGestureDetector::New(); + + Property::IndexContainer indices; + detector.GetPropertyIndices( indices ); + DALI_TEST_CHECK( indices.Size() ); + DALI_TEST_EQUALS( indices.Size(), detector.GetPropertyCount(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPanGestureLayerConsumesTouch(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Add a pan detector + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach( actor ); + SignalData data; + GestureReceivedFunctor functor( data ); + detector.DetectedSignal().Connect( &application, functor ); + + // Add a layer to overlap the actor + Layer layer = Layer::New(); + layer.SetSize(100.0f, 100.0f); + layer.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add( layer ); + layer.RaiseToTop(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit signals, should receive + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Set layer to consume all touch + layer.SetTouchConsumed( true ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit the same signals again, should not receive + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + + END_TEST; +} + +int UtcDaliPanGestureNoTimeDiff(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Add a pan detector + PanGestureDetector detector = PanGestureDetector::New(); + detector.Attach( actor ); + SignalData data; + GestureReceivedFunctor functor( data ); + detector.DetectedSignal().Connect( &application, functor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit signals, should receive + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 0)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 0)); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 0)); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_CHECK( !std::isinf( data.receivedGesture.velocity.x ) ); + DALI_TEST_CHECK( !std::isinf( data.receivedGesture.velocity.y ) ); + DALI_TEST_CHECK( !std::isinf( data.receivedGesture.screenVelocity.x ) ); + DALI_TEST_CHECK( !std::isinf( data.receivedGesture.screenVelocity.y ) ); + data.Reset(); + + data.Reset(); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Path.cpp b/automated-tests/src/dali/utc-Dali-Path.cpp new file mode 100644 index 0000000..8dc471c --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Path.cpp @@ -0,0 +1,396 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; +using namespace Dali::Internal; + +namespace +{ +// Knots fed into Allegro, which generates control points +static void SetupPath( Dali::Path& path) +{ + path.AddPoint(Vector3( 30.0, 80.0, 0.0)); + path.AddPoint(Vector3( 70.0, 120.0, 0.0)); + path.AddPoint(Vector3(100.0, 100.0, 0.0)); + + //Control points for first segment + path.AddControlPoint( Vector3( 39.0, 90.0, 0.0) ); + path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) ); + + //Control points for second segment + path.AddControlPoint(Vector3( 78.0, 120.0, 0.0) ); + path.AddControlPoint(Vector3( 93.0, 104.0, 0.0) ); +} + +} // anonymous namespace + +int utcDaliPathGetPoint(void) +{ + TestApplication application; + + Dali::Path path = Dali::Path::New(); + path.AddPoint(Vector3( 50.0, 50.0, 0.0)); + path.AddPoint(Vector3(120.0, 70.0, 0.0)); + path.AddPoint(Vector3(190.0, 250.0, 0.0)); + path.AddPoint(Vector3(260.0, 260.0, 0.0)); + path.AddPoint(Vector3(330.0, 220.0, 0.0)); + path.AddPoint(Vector3(400.0, 50.0, 0.0)); + + DALI_TEST_EQUALS(path.GetPoint(0), Vector3( 50.0, 50.0, 0.0), TEST_LOCATION); + DALI_TEST_EQUALS(path.GetPoint(1), Vector3(120.0, 70.0, 0.0), TEST_LOCATION); + DALI_TEST_EQUALS(path.GetPoint(2), Vector3(190.0, 250.0, 0.0), TEST_LOCATION); + DALI_TEST_EQUALS(path.GetPoint(3), Vector3(260.0, 260.0, 0.0), TEST_LOCATION); + DALI_TEST_EQUALS(path.GetPoint(4), Vector3(330.0, 220.0, 0.0), TEST_LOCATION); + DALI_TEST_EQUALS(path.GetPoint(5), Vector3(400.0, 50.0, 0.0), TEST_LOCATION); + END_TEST; +} + +int utcDaliPathGetPoint02(void) +{ + TestApplication application; + + Dali::Path path = Dali::Path::New(); + path.AddPoint(Vector3( 50.0, 50.0, 0.0f)); + + try + { + path.GetPoint(1); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "index < mPoint.Size()", TEST_LOCATION); + } + END_TEST; +} + +int utcDaliPathGetPoint03(void) +{ + TestApplication application; + + Dali::Path path = Dali::Path::New(); + + try + { + path.GetPoint(0); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "index < mPoint.Size()", TEST_LOCATION); + } + END_TEST; +} + +int utcDaliPathGetControlPoints(void) +{ + TestApplication application; + + Dali::Path path = Dali::Path::New(); + path.AddControlPoint( Vector3(0.0f, 0.0f, 0.0) ); + path.AddControlPoint( Vector3(108.0f, 57.0f, 0.0) ); + + DALI_TEST_EQUALS(path.GetControlPoint(0), Vector3(0.0f, 0.0f, 0.0f), TEST_LOCATION); + DALI_TEST_EQUALS(path.GetControlPoint(1), Vector3(108.0f, 57.0f, 0.0f), TEST_LOCATION); + END_TEST; +} + +int utcDaliPathGetControlPoints01(void) +{ + TestApplication application; + + Dali::Path path = Dali::Path::New(); + path.AddControlPoint(Vector3(0.0f, 0.0f, 0.0) ); + path.AddControlPoint(Vector3(108.0f, 57.0f, 0.0) ); + + try + { + path.GetControlPoint(5); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "index < mControlPoint.Size()", TEST_LOCATION); + } + END_TEST; +} + +int utcDaliPathGetControlPoints02(void) +{ + TestApplication application; + + Dali::Path path = Dali::Path::New(); + try + { + path.GetControlPoint(0); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "index < mControlPoint.Size()", TEST_LOCATION); + } + END_TEST; +} + +int utcDaliPathGenerateControlPoints01(void) +{ + TestApplication application; + + Dali::Path path = Dali::Path::New(); + + path.AddPoint(Vector3( 50.0, 50.0, 0.0)); + path.AddPoint(Vector3(120.0, 70.0, 0.0)); + path.AddPoint(Vector3(190.0, 250.0, 0.0)); + path.AddPoint(Vector3(260.0, 260.0, 0.0)); + path.AddPoint(Vector3(330.0, 220.0, 0.0)); + path.AddPoint(Vector3(400.0, 50.0, 0.0)); + + path.GenerateControlPoints(0.25); + + DALI_TEST_EQUALS(path.GetControlPoint(0), Vector3( 68.0, 55.0, 0.0), 1.0, TEST_LOCATION); + DALI_TEST_EQUALS(path.GetControlPoint(1), Vector3(107.0, 58.0, 0.0), 1.0, TEST_LOCATION); + + DALI_TEST_EQUALS(path.GetControlPoint(2), Vector3(156.0, 102.0, 0.0), 1.0, TEST_LOCATION); + DALI_TEST_EQUALS(path.GetControlPoint(3), Vector3(152.0, 220.0, 0.0), 1.0, TEST_LOCATION); + + DALI_TEST_EQUALS(path.GetControlPoint(4), Vector3(204.0, 261.0, 0.0), 1.0, TEST_LOCATION); + DALI_TEST_EQUALS(path.GetControlPoint(5), Vector3(243.0, 263.0, 0.0), 1.0, TEST_LOCATION); + + DALI_TEST_EQUALS(path.GetControlPoint(6), Vector3(280.0, 256.0, 0.0), 1.0, TEST_LOCATION); + DALI_TEST_EQUALS(path.GetControlPoint(7), Vector3(317.0, 235.0, 0.0), 1.0, TEST_LOCATION); + + DALI_TEST_EQUALS(path.GetControlPoint(8), Vector3(360.0, 185.0, 0.0), 1.0, TEST_LOCATION); + DALI_TEST_EQUALS(path.GetControlPoint(9), Vector3(383.0, 93.0, 0.0), 1.0, TEST_LOCATION); + + END_TEST; +} + +int utcDaliPathGetPointCount(void) +{ + TestApplication application; + Dali::Path path = Dali::Path::New(); + + DALI_TEST_EQUALS(path.GetPointCount(), 0u, TEST_LOCATION); + + path.AddPoint(Vector3( 50.0, 50.0, 0.0)); + path.AddPoint(Vector3(120.0, 70.0, 0.0)); + path.AddPoint(Vector3(190.0, 250.0, 0.0)); + path.AddPoint(Vector3(260.0, 260.0, 0.0)); + + DALI_TEST_EQUALS(path.GetPointCount(), 4u, TEST_LOCATION); + + path.AddPoint(Vector3(330.0, 220.0, 0.0)); + path.AddPoint(Vector3(400.0, 50.0, 0.0)); + + DALI_TEST_EQUALS(path.GetPointCount(), 6u, TEST_LOCATION); + END_TEST; +} + +int utcDaliPathGenerateControlPoints02(void) +{ + TestApplication application; + + Dali::Path path = Dali::Path::New(); + try + { + path.GenerateControlPoints(0.25); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "numSegments > 0", TEST_LOCATION); + } + END_TEST; +} + +int utcDaliPathGenerateControlPoints03(void) +{ + TestApplication application; + + Dali::Path path = Dali::Path::New(); + path.AddPoint(Vector3(400.0, 50.0, 0.0f)); + try + { + path.GenerateControlPoints(0.25); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "numSegments > 0", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliPathSample01(void) +{ + TestApplication application; + Dali::Path path = Dali::Path::New(); + SetupPath(path); + + //t = 0 + Vector3 position, tangent; + path.Sample(0.0f, position, tangent ); + DALI_TEST_EQUALS(position.x, 30.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 80.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 0.6f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, 0.7f, 0.1f, TEST_LOCATION); + + //t = 0.25 + path.Sample(0.25f, position, tangent ); + DALI_TEST_EQUALS(position.x, 48.0f, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 102.0f, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 0.6f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, 0.7f, 0.1f, TEST_LOCATION); + + // t = 0.5 + path.Sample(0.5f, position, tangent ); + DALI_TEST_EQUALS(position.x, 70.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 120.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 1.0f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, 0.0f, 0.1f, TEST_LOCATION); + + + //t = 0.75 + path.Sample(0.75f, position, tangent ); + DALI_TEST_EQUALS(position.x, 85.0f, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 112.0f, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 0.7f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, -0.6f, 0.1f, TEST_LOCATION); + + // t = 1 + path.Sample(1.0f, position, tangent ); + DALI_TEST_EQUALS(position.x, 100.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 100.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 0.8f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, -0.4f, 0.1f, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliPathDownCast(void) +{ + TestApplication application; + + Dali::Path path = Dali::Path::New(); + Handle handle = path; + SetupPath(path); + + Dali::Path path2 = Dali::Path::DownCast(handle); + DALI_TEST_CHECK(path2); + + //t = 0 + Vector3 position, tangent; + path2.Sample(0.0f, position, tangent ); + DALI_TEST_EQUALS(position.x, 30.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 80.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 0.6f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, 0.7f, 0.1f, TEST_LOCATION); + + //t = 0.25 + path2.Sample(0.25f, position, tangent ); + DALI_TEST_EQUALS(position.x, 48.0f, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 102.0f, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 0.6f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, 0.7f, 0.1f, TEST_LOCATION); + + // t = 0.5 + path2.Sample(0.5f, position, tangent ); + DALI_TEST_EQUALS(position.x, 70.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 120.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 1.0f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, 0.0f, 0.1f, TEST_LOCATION); + + + //t = 0.75 + path2.Sample(0.75f, position, tangent ); + DALI_TEST_EQUALS(position.x, 85.0f, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 112.0f, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 0.7f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, -0.6f, 0.1f, TEST_LOCATION); + + // t = 1 + path2.Sample(1.0f, position, tangent ); + DALI_TEST_EQUALS(position.x, 100.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 100.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 0.8f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, -0.4f, 0.1f, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliPathAssignment(void) +{ + TestApplication application; + + Dali::Path path = Dali::Path::New(); + SetupPath(path); + + Dali::Path path2; + path2 = path; + DALI_TEST_CHECK(path2); + + //t = 0 + Vector3 position, tangent; + path2.Sample(0.0f, position, tangent ); + DALI_TEST_EQUALS(position.x, 30.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 80.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 0.6f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, 0.7f, 0.1f, TEST_LOCATION); + + //t = 0.25 + path2.Sample(0.25f, position, tangent ); + DALI_TEST_EQUALS(position.x, 48.0f, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 102.0f, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 0.6f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, 0.7f, 0.1f, TEST_LOCATION); + + // t = 0.5 + path2.Sample(0.5f, position, tangent ); + DALI_TEST_EQUALS(position.x, 70.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 120.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 1.0f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, 0.0f, 0.1f, TEST_LOCATION); + + + //t = 0.75 + path2.Sample(0.75f, position, tangent ); + DALI_TEST_EQUALS(position.x, 85.0f, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 112.0f, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 0.7f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, -0.6f, 0.1f, TEST_LOCATION); + + // t = 1 + path2.Sample(1.0f, position, tangent ); + DALI_TEST_EQUALS(position.x, 100.0f, TEST_LOCATION); + DALI_TEST_EQUALS(position.y, 100.0f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.x, 0.8f, 0.1f, TEST_LOCATION); + DALI_TEST_EQUALS(tangent.y, -0.4f, 0.1f, TEST_LOCATION); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-PinchGesture.cpp b/automated-tests/src/dali/utc-Dali-PinchGesture.cpp new file mode 100644 index 0000000..3058f1f --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-PinchGesture.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_pinch_gesture_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_pinch_gesture_cleanup(void) +{ + test_return_value = TET_PASS; +} + +// Positive test case for a method +int UtcDaliPinchGestureConstructor(void) +{ + TestApplication application; // Reset all test adapter return codes + + PinchGesture gesture(Gesture::Started); + DALI_TEST_EQUALS(Gesture::Started, gesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, gesture.scale, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, gesture.speed, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pinch, gesture.type, TEST_LOCATION); + + PinchGesture gesture2(Gesture::Continuing); + DALI_TEST_EQUALS(Gesture::Continuing, gesture2.state, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, gesture2.scale, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, gesture2.speed, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pinch, gesture2.type, TEST_LOCATION); + + PinchGesture gesture3(Gesture::Finished); + DALI_TEST_EQUALS(Gesture::Finished, gesture3.state, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, gesture3.scale, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, gesture3.speed, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pinch, gesture3.type, TEST_LOCATION); + + // Test copy constructor + gesture3.scale = 3.0f; + gesture3.speed = 5.0f; + + PinchGesture pinch(gesture3); + DALI_TEST_EQUALS(Gesture::Finished, pinch.state, TEST_LOCATION); + DALI_TEST_EQUALS(3.0f, pinch.scale, TEST_LOCATION); + DALI_TEST_EQUALS(5.0f, pinch.speed, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pinch, pinch.type, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureAssignment(void) +{ + // Test Assignment operator + PinchGesture gesture(Gesture::Started); + DALI_TEST_EQUALS(Gesture::Started, gesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, gesture.scale, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, gesture.speed, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pinch, gesture.type, TEST_LOCATION); + + PinchGesture gesture2(Gesture::Continuing); + DALI_TEST_EQUALS(Gesture::Continuing, gesture2.state, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, gesture2.scale, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, gesture2.speed, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pinch, gesture2.type, TEST_LOCATION); + + gesture2.scale = 3.0f; + gesture2.speed = 5.0f; + + gesture = gesture2; + DALI_TEST_EQUALS(Gesture::Continuing, gesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(3.0f, gesture.scale, TEST_LOCATION); + DALI_TEST_EQUALS(5.0f, gesture.speed, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pinch, gesture.type, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureDynamicAllocation(void) +{ + PinchGesture* gesture = new PinchGesture( Gesture::Started ); + DALI_TEST_EQUALS(Gesture::Started, gesture->state, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, gesture->scale, TEST_LOCATION); + DALI_TEST_EQUALS(0.0f, gesture->speed, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Pinch, gesture->type, TEST_LOCATION); + delete gesture; + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp new file mode 100644 index 0000000..5fb8b27 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp @@ -0,0 +1,1379 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; + +void utc_dali_pinch_gesture_detector_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_pinch_gesture_detector_cleanup(void) +{ + test_return_value = TET_PASS; +} + +/////////////////////////////////////////////////////////////////////////////// +namespace +{ + +// Stores data that is populated in the callback and will be read by the TET cases +struct SignalData +{ + SignalData() + : functorCalled(false), + voidFunctorCalled(false), + receivedGesture(Gesture::Started) + {} + + void Reset() + { + functorCalled = false; + voidFunctorCalled = false; + + receivedGesture.state = Gesture::Started; + receivedGesture.scale = 0.0f; + receivedGesture.speed = 0.0f; + receivedGesture.screenCenterPoint = Vector2(0.0f, 0.0f); + receivedGesture.localCenterPoint = Vector2(0.0f, 0.0f); + + pinchedActor.Reset(); + } + + bool functorCalled; + bool voidFunctorCalled; + PinchGesture receivedGesture; + Actor pinchedActor; +}; + +// Functor that sets the data when called +struct GestureReceivedFunctor +{ + GestureReceivedFunctor(SignalData& data) : signalData(data) { } + + void operator()(Actor actor, const PinchGesture& pinch) + { + signalData.functorCalled = true; + signalData.receivedGesture = pinch; + signalData.pinchedActor = actor; + } + + void operator()() + { + signalData.voidFunctorCalled = true; + } + + SignalData& signalData; +}; + +// Functor that removes the gestured actor from stage +struct UnstageActorFunctor : public GestureReceivedFunctor +{ + UnstageActorFunctor( SignalData& data, Gesture::State& stateToUnstage ) + : GestureReceivedFunctor( data ), + stateToUnstage( stateToUnstage ) + { + } + + void operator()( Actor actor, const PinchGesture& pinch ) + { + GestureReceivedFunctor::operator()( actor, pinch ); + + if ( pinch.state == stateToUnstage ) + { + Stage::GetCurrent().Remove( actor ); + } + } + + Gesture::State& stateToUnstage; +}; + +// Functor for receiving a touch event +struct TouchEventFunctor +{ + bool operator()(Actor actor, const TouchEvent& touch) + { + return false; + } +}; + +// Generate a PinchGestureEvent to send to Core +Integration::PinchGestureEvent GeneratePinch( + Gesture::State state, + float scale, + float speed, + Vector2 centerpoint) +{ + Integration::PinchGestureEvent pinch(state); + + pinch.scale = scale; + pinch.speed = speed; + pinch.centerPoint = centerpoint; + + return pinch; +} + +} // anon namespace + +/////////////////////////////////////////////////////////////////////////////// + +int UtcDaliPinchGestureDetectorConstructor(void) +{ + TestApplication application; + + PinchGestureDetector detector; + DALI_TEST_CHECK(!detector); + END_TEST; +} + +int UtcDaliPinchGestureDetectorCopyConstructorP(void) +{ + TestApplication application; + + PinchGestureDetector detector = PinchGestureDetector::New();; + + PinchGestureDetector copy( detector ); + DALI_TEST_CHECK( detector ); + END_TEST; +} + +int UtcDaliPinchGestureDetectorAssignmentOperatorP(void) +{ + TestApplication application; + + PinchGestureDetector detector = PinchGestureDetector::New();; + + PinchGestureDetector assign; + assign = detector; + DALI_TEST_CHECK( detector ); + + DALI_TEST_CHECK( detector == assign ); + END_TEST; +} + +int UtcDaliPinchGestureDetectorNew(void) +{ + TestApplication application; + + PinchGestureDetector detector = PinchGestureDetector::New(); + + DALI_TEST_CHECK(detector); + + // Attach an actor and emit a touch event on the actor to ensure complete line coverage + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + detector.Attach(actor); + + Integration::TouchEvent touchEvent(1); + TouchPoint point(1, TouchPoint::Down, 20.0f, 20.0f); + touchEvent.AddPoint(point); + application.ProcessEvent(touchEvent); + + TouchPoint point2(1, TouchPoint::Down, 20.0f, 20.0f, 20.0f, 20.0f); + touchEvent.AddPoint(point2); + application.ProcessEvent(touchEvent); + END_TEST; +} + +int UtcDaliPinchGestureDetectorDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::PinchGestureDetector::DownCast()"); + + PinchGestureDetector detector = PinchGestureDetector::New(); + + BaseHandle object(detector); + + PinchGestureDetector detector2 = PinchGestureDetector::DownCast(object); + DALI_TEST_CHECK(detector2); + + PinchGestureDetector detector3 = DownCast< PinchGestureDetector >(object); + DALI_TEST_CHECK(detector3); + + BaseHandle unInitializedObject; + PinchGestureDetector detector4 = PinchGestureDetector::DownCast(unInitializedObject); + DALI_TEST_CHECK(!detector4); + + PinchGestureDetector detector5 = DownCast< PinchGestureDetector >(unInitializedObject); + DALI_TEST_CHECK(!detector5); + + GestureDetector detector6 = PinchGestureDetector::New(); + PinchGestureDetector detector7 = PinchGestureDetector::DownCast(detector6); + DALI_TEST_CHECK(detector7); + END_TEST; +} + +// Negative test case for a method +int UtcDaliPinchGestureSignalReceptionNegative(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Do a pinch outside actor's area + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 45.0f, Vector2(112.0f, 112.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Continue pinch into actor's area - we should still not receive the signal + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 4.5f, 95.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Stop pinching - we should still not receive the signal + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(12.0f, 12.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionDownMotionLeave(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start pan within the actor's area + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(10.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(20.0f, 20.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION); + + // Continue the pan within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 90.0f, Vector2(21.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(5.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(90.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(21.0f, 20.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION); + + // Pan Gesture leaves actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 15.5f, Vector2(320.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(10.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(15.5f, data.receivedGesture.speed, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(320.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION); + + // Gesture ends - we would receive a finished state + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 15.2f, 12.1f, Vector2(310.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(15.2f, data.receivedGesture.scale, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(12.1f, data.receivedGesture.speed, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(310.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionDownMotionUp(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start pinch within the actor's area + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(10.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(20.0f, 20.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION); + + // Continue the pinch within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 25.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(5.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(25.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(20.0f, 20.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION); + + // Gesture ends within actor's area - we would receive a finished state + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 25.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION); + DALI_TEST_EQUALS(5.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(25.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(20.0f, 20.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionCancelled(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start pinch within the actor's area + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION); + + + // Continue the pinch within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 25.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION); + + // The gesture is cancelled + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Cancelled, 5.0f, 25.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Cancelled, data.receivedGesture.state, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionDetach(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start pinch within the actor's area + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION); + + + // Continue the pinch within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 25.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION); + + // Gesture ends within actor's area + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 25.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION); + + // Detach actor + detector.DetachAll(); + + // Ensure we are no longer signalled + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 20.0f))); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 25.0f, Vector2(20.0f, 20.0f))); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 25.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionDetachWhilePinching(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start pinch within the actor's area + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION); + + // Continue the pinch within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 25.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION); + + // Detach actor during the pinch, we should not receive the next event + detector.DetachAll(); + + // Gesture ends within actor's area + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 25.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionActorDestroyedWhilePinching(void) +{ + TestApplication application; + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.DetectedSignal().Connect(&application, functor); + + // Attach a temporary actor to stop detector being removed from PinchGestureProcessor when main actor + // is destroyed. + Actor tempActor = Actor::New(); + tempActor.SetSize(100.0f, 100.0f); + tempActor.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT); + Stage::GetCurrent().Add(tempActor); + detector.Attach(tempActor); + + // Actor lifetime is scoped + { + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + detector.Attach(actor); + + // Start pinch within the actor's area + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION); + + // Continue the pinch within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 25.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION); + + // Remove the actor from stage and reset the data + Stage::GetCurrent().Remove(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + } + + // Actor should now have been destroyed + + // Gesture ends within the area where the actor used to be + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 25.0f, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionRotatedActor(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS); + Stage::GetCurrent().Add(actor); + + // Render and notify a couple of times + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Do an entire pinch, only check finished value + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f))); + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(10.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(10.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(10.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION); + + // Rotate actor again and render and notify + actor.SetOrientation(Dali::Degree(180.0f), Vector3::ZAXIS); + application.SendNotification(); + application.Render(); + + // Do an entire pinch, only check finished value + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f))); + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(10.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(10.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(10.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION); + + // Rotate actor again and render and notify + actor.SetOrientation(Dali::Degree(270.0f), Vector3::ZAXIS); + application.SendNotification(); + application.Render(); + + // Do an entire pinch, only check finished value + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f))); + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(10.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(10.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(10.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionChildHit(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + parent.SetSize(100.0f, 100.0f); + parent.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(parent); + + // Set child to completely cover parent. + // Change rotation of child to be different from parent so that we can check if our local coordinate + // conversion of the parent actor is correct. + Actor child = Actor::New(); + child.SetSize(100.0f, 100.0f); + child.SetAnchorPoint(AnchorPoint::CENTER); + child.SetParentOrigin(ParentOrigin::CENTER); + child.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS); + parent.Add(child); + + TouchEventFunctor touchFunctor; + child.TouchedSignal().Connect(&application, touchFunctor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(parent); + detector.DetectedSignal().Connect(&application, functor); + + // Do an entire pan, only check finished value - hits child area but parent should still receive it + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f))); + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 50.0f, Vector2(10.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, parent == data.pinchedActor, TEST_LOCATION); + DALI_TEST_EQUALS(5.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(10.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION); + + // Attach child and generate same touch points to yield same results + // (Also proves that you can detach and then re-attach another actor) + detector.Attach(child); + detector.Detach(parent); + + // Do an entire pan, only check finished value + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f))); + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 50.0f, Vector2(10.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, child == data.pinchedActor, TEST_LOCATION); + DALI_TEST_EQUALS(5.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(10.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionAttachDetachMany(void) +{ + TestApplication application; + + Actor first = Actor::New(); + first.SetSize(100.0f, 100.0f); + first.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(first); + + Actor second = Actor::New(); + second.SetSize(100.0f, 100.0f); + second.SetX(100.0f); + second.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(second); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(first); + detector.Attach(second); + detector.DetectedSignal().Connect(&application, functor); + + // Start pinch within second actor's area + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(120.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, second == data.pinchedActor, TEST_LOCATION); + + // Pinch moves into first actor's area - second actor should receive the pinch + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(10.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, second == data.pinchedActor, TEST_LOCATION); + + // Detach the second actor during the pinch, we should not receive the next event + detector.Detach(second); + + // Gesture ends within actor's area + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(120.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionActorBecomesUntouchable(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start pinch in actor's area + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Pan continues within actor's area + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Started, 5.0f, 50.0f, Vector2(10.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Actor become invisible - actor should not receive the next pinch + actor.SetVisible(false); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Gesture ends within actor's area + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 50.0f, Vector2(10.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionMultipleDetectorsOnActor(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + Actor actor2 = Actor::New(); + actor2.SetSize(100.0f, 100.0f); + actor2.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT); + Stage::GetCurrent().Add(actor2); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to one detector + SignalData firstData; + GestureReceivedFunctor firstFunctor(firstData); + PinchGestureDetector firstDetector = PinchGestureDetector::New(); + firstDetector.Attach(actor); + firstDetector.DetectedSignal().Connect(&application, firstFunctor); + + // Attach actor to another detector + SignalData secondData; + GestureReceivedFunctor secondFunctor(secondData); + PinchGestureDetector secondDetector = PinchGestureDetector::New(); + secondDetector.Attach(actor); + secondDetector.DetectedSignal().Connect(&application, secondFunctor); + + // Add second actor to second detector, when we remove the actor, this will make sure that this + // gesture detector is not removed from the GestureDetectorProcessor. In this scenario, the + // functor should still not be called (which is what we're also testing). + secondDetector.Attach(actor2); + + // Pinch in actor's area - both detector's functors should be called + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION); + + // Pinch continues in actor's area - both detector's functors should be called + firstData.Reset(); + secondData.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION); + + // Detach actor from firstDetector and emit pinch on actor, only secondDetector's functor should be called. + firstDetector.Detach(actor); + firstData.Reset(); + secondData.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(false, firstData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION); + + // New pinch on actor, only secondDetector has actor attached + firstData.Reset(); + secondData.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(false, firstData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION); + + // Detach actor from secondDetector + secondDetector.Detach(actor); + firstData.Reset(); + secondData.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(false, firstData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(false, secondData.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionMultipleStarted(void) +{ + // Should handle two started events gracefully. + + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Start pan in actor's area + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Send another start in actor's area + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Add a child actor to overlap actor and send another start in actor's area + Actor child = Actor::New(); + child.SetSize(100.0f, 100.0f); + child.SetAnchorPoint(AnchorPoint::CENTER); + child.SetParentOrigin(ParentOrigin::CENTER); + actor.Add(child); + + TouchEventFunctor touchFunctor; + child.TouchedSignal().Connect(&application, touchFunctor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Send another start in actor's area + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Send another start in actor's area + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSignalReceptionEnsureCorrectSignalling(void) +{ + TestApplication application; + + Actor actor1 = Actor::New(); + actor1.SetSize(100.0f, 100.0f); + actor1.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor1); + SignalData data1; + GestureReceivedFunctor functor1(data1); + PinchGestureDetector detector1 = PinchGestureDetector::New(); + detector1.Attach(actor1); + detector1.DetectedSignal().Connect(&application, functor1); + + Actor actor2 = Actor::New(); + actor2.SetSize(100.0f, 100.0f); + actor2.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT); + actor2.SetParentOrigin(ParentOrigin::BOTTOM_RIGHT); + Stage::GetCurrent().Add(actor2); + SignalData data2; + GestureReceivedFunctor functor2(data2); + PinchGestureDetector detector2 = PinchGestureDetector::New(); + detector2.Attach(actor2); + detector2.DetectedSignal().Connect(&application, functor2); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Start pan in actor1's area, only data1 should be set + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data1.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(false, data2.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureEmitIncorrectStateClear(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Try a Clear state + try + { + application.ProcessEvent(GeneratePinch(Gesture::Clear, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + tet_result(TET_FAIL); + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_ASSERT( e, "false", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliPinchGestureEmitIncorrectStatePossible(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Try a Possible state + try + { + application.ProcessEvent(GeneratePinch(Gesture::Possible, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + tet_result(TET_FAIL); + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_ASSERT( e, "false", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliPinchGestureActorUnstaged(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // State to remove actor in. + Gesture::State stateToUnstage( Gesture::Started ); + + // Attach actor to detector + SignalData data; + UnstageActorFunctor functor( data, stateToUnstage ); + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Emit signals + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Re-add actor to stage + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Change state to Gesture::Continuing to remove + stateToUnstage = Gesture::Continuing; + + // Emit signals + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Re-add actor to stage + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Change state to Gesture::Continuing to remove + stateToUnstage = Gesture::Finished; + + // Emit signals + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + tet_result( TET_PASS ); // If we get here then we have handled actor stage removal gracefully. + END_TEST; +} + +int UtcDaliPinchGestureActorStagedAndDestroyed(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Create and add a second actor so that GestureDetector destruction does not come into play. + Actor dummyActor( Actor::New() ); + dummyActor.SetSize( 100.0f, 100.0f ); + dummyActor.SetPosition( 100.0f, 100.0f ); + dummyActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(dummyActor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // State to remove actor in. + Gesture::State stateToUnstage( Gesture::Started ); + + // Attach actor to detector + SignalData data; + UnstageActorFunctor functor( data, stateToUnstage ); + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.Attach(dummyActor); + detector.DetectedSignal().Connect( &application, functor ); + + // Here we are testing a Started actor which is removed in the Started callback, but then added back + // before we get a continuing state. As we were removed from the stage, even if we're at the same + // position, we should still not be signalled. + + // Emit signals + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Re add to the stage, we should not be signalled + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Continue signal emission + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Here we delete an actor in started, we should not receive any subsequent signalling. + + // Emit signals + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Delete actor as well + actor.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Continue signal emission + application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureSystemOverlay(void) +{ + TestApplication application; + Dali::Integration::Core& core = application.GetCore(); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + Vector2 screenCoords( 50.0f, 50.0f ); + float scale ( 10.0f ); + float speed ( 50.0f ); + + // Start pan within the actor's area + application.ProcessEvent( GeneratePinch( Gesture::Started, scale, speed, screenCoords ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPinchGestureBehindTouchableSystemOverlay(void) +{ + TestApplication application; + Dali::Integration::Core& core = application.GetCore(); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + // SystemOverlay actor + Actor systemOverlayActor = Actor::New(); + systemOverlayActor.SetSize(100.0f, 100.0f); + systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add(systemOverlayActor); + + // Stage actor + Actor stageActor = Actor::New(); + stageActor.SetSize(100.0f, 100.0f); + stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(stageActor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set system-overlay actor to touchable + TouchEventData touchData; + TouchEventDataFunctor touchFunctor( touchData ); + systemOverlayActor.TouchedSignal().Connect(&application, touchFunctor); + + // Set stage actor to receive the gesture + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(stageActor); + detector.DetectedSignal().Connect(&application, functor); + + Vector2 screenCoords( 50.0f, 50.0f ); + float scale ( 10.0f ); + float speed ( 50.0f ); + + // Start pinch within the two actors' area + application.ProcessEvent( GeneratePinch( Gesture::Started, scale, speed, screenCoords ) ); + application.ProcessEvent( GeneratePinch( Gesture::Finished, scale, speed, screenCoords ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION ); + + data.Reset(); + touchData.Reset(); + + // Do touch in the same area + application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoords ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPinchGestureTouchBehindGesturedSystemOverlay(void) +{ + TestApplication application; + Dali::Integration::Core& core = application.GetCore(); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + // SystemOverlay actor + Actor systemOverlayActor = Actor::New(); + systemOverlayActor.SetSize(100.0f, 100.0f); + systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add(systemOverlayActor); + + // Stage actor + Actor stageActor = Actor::New(); + stageActor.SetSize(100.0f, 100.0f); + stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(stageActor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set stage actor to touchable + TouchEventData touchData; + TouchEventDataFunctor touchFunctor( touchData ); + stageActor.TouchedSignal().Connect(&application, touchFunctor); + + // Set system-overlay actor to have the gesture + SignalData data; + GestureReceivedFunctor functor(data); + + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(systemOverlayActor); + detector.DetectedSignal().Connect(&application, functor); + + Vector2 screenCoords( 50.0f, 50.0f ); + float scale ( 10.0f ); + float speed ( 50.0f ); + + // Start pinch within the two actors' area + application.ProcessEvent( GeneratePinch( Gesture::Started, scale, speed, screenCoords ) ); + application.ProcessEvent( GeneratePinch( Gesture::Finished, scale, speed, screenCoords ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION ); + + data.Reset(); + touchData.Reset(); + + // Do touch in the same area + application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoords ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPinchGestureLayerConsumesTouch(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Add a detector + SignalData data; + GestureReceivedFunctor functor(data); + PinchGestureDetector detector = PinchGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Add a layer to overlap the actor + Layer layer = Layer::New(); + layer.SetSize(100.0f, 100.0f); + layer.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add( layer ); + layer.RaiseToTop(); + + // Render and notify + application.SendNotification(); + application.Render(); + + Vector2 screenCoords( 50.0f, 50.0f ); + float scale ( 10.0f ); + float speed ( 50.0f ); + + // Emit signals, should receive + application.ProcessEvent( GeneratePinch( Gesture::Started, scale, speed, screenCoords ) ); + application.ProcessEvent( GeneratePinch( Gesture::Finished, scale, speed, screenCoords ) ); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Set layer to consume all touch + layer.SetTouchConsumed( true ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit the same signals again, should not receive + application.ProcessEvent( GeneratePinch( Gesture::Started, scale, speed, screenCoords ) ); + application.ProcessEvent( GeneratePinch( Gesture::Finished, scale, speed, screenCoords ) ); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Pixel.cpp b/automated-tests/src/dali/utc-Dali-Pixel.cpp new file mode 100644 index 0000000..78a3436 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Pixel.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include + +using std::max; +using namespace Dali; + + +static const float ROTATION_EPSILON = 0.0001f; + +void utc_dali_pixel_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_pixel_cleanup(void) +{ + test_return_value = TET_PASS; +} + +static void TestPixelEnumSize(const int size) +{ + DALI_TEST_CHECK( (static_cast( Pixel::LAST_VALID_PIXEL_FORMAT ) - static_cast( Pixel::FIRST_VALID_PIXEL_FORMAT ) + 1 ) == size && + "The Pixel::Format enum may have had new formats added. Expand the test cases to include them."); +} + +int UtcDaliPixelHasAlpha(void) +{ + TestApplication application; + + tet_infoline("UtcDaliPixelHasAlpha"); + + TestPixelEnumSize( 26 ); + + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::L8) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::RGB565) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::RGB888) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::RGB8888) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::BGR8888) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::BGR565) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_R11_EAC) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_SIGNED_R11_EAC) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_RG11_EAC) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_SIGNED_RG11_EAC) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_RGB8_ETC2) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_SRGB8_ETC2) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_RGB8_ETC1) == false); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_RGB_PVRTC_4BPPV1) == false); + + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::A8) == true); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::LA88) == true); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::RGBA5551) == true); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::RGBA4444) == true); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::RGBA8888) == true); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::BGRA8888) == true); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::BGRA5551) == true); + DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::BGRA4444) == true); + DALI_TEST_CHECK( Pixel::HasAlpha( Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 ) == true ); + DALI_TEST_CHECK( Pixel::HasAlpha( Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 ) == true ); + DALI_TEST_CHECK( Pixel::HasAlpha( Pixel::COMPRESSED_RGBA8_ETC2_EAC ) == true ); + DALI_TEST_CHECK( Pixel::HasAlpha( Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) == true ); + + END_TEST; +} + +int UtcDaliPixelHasAlphaN(void) +{ + DALI_TEST_EQUALS( Pixel::HasAlpha( Pixel::Format( 123123123123 ) ), false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPixelGetBytesPerPixel(void) +{ + TestApplication application; + + tet_infoline("UtcDaliPixelGetBytesPerPixel"); + + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::L8) == 1); + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::A8) == 1); + + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::LA88) == 2); + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::RGB565) == 2); + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::RGBA5551) == 2); + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::RGBA4444) == 2); + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::BGR565) == 2); + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::BGRA5551) == 2); + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::BGRA4444) == 2); + + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::RGB888) == 3); + + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::RGB8888) == 4); + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::BGR8888) == 4); + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::RGBA8888) == 4); + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::BGRA8888) == 4); + + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::L8) == 1); + + DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::COMPRESSED_R11_EAC) == 0); + + END_TEST; +} + +int UtcDaliPixelGetBytesPerPixelN(void) +{ + DALI_TEST_EQUALS( Pixel::GetBytesPerPixel( Pixel::Format( 123123123123 ) ), 0u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPixelGetAlphaOffsetAndMask(void) +{ + TestApplication application; + + tet_infoline("UtcDaliPixelGetAlphaOffsetAndMask"); + + int byteOffset = 0; + int bitMask = 0; + + // Be sure that the number of cases tested below is correct: + TestPixelEnumSize( 26 ); + + Pixel::GetAlphaOffsetAndMask(Pixel::L8, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::A8, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0xff); + Pixel::GetAlphaOffsetAndMask(Pixel::RGB888, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::RGB565, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::RGB8888, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::BGR8888, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::LA88, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 1 && bitMask == 0xff); + Pixel::GetAlphaOffsetAndMask(Pixel::RGBA4444, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 1 && bitMask == 0x0f); + Pixel::GetAlphaOffsetAndMask(Pixel::RGBA5551, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 1 && bitMask == 0x01); + Pixel::GetAlphaOffsetAndMask(Pixel::RGBA8888, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 3 && bitMask == 0xff); + Pixel::GetAlphaOffsetAndMask(Pixel::BGRA8888, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 3 && bitMask == 0xff); + Pixel::GetAlphaOffsetAndMask(Pixel::BGR565, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::BGRA4444, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 1 && bitMask == 0x0f); + Pixel::GetAlphaOffsetAndMask(Pixel::BGRA5551, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 1 && bitMask == 0x01); + + // Compressed formats with no meaningful result: + Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_R11_EAC, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_SIGNED_R11_EAC, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_RG11_EAC, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_SIGNED_RG11_EAC, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_RGB8_ETC2, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_SRGB8_ETC2, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_RGB8_ETC1, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_RGB_PVRTC_4BPPV1, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_RGBA8_ETC2_EAC, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, byteOffset, bitMask); + DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0); + END_TEST; +} + +int UtcDaliPixelGetAlphaOffsetAndMaskN(void) +{ + int byteOffset = 200; + int bitMask = 200; + Pixel::GetAlphaOffsetAndMask( Pixel::Format( 123123123123 ), byteOffset, bitMask ); + DALI_TEST_CHECK( byteOffset == 200 ); + DALI_TEST_CHECK( bitMask == 200 ); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-PropertyArray.cpp b/automated-tests/src/dali/utc-Dali-PropertyArray.cpp new file mode 100644 index 0000000..f55004b --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-PropertyArray.cpp @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_property_array_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_property_array_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliPropertyArrayPushBackP(void) +{ + Property::Array array; + + DALI_TEST_CHECK( 0 == array.Size() ); + + array.PushBack( 1 ); + + DALI_TEST_CHECK( 1 == array.Size() ); + + DALI_TEST_CHECK( array[0].Get() == 1 ); + + END_TEST; +} + +int UtcDaliPropertyArrayCapacityP(void) +{ + Property::Array array; + DALI_TEST_CHECK( array.Empty() ); + + array.Reserve(3); + + DALI_TEST_CHECK( 3 == array.Capacity() ); + END_TEST; +} + +int UtcDaliPropertyArrayReserveP(void) +{ + Property::Array array; + DALI_TEST_CHECK( array.Empty() ); + + array.Reserve(3); + + DALI_TEST_CHECK( 3 == array.Capacity() ); + DALI_TEST_CHECK( 0 == array.Size() ); + + array.PushBack( 1 ); + array.PushBack( "world" ); + array.PushBack( 3 ); + END_TEST; +} + +int UtcDaliPropertyArraySizeP(void) +{ + Property::Array array; + DALI_TEST_CHECK( 0 == array.Capacity() ); + DALI_TEST_CHECK( 0 == array.Size() ); + + array.Reserve(3); + + DALI_TEST_CHECK( 3 == array.Capacity() ); + DALI_TEST_CHECK( 0 == array.Size() ); + + array.PushBack( 1 ); + array.PushBack( "world" ); + array.PushBack( 3 ); + + DALI_TEST_CHECK( 3 == array.Size() ); + + END_TEST; +} + +int UtcDaliPropertyArrayCountP(void) +{ + Property::Array array; + DALI_TEST_CHECK( 0 == array.Capacity() ); + DALI_TEST_CHECK( 0 == array.Count() ); + + array.Reserve(3); + + DALI_TEST_CHECK( 3 == array.Capacity() ); + DALI_TEST_CHECK( 0 == array.Count() ); + + array.PushBack( 1 ); + array.PushBack( "world" ); + array.PushBack( 3 ); + + DALI_TEST_CHECK( 3 == array.Count() ); + + END_TEST; +} + +int UtcDaliPropertyArrayEmptyP(void) +{ + Property::Array array; + DALI_TEST_CHECK( array.Empty() ); + + array.Reserve(3); + + DALI_TEST_CHECK( array.Empty() ); + + array.PushBack( 1 ); + array.PushBack( "world" ); + array.PushBack( 3 ); + + DALI_TEST_CHECK( !array.Empty() ); + + END_TEST; +} + +int UtcDaliPropertyArrayClearP(void) +{ + Property::Array array; + DALI_TEST_CHECK( array.Empty() ); + + array.Reserve(3); + + DALI_TEST_CHECK( array.Empty() ); + + array.PushBack( 1 ); + array.PushBack( "world" ); + array.PushBack( 3 ); + + DALI_TEST_CHECK( !array.Empty() ); + + array.Clear(); + + DALI_TEST_CHECK( array.Empty() ); + + END_TEST; +} + +int UtcDaliPropertyArrayIndexOperatorP(void) +{ + Property::Array array; + + array.Reserve(3); + array.PushBack( 1 ); + array.PushBack( "world" ); + array.PushBack( 3 ); + + DALI_TEST_CHECK( array[0].Get() == 1 ); + DALI_TEST_CHECK( array[1].Get() == "world" ); + DALI_TEST_CHECK( array[2].Get() == 3 ); + + END_TEST; +} + +int UtcDaliPropertyArrayConstIndexOperatorP(void) +{ + Property::Array anArray; + + anArray.Reserve(3); + anArray.PushBack( 1 ); + anArray.PushBack( "world" ); + anArray.PushBack( 3 ); + + const Property::Array array(anArray); + + DALI_TEST_CHECK( array[0].Get() == 1 ); + DALI_TEST_CHECK( array[1].Get() == "world" ); + DALI_TEST_CHECK( array[2].Get() == 3 ); + + END_TEST; +} + +int UtcDaliPropertyArrayAssignmentOperatorP(void) +{ + Property::Array anArray; + + anArray.Reserve(3); + anArray.PushBack( 1 ); + anArray.PushBack( "world" ); + anArray.PushBack( 3 ); + + Property::Array array = anArray; + + DALI_TEST_CHECK( array[0].Get() == 1 ); + DALI_TEST_CHECK( array[1].Get() == "world" ); + DALI_TEST_CHECK( array[2].Get() == 3 ); + + END_TEST; +} + +int UtcDaliPropertyArrayResize(void) +{ + Property::Array array; + + array.Resize(3); + DALI_TEST_CHECK( array.Count() == 3 ); + + array.Resize(5); + DALI_TEST_CHECK( array.Count() == 5 ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-PropertyMap.cpp b/automated-tests/src/dali/utc-Dali-PropertyMap.cpp new file mode 100644 index 0000000..4867179 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-PropertyMap.cpp @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_property_map_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_property_map_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliPropertyMapPopulate(void) +{ + Property::Map map; + DALI_TEST_CHECK( map.Empty() ); + + map[ "hello" ] = 1; + map[ "world" ] = "world"; + map[ "world" ] = 3; // same item as line above + DALI_TEST_CHECK( !map.Empty() ); // Should no longer be empty + DALI_TEST_CHECK( map.Count() == 2 ); // Should only have two items, not three!! + DALI_TEST_CHECK( map["hello"].Get() == 1 ); + DALI_TEST_CHECK( map["world"].Get() == 3 ); + + map.Clear(); + DALI_TEST_CHECK( map.Empty() ); + END_TEST; +} + +int UtcDaliPropertyMapCopyAndAssignment(void) +{ + Property::Map map; + map[ "hello" ] = 1; + map[ "world" ] = 2; + + Property::Map assignedMap; + assignedMap[ "foo" ] = 3; + DALI_TEST_CHECK( assignedMap.Count() == 1 ); + assignedMap = map; + DALI_TEST_CHECK( assignedMap.Count() == 2 ); + + Property::Map copiedMap( map ); + DALI_TEST_CHECK( copiedMap.Count() == 2 ); + + // Self assignment + DALI_TEST_CHECK( map.Count() == 2 ); + map = map; + DALI_TEST_CHECK( map.Count() == 2 ); + + END_TEST; +} + +int UtcDaliPropertyMapConstOperator(void) +{ + Property::Map map; + map[ "hello" ] = 1; + map[ "world" ] = 2; + DALI_TEST_CHECK( map.Count() == 2 ); + + const Property::Map& constMap( map ); + DALI_TEST_CHECK( constMap[ "world" ].Get() == 2 ); + DALI_TEST_CHECK( constMap.Count() == 2 ); // Ensure count hasn't gone up + + // Invalid Key + try + { + constMap[ "invalid-key" ]; + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "! \"Invalid Key\"", TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliPropertyMapGetValue(void) +{ + Property::Map map; + map[ "hello" ] = 1; + map[ "world" ] = 2; + + Property::Value& value = map.GetValue( 0 ); + DALI_TEST_CHECK( value.Get() == 1 ); + value = 10; // Allows the actual changing of the value as we have a ref + DALI_TEST_CHECK( map[ "hello" ].Get() == 10 ); + + // Out of bounds + try + { + map.GetValue( 2 ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "position", TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliPropertyMapGetKey(void) +{ + Property::Map map; + map[ "hello" ] = 1; + map[ "world" ] = 2; + + DALI_TEST_CHECK( map.GetKey( 0 ) == "hello" ); + DALI_TEST_CHECK( map.GetKey( 1 ) == "world" ); + + // Out of bounds + try + { + map.GetKey( 2 ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "position", TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliPropertyMapGetPair(void) +{ + Property::Map map; + map[ "hello" ] = 1; + map[ "world" ] = 2; + + DALI_TEST_CHECK( map.GetPair( 0 ).first == "hello" ); + DALI_TEST_CHECK( map.GetPair( 0 ).second.Get< int >() == 1 ); + DALI_TEST_CHECK( map.GetPair( 1 ).first == "world" ); + DALI_TEST_CHECK( map.GetPair( 1 ).second.Get< int >() == 2 ); + + // Out of bounds + try + { + map.GetPair( 2 ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "position", TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliPropertyMapFind(void) +{ + Property::Map map; + map[ "hello" ] = 1; + map[ "world" ] = 2; + + Property::Value* value = NULL; + + value = map.Find( "hello" ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( value->Get() == 1 ); + + value = map.Find( "world" ); + DALI_TEST_CHECK( value ); + DALI_TEST_CHECK( value->Get() == 2 ); + + value = map.Find( "invalid-key" ); + DALI_TEST_CHECK( !value ); + + END_TEST; +} + +int UtcDaliPropertyMapInsertP(void) +{ + Property::Map map; + DALI_TEST_EQUALS( 0, map.Count(), TEST_LOCATION ); + map.Insert( "foo", "bar"); + DALI_TEST_EQUALS( 1, map.Count(), TEST_LOCATION ); + Property::Value* value = map.Find( "foo" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( "bar", value->Get(), TEST_LOCATION ); + map.Insert( std::string("foo2"), "testing" ); + DALI_TEST_EQUALS( 2, map.Count(), TEST_LOCATION ); + value = map.Find( "foo2" ); + DALI_TEST_CHECK( value ); + DALI_TEST_EQUALS( "testing", value->Get(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyMapMerge(void) +{ + Property::Map map; + map[ "hello" ] = 1; + map[ "world" ] = 2; + + DALI_TEST_CHECK( map.Count() == 2 ); + + // Create another map with the same keys but different values + Property::Map map2; + map[ "hello" ] = 3; + map[ "world" ] = 4; + + // Merge map2 into map1, count should still be 2, map values should be from map2 + map.Merge( map2 ); + DALI_TEST_CHECK( map.Count() == 2 ); + DALI_TEST_CHECK( map[ "hello" ].Get< int >() == 3 ); + DALI_TEST_CHECK( map[ "world"].Get< int >() == 4 ); + + // Create another map with different keys + Property::Map map3; + map3[ "foo" ] = 5; + map3[ "bar" ] = 6; + + // Merge map3 into map1, count should increase, existing values should match previous and new values should match map3 + map.Merge( map3 ); + DALI_TEST_CHECK( map.Count() == 4 ); + DALI_TEST_CHECK( map[ "hello" ].Get< int >() == 3 ); + DALI_TEST_CHECK( map[ "world"].Get< int >() == 4 ); + DALI_TEST_CHECK( map[ "foo"].Get< int >() == 5 ); + DALI_TEST_CHECK( map[ "bar"].Get< int >() == 6 ); + + // Create an empty map and attempt to merge, should be successful, nothing should change + Property::Map map4; + DALI_TEST_CHECK( map4.Empty() ); + map.Merge( map4 ); + DALI_TEST_CHECK( map4.Empty() ); + DALI_TEST_CHECK( map.Count() == 4 ); + DALI_TEST_CHECK( map[ "hello" ].Get< int >() == 3 ); + DALI_TEST_CHECK( map[ "world"].Get< int >() == 4 ); + DALI_TEST_CHECK( map[ "foo"].Get< int >() == 5 ); + DALI_TEST_CHECK( map[ "bar"].Get< int >() == 6 ); + + // Merge map into map4, map4 should be the same as map now. + map4.Merge( map ); + DALI_TEST_CHECK( map4.Count() == 4 ); + DALI_TEST_CHECK( map4[ "hello" ].Get< int >() == 3 ); + DALI_TEST_CHECK( map4[ "world"].Get< int >() == 4 ); + DALI_TEST_CHECK( map4[ "foo"].Get< int >() == 5 ); + DALI_TEST_CHECK( map4[ "bar"].Get< int >() == 6 ); + + // Attempt to merge into itself, should be successful, nothing should change + map.Merge( map ); + DALI_TEST_CHECK( map.Count() == 4 ); + DALI_TEST_CHECK( map[ "hello" ].Get< int >() == 3 ); + DALI_TEST_CHECK( map[ "world"].Get< int >() == 4 ); + DALI_TEST_CHECK( map[ "foo"].Get< int >() == 5 ); + DALI_TEST_CHECK( map[ "bar"].Get< int >() == 6 ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-PropertyNotification.cpp b/automated-tests/src/dali/utc-Dali-PropertyNotification.cpp new file mode 100644 index 0000000..690e6c4 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-PropertyNotification.cpp @@ -0,0 +1,879 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_property_notification_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_property_notification_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace { + +static bool gCallBackCalled; + +static void TestCallback(PropertyNotification& source) +{ + gCallBackCalled = true; +} + +const int RENDER_FRAME_INTERVAL(16); ///< Duration of each frame in ms. (at approx 60FPS) +const int DEFAULT_WAIT_PERIOD(100); ///< Default waiting period for check. + + +class TestClass : public ConnectionTracker +{ +public: + + TestClass() + { + } + + ~TestClass() + { + } + + void Initialize() + { + mActor = Actor::New(); + Stage::GetCurrent().Add( mActor ); + mNotification = mActor.AddPropertyNotification( Actor::Property::POSITION_X, GreaterThanCondition(100.0f) ); + mNotification.NotifySignal().Connect( this, &TestClass::OnPropertyNotify ); + } + + void RemovePropertyNotification() + { + mActor.RemovePropertyNotification( mNotification ); + } + + void RemovePropertyNotifications() + { + mActor.RemovePropertyNotifications(); + } + + void Terminate() + { + Stage::GetCurrent().Remove( mActor ); + mActor.Reset(); + mNotification.Reset(); + } + + void OnPropertyNotify( PropertyNotification& source ) + { + tet_infoline(" OnPropertyNotify"); + gCallBackCalled = true; + } + + Actor mActor; + PropertyNotification mNotification; +}; + + +/* + * Simulate time passed by. + * + * @note this will always process at least 1 frame (1/60 sec) + * + * @param application Test application instance + * @param duration Time to pass in milliseconds. + * @return The actual time passed in milliseconds + */ +int Wait(TestApplication& application, int duration = 0) +{ + int time = 0; + + for(int i = 0; i <= ( duration / RENDER_FRAME_INTERVAL); i++) + { + application.SendNotification(); + application.Render(RENDER_FRAME_INTERVAL); + time += RENDER_FRAME_INTERVAL; + } + + return time; +} + +} // unnamed namespace + + +// Positive test case for a method +int UtcDaliPropertyNotificationDownCast(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationDownCast"); + + Actor actor = Actor::New(); + PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X, GreaterThanCondition(100.0f)); + BaseHandle handle = notification; + PropertyNotification notificationHandle; + + DALI_TEST_CHECK(notification); + DALI_TEST_CHECK(handle); + DALI_TEST_CHECK(!notificationHandle); + + notificationHandle = PropertyNotification::DownCast( handle ); + DALI_TEST_CHECK(notificationHandle); + END_TEST; +} + + +// Negative test case for a method +int UtcDaliPropertyNotificationDownCastNegative(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationDownCastNegative"); + + // Create something derived from BaseHandle other than a PropertyNotification. + Actor somethingElse = Actor::New(); + + Actor actor = Actor::New(); + actor.AddPropertyNotification(Actor::Property::POSITION_X, GreaterThanCondition(100.0f)); + BaseHandle handle = somethingElse; + PropertyNotification notificationHandle; + + notificationHandle = PropertyNotification::DownCast( handle ); + DALI_TEST_CHECK(!notificationHandle); + END_TEST; +} + +int UtcDaliAddPropertyNotification(void) +{ + TestApplication application; // Reset all test adapter return codes + tet_infoline(" UtcDaliAddPropertyNotification"); + + Actor actor = Actor::New(); + + PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X, GreaterThanCondition(100.0f)); + DALI_TEST_CHECK( notification ); + END_TEST; +} + +int UtcDaliAddPropertyNotificationCallback(void) +{ + TestApplication application; // Reset all test adapter return codes + + TestClass* object = new TestClass; + + object->Initialize(); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + + gCallBackCalled = false; + + tet_infoline(" UtcDaliAddPropertyNotificationCallback - Forcing notification condition true, should receive a notification"); + object->mActor.SetPosition(Vector3(200.0f, 0.0f, 0.0f)); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + DALI_TEST_CHECK( gCallBackCalled ); + gCallBackCalled = false; + + tet_infoline(" UtcDaliAddPropertyNotificationCallback - Forcing notification condition false, should not receive a notification"); + object->mActor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + DALI_TEST_CHECK( !gCallBackCalled ); + gCallBackCalled = false; + + tet_infoline(" UtcDaliAddPropertyNotificationCallback - Deleting notification and it's owning object, should not receive a notification"); + object->mActor.SetPosition(Vector3(200.0f, 0.0f, 0.0f)); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + object->Terminate(); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + DALI_TEST_CHECK( !gCallBackCalled ); + + tet_infoline(" UtcDaliAddPropertyNotificationCallback - Removing notification and it's owning object, should not receive a notification"); + object->Initialize(); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + gCallBackCalled = false; + + object->RemovePropertyNotification(); + + object->mActor.SetPosition(Vector3(200.0f, 0.0f, 0.0f)); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + DALI_TEST_CHECK( !gCallBackCalled ); + + tet_infoline(" UtcDaliAddPropertyNotificationCallback - Removing all notifications and it's owning object, should not receive a notification"); + object->Initialize(); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + gCallBackCalled = false; + + object->RemovePropertyNotifications(); + + object->mActor.SetPosition(Vector3(200.0f, 0.0f, 0.0f)); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + DALI_TEST_CHECK( !gCallBackCalled ); + + + delete object; + END_TEST; +} + +int UtcDaliAddPropertyNotificationTypeProperty(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + + // Currently, Type registry properties cannot be animated + try + { + actor.AddPropertyNotification( PROPERTY_REGISTRATION_START_INDEX, GreaterThanCondition( 100.0f ) ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "false && \"Property notification added to event side only property", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliPropertyNotificationGetCondition(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationGetCondition"); + + Actor actor = Actor::New(); + + PropertyCondition condition = GreaterThanCondition(100.0f); + PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X, condition); + DALI_TEST_CHECK( condition == notification.GetCondition() ); + END_TEST; +} + +class PropertyNotificationConstWrapper +{ +public: + + PropertyNotificationConstWrapper(PropertyNotification propertyNotification) + :mPropertyNotification(propertyNotification) + { + + } + + /** + * Returns const reference to property notification. + * @return const reference. + */ + const PropertyCondition& GetCondition() const + { + return mPropertyNotification.GetCondition(); + } + + PropertyNotification mPropertyNotification; +}; + +int UtcDaliPropertyNotificationGetConditionConst(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationGetConditionConst"); + + Actor actor = Actor::New(); + + PropertyCondition condition = GreaterThanCondition(100.0f); + PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X, condition); + PropertyNotificationConstWrapper notificationConst(notification); + const PropertyCondition& conditionReference1 = notificationConst.GetCondition(); + const PropertyCondition& conditionReference2 = notificationConst.GetCondition(); + + DALI_TEST_CHECK( (&conditionReference1) == (&conditionReference2) ); + DALI_TEST_CHECK( conditionReference1 == condition ); + END_TEST; +} + +int UtcDaliPropertyNotificationGetTarget(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationGetTarget"); + + Actor actor = Actor::New(); + Actor actor2 = Actor::New(); + + PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X, + GreaterThanCondition(100.0f)); + Actor targetActor = Actor::DownCast( notification.GetTarget() ); + + DALI_TEST_CHECK( targetActor == actor ); + END_TEST; +} + +int UtcDaliPropertyNotificationGetProperty(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationGetProperty"); + + Actor actor = Actor::New(); + + PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X, + GreaterThanCondition(100.0f)); + Property::Index targetProperty = notification.GetTargetProperty(); + + DALI_TEST_EQUALS( targetProperty, Actor::Property::POSITION_X, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyNotificationGetNotifyMode(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationGetNotifyMode"); + + Actor actor = Actor::New(); + + PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X, + GreaterThanCondition(100.0f)); + notification.SetNotifyMode(PropertyNotification::NotifyOnChanged); + PropertyNotification::NotifyMode notifyMode = notification.GetNotifyMode(); + + DALI_TEST_EQUALS( notifyMode, PropertyNotification::NotifyOnChanged, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyNotificationGetNotifyResultP(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationGetNotifyMode"); + + Actor actor = Actor::New(); + + PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X, + GreaterThanCondition(100.0f)); + notification.SetNotifyMode(PropertyNotification::NotifyOnChanged); + gCallBackCalled = false; + notification.NotifySignal().Connect( &TestCallback ); + + actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + + bool notifyResult = notification.GetNotifyResult(); + + DALI_TEST_EQUALS( notifyResult, false, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyNotificationGreaterThan(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationGreaterThan"); + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION_X, GreaterThanCondition(100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + + actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + + // Move right to satisfy condition + gCallBackCalled = false; + actor.SetPosition(Vector3(200.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Move left to un-satisfy condition + gCallBackCalled = false; + actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( !gCallBackCalled ); + + // Move right to satisfy condition again. + gCallBackCalled = false; + Wait(application, DEFAULT_WAIT_PERIOD); + actor.SetPosition(Vector3(200.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + END_TEST; +} + +int UtcDaliPropertyNotificationLessThan(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationLessThan"); + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION_X, LessThanCondition(100.0f ) ); + notification.NotifySignal().Connect( &TestCallback ); + + actor.SetPosition(Vector3(200.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + + // Move left to satisfy condition + gCallBackCalled = false; + actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Move right to un-satisfy condition + gCallBackCalled = false; + actor.SetPosition(Vector3(200.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( !gCallBackCalled ); + + // Move left to satisfy condition again. + gCallBackCalled = false; + Wait(application, DEFAULT_WAIT_PERIOD); + actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + END_TEST; +} + +int UtcDaliPropertyNotificationInside(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationInside"); + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION_X, InsideCondition(100.0f, 200.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + + actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + + // Move inside to satisfy condition + gCallBackCalled = false; + actor.SetPosition(Vector3(150.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Move outside (right) to un-satisfy condition + gCallBackCalled = false; + actor.SetPosition(Vector3(300.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( !gCallBackCalled ); + + // Move inside to satisfy condition again. + gCallBackCalled = false; + Wait(application, DEFAULT_WAIT_PERIOD); + actor.SetPosition(Vector3(150.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + END_TEST; +} + +int UtcDaliPropertyNotificationOutside(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationOutside"); + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION_X, OutsideCondition(100.0f, 200.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + + actor.SetPosition(Vector3(150.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + + // Move outside (left) to satisfy condition + gCallBackCalled = false; + actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Move inside to un-satisfy condition + gCallBackCalled = false; + actor.SetPosition(Vector3(150.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( !gCallBackCalled ); + + // Move outside (right) to satisfy condition again. + gCallBackCalled = false; + Wait(application, DEFAULT_WAIT_PERIOD); + actor.SetPosition(Vector3(300.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + END_TEST; +} + +int UtcDaliPropertyNotificationVectorComponentGreaterThan(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationGreaterThan"); + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION, 0, GreaterThanCondition(100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + notification = actor.AddPropertyNotification( Actor::Property::POSITION, 1, GreaterThanCondition(100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + notification = actor.AddPropertyNotification( Actor::Property::POSITION, 2, GreaterThanCondition(100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + notification = actor.AddPropertyNotification( Actor::Property::COLOR, 3, GreaterThanCondition(0.5f) ); + notification.NotifySignal().Connect( &TestCallback ); + + actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + + // Move right to satisfy XAxis condition + gCallBackCalled = false; + actor.SetPosition(Vector3(200.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Move down to satisfy YAxis condition + gCallBackCalled = false; + actor.SetPosition(Vector3(200.0f, 200.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Move forward to satisfy ZAxis + gCallBackCalled = false; + Wait(application, DEFAULT_WAIT_PERIOD); + actor.SetPosition(Vector3(200.0f, 200.0f, 200.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Change alpha Colour to satisfy w/alpha component condition + gCallBackCalled = false; + Wait(application, DEFAULT_WAIT_PERIOD); + actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + END_TEST; +} + +int UtcDaliPropertyNotificationVectorComponentLessThan(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationLessThan"); + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION, 0, LessThanCondition(-100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + notification = actor.AddPropertyNotification( Actor::Property::POSITION, 1, LessThanCondition(-100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + notification = actor.AddPropertyNotification( Actor::Property::POSITION, 2, LessThanCondition(-100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + notification = actor.AddPropertyNotification( Actor::Property::COLOR, 3, LessThanCondition(0.5f) ); + notification.NotifySignal().Connect( &TestCallback ); + + actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + + // Move left to satisfy XAxis condition + gCallBackCalled = false; + actor.SetPosition(Vector3(-200.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Move up to satisfy YAxis condition + gCallBackCalled = false; + actor.SetPosition(Vector3(-200.0f, -200.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Move back to satisfy ZAxis + gCallBackCalled = false; + Wait(application, DEFAULT_WAIT_PERIOD); + actor.SetPosition(Vector3(-200.0f, -200.0f, -200.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Change alpha Colour to satisfy w/alpha component condition + gCallBackCalled = false; + Wait(application, DEFAULT_WAIT_PERIOD); + actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + END_TEST; +} + +int UtcDaliPropertyNotificationVectorComponentInside(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationInside"); + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION, 0, InsideCondition(-100.0f, 100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + notification = actor.AddPropertyNotification( Actor::Property::POSITION, 1, InsideCondition(-100.0f, 100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + notification = actor.AddPropertyNotification( Actor::Property::POSITION, 2, InsideCondition(-100.0f, 100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + notification = actor.AddPropertyNotification( Actor::Property::COLOR, 3, InsideCondition(0.25f, 0.75f) ); + notification.NotifySignal().Connect( &TestCallback ); + + // set outside all conditions + actor.SetPosition(Vector3(200.0f, 200.0f, 200.0f)); + actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + + // Move x to inside condition + gCallBackCalled = false; + actor.SetPosition(Vector3(0.0f, 200.0f, 200.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Move y to inside condition + gCallBackCalled = false; + actor.SetPosition(Vector3(0.0f, 0.0f, 200.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Move z to inside condition + gCallBackCalled = false; + Wait(application, DEFAULT_WAIT_PERIOD); + actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // change alpha to inside condition + gCallBackCalled = false; + Wait(application, DEFAULT_WAIT_PERIOD); + actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 0.5f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + END_TEST; +} + +int UtcDaliPropertyNotificationVectorComponentOutside(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationOutside"); + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION, 0, OutsideCondition(-100.0f, 100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + notification = actor.AddPropertyNotification( Actor::Property::POSITION, 1, OutsideCondition(-100.0f, 100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + notification = actor.AddPropertyNotification( Actor::Property::POSITION, 2, OutsideCondition(-100.0f, 100.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + notification = actor.AddPropertyNotification( Actor::Property::COLOR, 3, OutsideCondition(0.25f, 0.75f) ); + notification.NotifySignal().Connect( &TestCallback ); + + // set inside all conditions + actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 0.5f)); + Wait(application, DEFAULT_WAIT_PERIOD); + + // Move x to outside condition + gCallBackCalled = false; + actor.SetPosition(Vector3(200.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Move y to outside condition + gCallBackCalled = false; + actor.SetPosition(Vector3(200.0f, 200.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // Move z to outside condition + gCallBackCalled = false; + Wait(application, DEFAULT_WAIT_PERIOD); + actor.SetPosition(Vector3(200.0f, 200.0f, 200.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + + // change alpha to outside condition + gCallBackCalled = false; + Wait(application, DEFAULT_WAIT_PERIOD); + actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + END_TEST; +} + +int UtcDaliPropertyConditionGetArguments(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyConditionGetArguments"); + + PropertyCondition condition = GreaterThanCondition( 50.0f ); + + DALI_TEST_EQUALS( condition.GetArgumentCount(), 1u, TEST_LOCATION ); + float value = condition.GetArgument( 0 ); + DALI_TEST_EQUALS( value, 50.0f, TEST_LOCATION ); + + condition = InsideCondition( 125.0f, 250.0f ); + + DALI_TEST_EQUALS( condition.GetArgumentCount(), 2u, TEST_LOCATION ); + float value1 = condition.GetArgument( 0 ); + float value2 = condition.GetArgument( 1 ); + DALI_TEST_EQUALS( value1, 125.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( value2, 250.0f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyNotificationStep(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationStep"); + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + const float step = 100.0f; + // float + PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION, 0, StepCondition(step, 50.0f) ); + notification.NotifySignal().Connect( &TestCallback ); + + // set initial position + actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + + // test both directions + for( int i = 1 ; i < 10 ; ++i ) + { + // Move x to negative position + gCallBackCalled = false; + actor.SetPosition(Vector3((i * step), 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + } + + for( int i = 1 ; i < 10 ; ++i ) + { + // Move x to negative position + gCallBackCalled = false; + actor.SetPosition(Vector3(-(i * step), 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + } + END_TEST; +} + +int UtcDaliPropertyNotificationVariableStep(void) +{ + TestApplication application; + tet_infoline(" UtcDaliPropertyNotificationStep"); + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + + Dali::Vector values; + + const float averageStep = 100.0f; + + for( int i = 1 ; i < 10 ; i++ ) + { + values.PushBack(i * averageStep + (i % 2 == 0 ? -(averageStep * 0.2f) : (averageStep * 0.2f))); + } + // float + PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION, 0, VariableStepCondition(values) ); + notification.NotifySignal().Connect( &TestCallback ); + + // set initial position lower than first position in list + actor.SetPosition(Vector3(values[0] - averageStep, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + + for( unsigned int i = 0 ; i < values.Count() - 1 ; ++i ) + { + gCallBackCalled = false; + // set position half way between the current values + float position = values[i] + (0.5f * (values[i + 1] - values[i])); + actor.SetPosition(Vector3(position, 0.0f, 0.0f)); + Wait(application, DEFAULT_WAIT_PERIOD); + DALI_TEST_CHECK( gCallBackCalled ); + } + END_TEST; +} + +static bool gCallBack2Called = false; +void TestCallback2(PropertyNotification& source) +{ + gCallBack2Called = true; +} + +int UtcDaliPropertyNotificationOrder(void) +{ + TestApplication application; // Reset all test adapter return codes + + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + // this should complete in first frame + PropertyNotification notification1 = actor.AddPropertyNotification( Actor::Property::POSITION_X, GreaterThanCondition(90.0f) ); + notification1.NotifySignal().Connect( &TestCallback ); + // this should complete in second frame + PropertyNotification notification2 = actor.AddPropertyNotification( Actor::Property::POSITION_X, GreaterThanCondition(150.0f) ); + notification2.NotifySignal().Connect( &TestCallback2 ); + Animation animation = Animation::New( 0.032f ); // finishes in 32 ms + animation.AnimateTo( Property(actor, Actor::Property::POSITION ), Vector3( 200.0f, 0.0f, 0.0f ), AlphaFunction::LINEAR ); + animation.Play(); + + // flush the queue + application.SendNotification(); + // first frame + application.Render(RENDER_FRAME_INTERVAL); + // no notifications yet + DALI_TEST_EQUALS( gCallBackCalled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( gCallBack2Called, false, TEST_LOCATION ); + gCallBackCalled = false; + gCallBack2Called = false; + + // dont serve the notifications but run another update & render + // this simulates situation where there is a notification in event side but it's not been picked up by event thread + // second frame + application.Render(RENDER_FRAME_INTERVAL); + DALI_TEST_EQUALS( gCallBackCalled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( gCallBack2Called, false, TEST_LOCATION ); + + // serve the notifications + application.SendNotification(); + DALI_TEST_EQUALS( gCallBackCalled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( gCallBack2Called, true, TEST_LOCATION ); + + gCallBackCalled = false; + gCallBack2Called = false; + application.Render(RENDER_FRAME_INTERVAL); + application.SendNotification(); + DALI_TEST_EQUALS( gCallBackCalled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( gCallBack2Called, false, TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-PropertyTypes.cpp b/automated-tests/src/dali/utc-Dali-PropertyTypes.cpp new file mode 100644 index 0000000..c5b6252 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-PropertyTypes.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + +using namespace Dali; + +DALI_IMPORT_API const char* const GetName(Property::Type type); + +int UtcDaliPropertyTypesGetNameP(void) +{ + DALI_TEST_EQUALS( "NONE", Dali::PropertyTypes::GetName(Property::NONE ), TEST_LOCATION ); + DALI_TEST_EQUALS( "BOOLEAN", Dali::PropertyTypes::GetName(Property::BOOLEAN ), TEST_LOCATION ); + DALI_TEST_EQUALS( "FLOAT", Dali::PropertyTypes::GetName(Property::FLOAT ), TEST_LOCATION ); + DALI_TEST_EQUALS( "INTEGER", Dali::PropertyTypes::GetName(Property::INTEGER ), TEST_LOCATION ); + DALI_TEST_EQUALS( "VECTOR2", Dali::PropertyTypes::GetName(Property::VECTOR2 ), TEST_LOCATION ); + DALI_TEST_EQUALS( "VECTOR3", Dali::PropertyTypes::GetName(Property::VECTOR3 ), TEST_LOCATION ); + DALI_TEST_EQUALS( "VECTOR4", Dali::PropertyTypes::GetName(Property::VECTOR4 ), TEST_LOCATION ); + DALI_TEST_EQUALS( "MATRIX3", Dali::PropertyTypes::GetName(Property::MATRIX3 ), TEST_LOCATION ); + DALI_TEST_EQUALS( "MATRIX", Dali::PropertyTypes::GetName(Property::MATRIX ), TEST_LOCATION ); + DALI_TEST_EQUALS( "RECTANGLE", Dali::PropertyTypes::GetName(Property::RECTANGLE ), TEST_LOCATION ); + DALI_TEST_EQUALS( "ROTATION", Dali::PropertyTypes::GetName(Property::ROTATION ), TEST_LOCATION ); + DALI_TEST_EQUALS( "STRING", Dali::PropertyTypes::GetName(Property::STRING ), TEST_LOCATION ); + DALI_TEST_EQUALS( "ARRAY", Dali::PropertyTypes::GetName(Property::ARRAY ), TEST_LOCATION ); + DALI_TEST_EQUALS( "MAP", Dali::PropertyTypes::GetName(Property::MAP ), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyTypesGet02P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::BOOLEAN ); + END_TEST; +} + +int UtcDaliPropertyTypesGet03P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::FLOAT ); + END_TEST; +} + +int UtcDaliPropertyTypesGet04P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::INTEGER ); + END_TEST; +} + +int UtcDaliPropertyTypesGet06P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::VECTOR2 ); + END_TEST; +} + +int UtcDaliPropertyTypesGet07P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::VECTOR3 ); + END_TEST; +} + +int UtcDaliPropertyTypesGet08P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::VECTOR4 ); + END_TEST; +} + +int UtcDaliPropertyTypesGet09P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::MATRIX3 ); + END_TEST; +} + +int UtcDaliPropertyTypesGet10(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::MATRIX ); + END_TEST; +} + +int UtcDaliPropertyTypesGet11P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::ROTATION ); + END_TEST; +} + +int UtcDaliPropertyTypesGet12P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::ROTATION ); + END_TEST; +} + +int UtcDaliPropertyTypesGet13P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::STRING ); + END_TEST; +} + +int UtcDaliPropertyTypesGet14P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get >() == Property::RECTANGLE ); + END_TEST; +} + +int UtcDaliPropertyTypesGet15P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::MAP ); + END_TEST; +} + +int UtcDaliPropertyTypesGet16P(void) +{ + DALI_TEST_CHECK( Dali::PropertyTypes::Get() == Property::ARRAY ); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-PropertyValue.cpp b/automated-tests/src/dali/utc-Dali-PropertyValue.cpp new file mode 100644 index 0000000..6b0bba5 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-PropertyValue.cpp @@ -0,0 +1,1242 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + +using namespace Dali; + +namespace +{ + +void CheckTypeName(const Property::Type& type) +{ + switch(type) + { + case Property::NONE: + { + DALI_TEST_CHECK( "NONE" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::BOOLEAN: + { + DALI_TEST_CHECK( "BOOLEAN" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::FLOAT: + { + DALI_TEST_CHECK( "FLOAT" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::INTEGER: + { + DALI_TEST_CHECK( "INTEGER" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::VECTOR2: + { + DALI_TEST_CHECK( "VECTOR2" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::VECTOR3: + { + DALI_TEST_CHECK( "VECTOR3" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::VECTOR4: + { + DALI_TEST_CHECK( "VECTOR4" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::MATRIX3: + { + DALI_TEST_CHECK( "MATRIX3" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::MATRIX: + { + DALI_TEST_CHECK( "MATRIX" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::RECTANGLE: + { + DALI_TEST_CHECK( "RECTANGLE" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::ROTATION: + { + DALI_TEST_CHECK( "ROTATION" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::STRING: + { + DALI_TEST_CHECK( "STRING" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::ARRAY: + { + DALI_TEST_CHECK( "ARRAY" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + case Property::MAP: + { + DALI_TEST_CHECK( "MAP" == std::string(PropertyTypes::GetName( type ) ) ); + break; + } + } // switch(type) + +} // CheckTypeName + +template +struct CheckCopyCtorP +{ + CheckCopyCtorP(Property::Value value) + { + Property::Value copy( value ); + DALI_TEST_CHECK( value.Get() == copy.Get() ); + } +}; + +} // unnamed namespace + +void utc_dali_property_value_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_property_value_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +int UtcDaliPropertyValueConstructorsNoneP(void) +{ + Property::Value value; + + DALI_TEST_CHECK( value.GetType() == Property::NONE ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsNoneTypeP(void) +{ + Property::Value value( Property::NONE ); + + DALI_TEST_CHECK( value.GetType() == Property::NONE ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsBoolP(void) +{ + Property::Value value(true); + + DALI_TEST_CHECK( value.GetType() == Property::BOOLEAN ); + DALI_TEST_CHECK( value.Get() == true ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorBoolTypeP(void) +{ + Property::Value value(Property::BOOLEAN); + + DALI_TEST_CHECK( value.GetType() == Property::BOOLEAN ); + DALI_TEST_CHECK( value.Get() == false ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsFloatP(void) +{ + Property::Value value(2.f); + + DALI_TEST_CHECK( value.GetType() == Property::FLOAT ); + DALI_TEST_CHECK( value.Get() == 2.f ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsFloatTypeP(void) +{ + Property::Value value(Property::FLOAT); + + DALI_TEST_CHECK( value.GetType() == Property::FLOAT ); + DALI_TEST_CHECK( value.Get() == 0.f ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsIntP(void) +{ + Property::Value value(1); + + DALI_TEST_CHECK( value.GetType() == Property::INTEGER ); + DALI_TEST_CHECK( value.Get() == 1 ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsIntTypeP(void) +{ + Property::Value value(Property::INTEGER); + + DALI_TEST_CHECK( value.GetType() == Property::INTEGER ); + DALI_TEST_CHECK( value.Get() == 0 ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsVector2P(void) +{ + Vector2 v(1,1); + Property::Value value(v); + + DALI_TEST_CHECK( value.GetType() == Property::VECTOR2 ); + DALI_TEST_CHECK( value.Get() == v ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsVector2TypeP(void) +{ + Property::Value value( Property::VECTOR2 ); + + DALI_TEST_CHECK( value.GetType() == Property::VECTOR2 ); + DALI_TEST_CHECK( value.Get() == Vector2::ZERO ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsVector3P(void) +{ + Vector3 v(1.f,2.f,3.f); + Property::Value value(v); + + DALI_TEST_CHECK( value.GetType() == Property::VECTOR3 ); + DALI_TEST_CHECK( value.Get() == v ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsVector3TypeP(void) +{ + Property::Value value( Property::VECTOR3 ); + + DALI_TEST_CHECK( value.GetType() == Property::VECTOR3 ); + DALI_TEST_CHECK( value.Get() == Vector3() ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsVector4P(void) +{ + Vector4 v(1.f,1.f,1.f,0.9f); + Property::Value value(v); + + DALI_TEST_CHECK( value.GetType() == Property::VECTOR4 ); + DALI_TEST_CHECK( value.Get() == v ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsVector4TypeP(void) +{ + Property::Value value( Property::VECTOR4 ); + + DALI_TEST_CHECK( value.GetType() == Property::VECTOR4 ); + DALI_TEST_CHECK( value.Get() == Vector4() ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsMatrix3P(void) +{ + Matrix3 v(1.0,1.0,1.0, 1.0,1.0,1.0, 1.0,1.0,1.0); + Property::Value value(v); + + DALI_TEST_CHECK( value.GetType() == Property::MATRIX3 ); + DALI_TEST_CHECK( value.Get() == v ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsMatrix3TypeP(void) +{ + Property::Value value( Property::MATRIX3 ); + + DALI_TEST_CHECK( value.GetType() == Property::MATRIX3 ); + DALI_TEST_CHECK( value.Get() == Matrix3() ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsMatrixP(void) +{ + float a[] = {1.0,1.0,1.0,1.0, 1.0,1.0,1.0,1.0, 1.0,1.0,1.0,1.0, 1.0,1.0,1.0,1.0}; + Matrix v(a); + Property::Value value(v); + + DALI_TEST_CHECK( value.GetType() == Property::MATRIX ); + DALI_TEST_CHECK( value.Get() == v ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsMatrixTypeP(void) +{ + Property::Value value( Property::MATRIX ); + + DALI_TEST_CHECK( value.GetType() == Property::MATRIX ); + DALI_TEST_CHECK( value.Get() == Matrix() ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsRectP(void) +{ + Rect v(1.0,1.0,1.0,1.0); + Property::Value value(v); + + DALI_TEST_EQUALS( value.GetType(), Property::RECTANGLE, TEST_LOCATION ); + DALI_TEST_CHECK( value.Get >() == v ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsRectTypeP(void) +{ + Property::Value value( Property::RECTANGLE ); + + DALI_TEST_CHECK( value.GetType() == Property::RECTANGLE ); + DALI_TEST_CHECK( value.Get >() == Rect(0,0,0,0) ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsAngleAxisP(void) +{ + AngleAxis input( Dali::ANGLE_90, Vector3::XAXIS ); + Property::Value value( input ); + + DALI_TEST_CHECK( value.GetType() == Property::ROTATION ); + AngleAxis result = value.Get(); + DALI_TEST_EQUALS( result.angle, input.angle, TEST_LOCATION ); + DALI_TEST_EQUALS( result.axis, input.axis, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsQuaternionP(void) +{ + Quaternion v( Vector4(1.0,1.0,1.0,1.0) ); + Property::Value value(v); + + DALI_TEST_CHECK( value.GetType() == Property::ROTATION ); + DALI_TEST_CHECK( value.Get() == v ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsRotationTypeP(void) +{ + Property::Value value( Property::ROTATION ); + + DALI_TEST_CHECK( value.GetType() == Property::ROTATION ); + AngleAxis result = value.Get(); + DALI_TEST_EQUALS( result.angle, Radian(0.f), TEST_LOCATION ); + DALI_TEST_EQUALS( result.axis, Vector3::ZERO, TEST_LOCATION ); // identity quaternion returns a zero angle-axis + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsStringP(void) +{ + std::string v("1"); + Property::Value value(v); + + DALI_TEST_CHECK( value.GetType() == Property::STRING ); + DALI_TEST_CHECK( value.Get() == v ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsStringTypeP(void) +{ + Property::Value value( Property::STRING ); + + DALI_TEST_CHECK( value.GetType() == Property::STRING ); + DALI_TEST_CHECK( value.Get() == std::string() ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsArrayP(void) +{ + Property::Array foo; + Property::Value value( foo ); + + DALI_TEST_CHECK( value.GetType() == Property::ARRAY ); + DALI_TEST_CHECK( value.Get().Count() == 0 ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsArray2P(void) +{ + Property::Array foo; + foo.PushBack( Property::Value() ); + Property::Value value( foo ); + + DALI_TEST_CHECK( value.GetType() == Property::ARRAY ); + DALI_TEST_CHECK( value.Get().Count() == 1 ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsArrayTypeP(void) +{ + Property::Value value(Property::ARRAY); + + DALI_TEST_CHECK( value.GetType() == Property::ARRAY ); + DALI_TEST_CHECK( value.Get().Count() == 0 ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsMapP(void) +{ + Property::Map map; + Property::Value value( map ); + + DALI_TEST_CHECK( value.GetType() == Property::MAP ); + DALI_TEST_CHECK( value.Get().Count() == 0 ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsMap2P(void) +{ + Property::Map map; + map.Insert( "", "" ); + Property::Value value( map ); + + DALI_TEST_CHECK( value.GetType() == Property::MAP ); + DALI_TEST_CHECK( value.Get().Count() == 1 ); + + END_TEST; +} + +int UtcDaliPropertyValueConstructorsMapTypeP(void) +{ + Property::Value value(Property::MAP); + + DALI_TEST_CHECK( value.GetType() == Property::MAP ); + DALI_TEST_CHECK( value.Get().Count() == 0 ); + + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorP(void) +{ + Property::Value value; + Property::Value value2( value ); + DALI_TEST_EQUALS( value.GetType(), value2.GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS( value.GetMap(), value2.GetMap(), TEST_LOCATION ); + DALI_TEST_EQUALS( value.GetArray(), value2.GetArray(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorBoolP(void) +{ + CheckCopyCtorP check(true); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorFloatP(void) +{ + CheckCopyCtorP check(1.f); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorIntP(void) +{ + CheckCopyCtorP check(1); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructoVector2P(void) +{ + CheckCopyCtorP check( Vector2(2,1) ); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorVector3P(void) +{ + CheckCopyCtorP check( Vector3(3.f,2.f,1.f) ); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorVector4P(void) +{ + CheckCopyCtorP check( Vector4(4.f,3.f,2.f,1.f) ); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorMatrix3P(void) +{ + CheckCopyCtorP check( Matrix3::IDENTITY ); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorMatrixP(void) +{ + CheckCopyCtorP check(Matrix::IDENTITY); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorRectP(void) +{ + CheckCopyCtorP > check( Rect(1.0,1.0,1.0,1.0) ); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorAngleAxisP(void) +{ + CheckCopyCtorP check( AngleAxis(Degree(1.0), Vector3(1.0,1.0,1.0)) ); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorQuaternionP(void) +{ + CheckCopyCtorP check( Quaternion( Vector4(1.0, 1.0, 1.0, 1.0) ) ); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorStringP(void) +{ + CheckCopyCtorP check( std::string("1") ); + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorArrayP(void) +{ + Property::Value value1(Property::ARRAY); + Property::Array* array= value1.GetArray(); + array->PushBack(Property::Value(1)); + + Property::Value value2( value1 ); + DALI_TEST_EQUALS( value1.GetType(), value2.GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS( value1.GetArray()->Count(), value2.GetArray()->Count(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyValueCopyConstructorMapP(void) +{ + Property::Value value1(Property::MAP); + Property::Map* map = value1.GetMap(); + (*map)["1"] = Property::Value(1); + + Property::Value value2( value1 ); + DALI_TEST_EQUALS( value1.GetType(), value2.GetType(), TEST_LOCATION ); + DALI_TEST_EQUALS( value1.GetMap()->Count(), value2.GetMap()->Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( value1.GetMap()->GetKey( 0 ), value2.GetMap()->GetKey( 0 ), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyValueAssignmentSelfP(void) +{ + Property::Value value; + Property::Value* self = &value; + value = *self; + DALI_TEST_EQUALS( value.GetType(), Property::NONE, TEST_LOCATION ); + DALI_TEST_CHECK( value.GetMap() == NULL ); + DALI_TEST_CHECK( value.GetArray() == NULL ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorNoneP(void) +{ + Property::Value value; + value = Property::Value(); // type match + DALI_TEST_EQUALS( value.GetType(), Property::NONE, TEST_LOCATION ); + Property::Value copy( false ); + copy = value; // type mismatch + DALI_TEST_EQUALS( value.GetType(), Property::NONE, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorBoolP(void) +{ + Property::Value value; + value = Property::Value(true); // type mismatch + DALI_TEST_CHECK( true == value.Get() ); + Property::Value copy( false ); + copy = value; // type match + DALI_TEST_CHECK( true == copy.Get() ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorIntP(void) +{ + Property::Value value; + value = Property::Value(10); // type mismatch + DALI_TEST_CHECK( 10 == value.Get() ); + Property::Value copy( 99 ); + copy = value; // type match + DALI_TEST_CHECK( 10 == copy.Get() ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorFloatP(void) +{ + Property::Value value; + value = Property::Value(10.f); // mismatch + DALI_TEST_CHECK( Dali::Equals(10.f, value.Get() ) ); + Property::Value copy(321.f); + copy = value; // match + DALI_TEST_CHECK( Dali::Equals(10.f, copy.Get() ) ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorVector2P(void) +{ + Property::Value value; + value = Property::Value( Vector2(1,2) ); // mismatch + DALI_TEST_CHECK( Vector2(1,2) == value.Get() ); + Property::Value copy( Property::VECTOR2 ); + copy = value; // match + DALI_TEST_CHECK( Vector2(1,2) == copy.Get() ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorVector3P(void) +{ + Property::Value value; + value = Property::Value( Vector3(1.f,2.f,3.f) ); // mismatch + DALI_TEST_CHECK( Vector3(1.f,2.f,3.f) == value.Get() ); + Property::Value copy( Property::VECTOR3 ); + copy = value; // match + DALI_TEST_CHECK( Vector3(1.f,2.f,3.f) == copy.Get() ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorVector4P(void) +{ + Property::Value value; + value = Property::Value( Vector4(1,2,3,4) ); // mismatch + DALI_TEST_CHECK( Vector4(1,2,3,4) == value.Get() ); + Property::Value copy( Vector4(0,1,2,3) ); + copy = value; // match + DALI_TEST_CHECK( Vector4(1,2,3,4) == copy.Get() ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorMatrix3P(void) +{ + Property::Value value; + value = Property::Value( Matrix3::IDENTITY ); // mismatch + DALI_TEST_CHECK( Matrix3::IDENTITY == value.Get() ); + Property::Value copy( Property::MATRIX3 ); + copy = value; // match + DALI_TEST_CHECK( Matrix3::IDENTITY == copy.Get() ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorMatrixP(void) +{ + Property::Value value; + value = Property::Value( Matrix::IDENTITY ); // mismatch + DALI_TEST_CHECK( Matrix::IDENTITY == value.Get() ); + Matrix foo; + Property::Value copy( foo ); + copy = value; // match + DALI_TEST_CHECK( Matrix::IDENTITY == copy.Get() ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorRectP(void) +{ + Property::Value value; + typedef Dali::Rect Rectangle; + value = Property::Value( Rectangle(4,3,2,1) ); // mismatch + DALI_TEST_CHECK( Rectangle(4,3,2,1) == value.Get() ); + Property::Value copy( Property::RECTANGLE ); + copy = value; // match + Rectangle copyRect; + copy.Get(copyRect); + DALI_TEST_CHECK( Rectangle(4,3,2,1) == copyRect ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorQuaternionP(void) +{ + Property::Value value; + value = Property::Value( Quaternion(1,1,1,1) ); // mismatch + DALI_TEST_CHECK( Quaternion(1,1,1,1) == value.Get() ); + Property::Value copy( Property::ROTATION ); + copy = value; // match + DALI_TEST_CHECK( Quaternion(1,1,1,1) == copy.Get() ); + END_TEST; +} + + +int UtcDaliPropertyValueAssignmentOperatorAngleAxisP(void) +{ + Property::Value value; + value = Property::Value( AngleAxis( Radian(Math::PI_2), Vector3::XAXIS ) ); // mismatch + DALI_TEST_EQUALS( value.Get().axis, Vector3::XAXIS, TEST_LOCATION ); + DALI_TEST_EQUALS( value.Get().angle, Radian(Math::PI_2), TEST_LOCATION ); + Property::Value copy( Property::ROTATION ); + copy = value; // match + DALI_TEST_EQUALS( value.Get().axis, copy.Get().axis, TEST_LOCATION ); + DALI_TEST_EQUALS( value.Get().angle, copy.Get().angle, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorStringP(void) +{ + Property::Value value; + value = Property::Value("yes"); // mismatch + DALI_TEST_CHECK( "yes" == value.Get() ); + Property::Value copy("no"); + copy = value; // match + DALI_TEST_CHECK( "yes" == copy.Get() ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorArrayP(void) +{ + Property::Value value; + value = Property::Value(Property::ARRAY); // mismatch + value.GetArray()->PushBack(10); + DALI_TEST_CHECK( value.GetArray() ); + Property::Value copy(Property::ARRAY); + copy = value; // match + Property::Array array; + copy.Get( array ); + int getItem = 0; + array[0].Get( getItem ); + DALI_TEST_CHECK( getItem == 10 ); + END_TEST; +} + +int UtcDaliPropertyValueAssignmentOperatorMapP(void) +{ + Property::Value value; + value = Property::Value(Property::MAP); // mismatch + value.GetMap()->Insert("key", "value"); + Property::Value copy( Property::MAP ); // match + copy = value; + Property::Map map; + copy.Get( map ); + DALI_TEST_CHECK( map.GetKey(0) == "key" ); + END_TEST; +} + +int UtcDaliPropertyValueGetTypeP(void) +{ + Property::Value value; + DALI_TEST_CHECK( value.GetType() == Property::NONE ); + END_TEST; +} + +int UtcDaliPropertyValueGetBoolP(void) +{ + Property::Value value(true); + bool boolean( false ); + DALI_TEST_CHECK( value.Get( boolean ) == true ); + DALI_TEST_CHECK( value.Get() == true ); + std::string string; + DALI_TEST_CHECK( value.Get( string ) == false ); + value = Property::Value(1.f); + DALI_TEST_CHECK( value.Get() == 1.f ); + END_TEST; +} + +int UtcDaliPropertyValueGetBoolN(void) +{ + Property::Value value; + DALI_TEST_CHECK( value.Get() == false ); + bool boolean( false ); + DALI_TEST_CHECK( value.Get( boolean ) == false ); + END_TEST; +} + +int UtcDaliPropertyValueGetFloatP(void) +{ + Property::Value value(1.1f); + float flow( 0.0f ); + DALI_TEST_EQUALS( 1.1f, value.Get(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value.Get( flow ), TEST_LOCATION ); + DALI_TEST_EQUALS( 1.1f, flow, TEST_LOCATION ); + + Property::Value intValue(100); + DALI_TEST_EQUALS( 100.f, intValue.Get(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, intValue.Get( flow ), TEST_LOCATION ); + DALI_TEST_EQUALS( 100.f, flow, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyValueGetFloatN(void) +{ + Property::Value value; + float result( 1.0f ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( 1.0f, result, TEST_LOCATION ); // result is not modified + Property::Value value2( "" ); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( 1.0f, result, TEST_LOCATION ); // result is not modified + END_TEST; +} + +int UtcDaliPropertyValueGetIntP(void) +{ + Property::Value value(123); + int result( 10 ); + DALI_TEST_EQUALS( 123, value.Get(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( 123, result, TEST_LOCATION ); + + Property::Value floatValue(21.f); + DALI_TEST_EQUALS( 21, floatValue.Get(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, floatValue.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( 21, result, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliPropertyValueGetIntN(void) +{ + Property::Value value; + int result( 10 ); + DALI_TEST_EQUALS( 0, value.Get(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( 10, result, TEST_LOCATION ); // result is not modified + Property::Value value2(""); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( 10, result, TEST_LOCATION ); // result is not modified + END_TEST; +} + +int UtcDaliPropertyValueGetRectP(void) +{ + Property::Value value( Rect(1,2,3,4) ); + Rect result(4,3,2,1); + DALI_TEST_EQUALS( Rect(1,2,3,4), value.Get< Rect >(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Rect(1,2,3,4), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetRectN(void) +{ + Property::Value value; + Rect result(4,3,2,1); + DALI_TEST_EQUALS( Rect(0,0,0,0), value.Get< Rect >(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Rect(4,3,2,1), result, TEST_LOCATION ); + Property::Value value2(""); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Rect(4,3,2,1), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetVector2P(void) +{ + Property::Value value( Vector2(1.0f,2.0f) ); + Vector2 result; + DALI_TEST_EQUALS( Vector2(1.0f,2.0f), value.Get< Vector2 >(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Vector2(1.0f,2.0f), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetVector2N(void) +{ + Property::Value value; + Vector2 result; + DALI_TEST_EQUALS( Vector2(0.f,0.f), value.Get< Vector2 >(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Vector2(), result, TEST_LOCATION ); + Property::Value value2(""); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Vector2(), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetVector3P(void) +{ + Property::Value value( Vector3(1.0f,2.0f,-1.f) ); + Vector3 result; + DALI_TEST_EQUALS( Vector3(1.0f,2.0f,-1.f), value.Get< Vector3 >(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Vector3(1.0f,2.0f,-1.f), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetVector3N(void) +{ + Property::Value value; + Vector3 result; + DALI_TEST_EQUALS( Vector3(0.f,0.f,0.f), value.Get< Vector3 >(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Vector3(), result, TEST_LOCATION ); + Property::Value value2(""); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Vector3(), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetVector4P(void) +{ + Property::Value value( Vector4(1.f,2.f,-1.f,-3.f) ); + Vector4 result; + DALI_TEST_EQUALS( Vector4(1.f,2.f,-1.f,-3.f), value.Get< Vector4 >(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Vector4(1.f,2.f,-1.f,-3.f), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetVector4N(void) +{ + Property::Value value; + Vector4 result; + DALI_TEST_EQUALS( Vector4(0.f,0.f,0.f,0.f), value.Get< Vector4 >(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Vector4(), result, TEST_LOCATION ); + Property::Value value2(""); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Vector4(), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetMatrix3P(void) +{ + Property::Value value( Matrix3(1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f) ); + Matrix3 result; + DALI_TEST_EQUALS( Matrix3(1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f), value.Get< Matrix3 >(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Matrix3(1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetMatrix3N(void) +{ + Property::Value value; + Matrix3 result(1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f); + DALI_TEST_EQUALS( Matrix3(), value.Get< Matrix3 >(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Matrix3(1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f), result, TEST_LOCATION ); + Property::Value value2(""); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Matrix3(1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetMatrixP(void) +{ + float matrixValues[16] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 }; + Matrix input( matrixValues ); + Property::Value value( input ); + Matrix result; + DALI_TEST_EQUALS( input, value.Get< Matrix >(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( input, result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetMatrixN(void) +{ + Property::Value value; + Matrix result( Matrix::IDENTITY ); + DALI_TEST_EQUALS( Matrix(), value.Get< Matrix >(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Matrix::IDENTITY, result, TEST_LOCATION ); + + Property::Value value2(""); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Matrix::IDENTITY, result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetAngleAxisP(void) +{ + AngleAxis input( Dali::ANGLE_90, Vector3::XAXIS ); + Property::Value value( input ); + AngleAxis result = value.Get(); + DALI_TEST_EQUALS( input.angle, result.angle, TEST_LOCATION ); + DALI_TEST_EQUALS( input.axis, result.axis, TEST_LOCATION ); + + DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( input, result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetAngleAxisN(void) +{ + Property::Value value; + AngleAxis b = value.Get(); + AngleAxis result; + DALI_TEST_EQUALS( 0.f, b.angle, TEST_LOCATION ); + DALI_TEST_EQUALS( Vector3::ZERO, b.axis, TEST_LOCATION ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( AngleAxis(), result, TEST_LOCATION ); + + Property::Value value2(""); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( AngleAxis(), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetQuaternionP(void) +{ + Property::Value value( Quaternion(1.f,2.f,3.f,4.f) ); + Quaternion result; + DALI_TEST_EQUALS( Quaternion(1.f,2.f,3.f,4.f), value.Get< Quaternion >(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Quaternion(1.f,2.f,3.f,4.f), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetQuaternionN(void) +{ + Property::Value value; + Quaternion result(1.f,2.f,3.f,4.f); + DALI_TEST_EQUALS( Quaternion(), value.Get< Quaternion >(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Quaternion(1.f,2.f,3.f,4.f), result, TEST_LOCATION ); + + Property::Value value2(""); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( Quaternion(1.f,2.f,3.f,4.f), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetStringP(void) +{ + Property::Value value( std::string("hello") ); + std::string result; + DALI_TEST_EQUALS( std::string("hello"), value.Get< std::string >(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( std::string("hello"), result, TEST_LOCATION ); + + Property::Value value2( "C hi!" ); + DALI_TEST_EQUALS( "C hi!", value2.Get< std::string >(), TEST_LOCATION ); + DALI_TEST_EQUALS( true, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( "C hi!", result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetStringN(void) +{ + Property::Value value; + std::string result("doesn't change"); + DALI_TEST_EQUALS( std::string(), value.Get< std::string >(), TEST_LOCATION ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( "doesn't change", result, TEST_LOCATION ); + + Property::Value value2(10); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( "doesn't change", result, TEST_LOCATION ); + + Property::Value value3((char*)NULL); + DALI_TEST_EQUALS( true, value3.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( std::string(), result, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliPropertyValueGetArrayP(void) +{ + Property::Value value( Property::ARRAY ); + DALI_TEST_CHECK( NULL != value.GetArray() ); + value.GetArray()->PushBack( Property::Value(1) ); + Property::Array got = value.Get(); + DALI_TEST_CHECK( got[0].Get() == 1); + Property::Array result; + DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION ); + DALI_TEST_CHECK( result[0].Get() == 1); + END_TEST; +} + +int UtcDaliPropertyValueGetArrayN(void) +{ + Property::Value value; + DALI_TEST_CHECK( NULL == value.GetArray() ); + Property::Array result; + result.PushBack( Property::Value( 10 ) ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( 1, result.Count(), TEST_LOCATION ); // array is not modified + + Property::Value value2(""); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( 1, result.Count(), TEST_LOCATION ); // array is not modified + END_TEST; +} + +int UtcDaliPropertyValueGetMapP(void) +{ + Property::Value value(Property::MAP); + DALI_TEST_CHECK( NULL == value.GetArray() ); + DALI_TEST_CHECK( NULL != value.GetMap() ); + value.GetMap()->Insert("key", Property::Value(1)); + Property::Map result = value.Get(); + DALI_TEST_CHECK(result.Find("key")->Get() == 1); + DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION ); + DALI_TEST_CHECK(result.Find("key")->Get() == 1); + END_TEST; +} + +int UtcDaliPropertyValueGetMapN(void) +{ + Property::Value value; + DALI_TEST_CHECK( NULL == value.GetMap() ); + DALI_TEST_EQUALS( 0, value.Get().Count(), TEST_LOCATION ); + Property::Map result; + result.Insert("key", "value" ); + DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( 1, result.Count(), TEST_LOCATION ); + + Property::Value value2(""); + DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION ); + DALI_TEST_EQUALS( 1, result.Count(), TEST_LOCATION ); // array is not modified + END_TEST; +} + +int UtcDaliPropertyValueOutputStream(void) +{ + TestApplication application; + tet_infoline("Testing Property::Value output stream"); + typedef Dali::Rect Rectangle; + + Property::Value value(true); + { + std::ostringstream stream; + stream << value; + DALI_TEST_CHECK( stream.str() == "1" ) + } + + { + Property::Value empty; + std::ostringstream stream; + stream << empty; + DALI_TEST_EQUALS( stream.str(), "empty type", TEST_LOCATION ); + } + + { + Property::Value empty( Property::NONE ); + std::ostringstream stream; + stream << empty; + DALI_TEST_CHECK( stream.str() == "undefined type" ) + } + + { + value = Property::Value(20.2f); + std::ostringstream stream; + stream << value; + DALI_TEST_CHECK( stream.str() == "20.2" ) + } + + { + value = Property::Value(-25); + std::ostringstream stream; + stream << value; + DALI_TEST_CHECK( stream.str() == "-25" ) + } + + { + value = Property::Value( Vector2(1.f,1.f) ); + std::ostringstream stream; + stream << value; + DALI_TEST_CHECK( stream.str() == "[1, 1]" ); + } + + { + value = Property::Value( Vector3(1.f,1.f,1.f) ); + std::ostringstream stream; + stream << value; + DALI_TEST_CHECK( stream.str() == "[1, 1, 1]" ); + } + + { + value = Property::Value( Vector4(-4.f,-3.f,-2.f,-1.f) ); + std::ostringstream stream; + stream << value; + DALI_TEST_EQUALS( stream.str(), "[-4, -3, -2, -1]", TEST_LOCATION ); + } + + { + value = Property::Value( Matrix3::IDENTITY ); + std::ostringstream stream; + stream << value; + DALI_TEST_CHECK( stream.str() == "[ [1, 0, 0], [0, 1, 0], [0, 0, 1] ]" ); + } + + { + value = Property::Value( Matrix::IDENTITY ); + std::ostringstream stream; + stream << value; + DALI_TEST_CHECK( stream.str() == "[ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ]" ); + } + + { + value = Property::Value( Rectangle(1,2,3,4) ); + std::ostringstream stream; + stream << value; + DALI_TEST_CHECK( stream.str() == "[1, 2, 3, 4]" ); + } + + { + value = Property::Value( AngleAxis( Dali::ANGLE_120, Vector3::XAXIS ) ); + std::ostringstream stream; + stream << value; + tet_printf("angle axis = %s \n", stream.str().c_str() ); + DALI_TEST_EQUALS( stream.str(), "[ Axis: [1, 0, 0], Angle: 120 degrees ]", TEST_LOCATION ); + } + + { + value = Property::Value( std::string( "Foo" ) ); + std::ostringstream stream; + stream << value; + DALI_TEST_CHECK( stream.str() == "Foo" ); + } + + // Maps and arrays currently not supported, we just check a message is output + { + Property::Map map; + value = Property::Value( map ); + std::ostringstream stream; + stream << value; + DALI_TEST_CHECK( !stream.str().empty() ); + } + { + Property::Array array; + value = Property::Value( array ); + std::ostringstream stream; + stream << value; + DALI_TEST_CHECK( !stream.str().empty() ); + } + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Quaternion.cpp b/automated-tests/src/dali/utc-Dali-Quaternion.cpp new file mode 100644 index 0000000..aac64e6 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Quaternion.cpp @@ -0,0 +1,1118 @@ +/* + * Copyright ( c ) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 ( the "License" ); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include + +using namespace Dali; + + +void utc_dali_quaternion_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_quaternion_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +int UtcDaliQuaternionCtorDefaultP(void) +{ + Quaternion q; + DALI_TEST_EQUALS( q.AsVector().w, 1.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( q.AsVector().x, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( q.AsVector().y, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( q.AsVector().z, 0.0f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionCtorCosSinThetaP(void) +{ + Quaternion q( 1.0f, 0.1f, 0.2f, 0.3f ); + + DALI_TEST_EQUALS( q.AsVector().w, 1.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( q.AsVector().x, 0.1f, TEST_LOCATION ); + DALI_TEST_EQUALS( q.AsVector().y, 0.2f, TEST_LOCATION ); + DALI_TEST_EQUALS( q.AsVector().z, 0.3f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionCtorVector4P(void) +{ + Quaternion q( Vector4( 1.0f, 0.1f, 0.2f, 0.3f ) ); + + DALI_TEST_EQUALS( q.AsVector().x, 1.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( q.AsVector().y, 0.1f, TEST_LOCATION ); + DALI_TEST_EQUALS( q.AsVector().z, 0.2f, TEST_LOCATION ); + DALI_TEST_EQUALS( q.AsVector().w, 0.3f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionCtorAxisAngleVector3P(void) +{ + Quaternion q( Dali::ANGLE_90, Vector3( 1.0f, 2.0f, 3.0f ) ); + + // This will be normalised: + DALI_TEST_EQUALS( q.AsVector().w, 0.707f, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( q.AsVector().x, 0.189f, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( q.AsVector().y, 0.378f, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( q.AsVector().z, 0.567f, 0.001, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionCtorEulerAngleP(void) +{ + Quaternion q1(0.924f, 0.383f, 0.0f, 0.0f); + Vector4 r1(Radian(Degree(45)), 0.0f, 0.0f, 0.0f); + + Quaternion q2(0.793f, 0.0f, 0.609f, 0.0f); + Vector4 r2(0.0f, Radian(Degree(75)), 0.0f, 0.0f); + + Quaternion q3(0.383f, 0.0f, 0.0f, 0.924f); + Vector4 r3(0.0f, 0.0f, Radian(Degree(135)), 0.0f); + + Quaternion q4(0.795f, 0.478f, 0.374f, 0.006f); + Vector4 r4(Radian(Degree(71)), Radian(Degree(36)), Radian(Degree(27)), 0.0f); + + Quaternion q5( -0.149f, -0.697f, 0.145f, -0.686f); + Vector4 r5(Radian(Degree(148.0)), Radian(Degree(-88.2)), Radian(Degree(8.0)), 0.0f); + + DALI_TEST_EQUALS(q1.EulerAngles(), r1, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(q2.EulerAngles(), r2, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(q3.EulerAngles(), r3, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(q4.EulerAngles(), r4, 0.01, TEST_LOCATION); + DALI_TEST_EQUALS(q5.EulerAngles(), r5, 0.01, TEST_LOCATION); + END_TEST; +} + +int UtcDaliQuaternionCtorMatrixP01(void) +{ + // angle: 60 deg, axis: [1,2,3] + float Mref_raw[16] = { 0.535714f, 0.765794f, -0.355767f, 0.0f, + -0.622936f, 0.642857f, 0.445741f, 0.0f, + 0.570053f, -0.0171693f, 0.821429f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f}; + Matrix Mref( Mref_raw ); + + Quaternion q1( Radian(M_PI/3.0f), Vector3( 1.0f, 2.0f, 3.0f ) ); + Quaternion q2( Mref ); + + DALI_TEST_EQUALS( q1, q2, 0.001, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionCtorMatrixP02(void) +{ + // IDENTITY rotation + Quaternion q; + + Matrix m( q ); // Convert to matrix + + Quaternion q2( m ); // and back to a quaternion + + DALI_TEST_EQUALS( q, q2, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( m, Matrix::IDENTITY, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionCtorMatrixP03(void) +{ + // Create an arbitrary forward vector + for( float x=-1.0f; x<=1.0f; x+=0.1f ) + { + for( float y=-1.0f; y<1.0f; y+=0.1f ) + { + for( float z=-1.0f; z<1.0f; z+=0.1f ) + { + Vector3 vForward( x, y, z ); + vForward.Normalize(); + + // Construct an up vector from a sideways move + Vector3 vSide; + Vector3 vUp = vForward.Cross( Vector3( vForward.x+1.0f, vForward.y, vForward.z ) ); + if( vUp.Length() > 0.01 ) + { + vUp.Normalize(); + vSide = vUp.Cross( vForward ); + vSide.Normalize(); + } + else + { + vSide = vForward.Cross( Vector3( vForward.x, vForward.y+1.0f, vForward.z ) ); + vSide.Normalize(); + vUp = vForward.Cross( vSide ); + vUp.Normalize(); + } + + // Generate a matrix, and then a quaternion from it + Matrix rotMatrix( Matrix::IDENTITY ); + rotMatrix.SetXAxis( vSide ); + rotMatrix.SetYAxis( vUp ); + rotMatrix.SetZAxis( vForward ); + Quaternion q( rotMatrix ); + + // Generate a matrix from the quaternion, check they are the same + Matrix resultMatrix( q ); + DALI_TEST_EQUALS( resultMatrix, rotMatrix, 0.001f, TEST_LOCATION ); + + // Rotate an arbitrary vector by both quaternion and rotation matrix, + // check the result is the same + + Vector4 aVector( -2.983f, -3.213f, 8.2239f, 1.0f ); + Vector3 aVectorRotatedByQ = q.Rotate( Vector3( aVector ) ); + Vector4 aVectorRotatedByR = rotMatrix*aVector; + DALI_TEST_EQUALS( aVectorRotatedByQ, Vector3( aVectorRotatedByR ), 0.001f, TEST_LOCATION ); + } + } + } + END_TEST; +} + +int UtcDaliQuaternionCtorAxesP01(void) +{ + // angle: 60 deg, axis: [1,2,3] + float Mref_raw[16] = { 0.535714f, 0.765794f, -0.355767f, 0.0f, + -0.622936f, 0.642857f, 0.445741f, 0.0f, + 0.570053f, -0.0171693f, 0.821429f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f}; + Matrix Mref( Mref_raw ); + + Quaternion q1( Radian(M_PI/3.0f), Vector3( 1.0f, 2.0f, 3.0f ) ); + Quaternion q2( Mref.GetXAxis(), Mref.GetYAxis(), Mref.GetZAxis() ); + + DALI_TEST_EQUALS( q1, q2, 0.001, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionCtorAxesP02(void) +{ + Vector3 xAxis( Vector3::XAXIS ); + Vector3 yAxis( Vector3::YAXIS ); + Vector3 zAxis( Vector3::ZAXIS ); + + Quaternion q1( xAxis, yAxis, zAxis ); + + DALI_TEST_EQUALS( q1, Quaternion::IDENTITY, TEST_LOCATION ); + + xAxis = Vector3( 1.0f, 1.0f, 0.0f ); + xAxis.Normalize(); + yAxis = Vector3( -1.0f, 1.0f, 0.0f ); // 45 degrees anticlockwise ( +ve ) around z + yAxis.Normalize(); + zAxis = xAxis.Cross( yAxis ); + zAxis.Normalize(); + Quaternion q2( xAxis, yAxis, zAxis ); + + DALI_TEST_EQUALS( q2, Quaternion( Radian( Degree( 45 ) ), Vector3::ZAXIS ), 0.001f, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliQuaternionCtorAxesP03(void) +{ + // Create an arbitrary forward vector + for( float x=-1.0f; x<=1.0f; x+=0.1f ) + { + for( float y=-1.0f; y<1.0f; y+=0.1f ) + { + for( float z=-1.0f; z<1.0f; z+=0.1f ) + { + Vector3 vForward( x, y, z ); + vForward.Normalize(); + + // Construct an up vector from a sideways move + Vector3 vSide; + Vector3 vUp = vForward.Cross( Vector3( vForward.x+1.0f, vForward.y, vForward.z ) ); + if( vUp.Length() > 0.01 ) + { + vUp.Normalize(); + vSide = vUp.Cross( vForward ); + vSide.Normalize(); + } + else + { + vSide = vForward.Cross( Vector3( vForward.x, vForward.y+1.0f, vForward.z ) ); + vSide.Normalize(); + vUp = vForward.Cross( vSide ); + vUp.Normalize(); + } + + // Generate a quaternion + Quaternion q( vSide, vUp, vForward ); + + Matrix rotMatrix; + rotMatrix.SetXAxis( vSide ); + rotMatrix.SetYAxis( vUp ); + rotMatrix.SetZAxis( vForward ); + + // Generate a matrix from the quaternion, check they are the same + Matrix m( q ); + DALI_TEST_EQUALS( m.GetXAxis(), vSide, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( m.GetYAxis(), vUp, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( m.GetZAxis(), vForward, 0.001f, TEST_LOCATION ); + + // Rotate an arbitrary vector by both quaternion and rotation matrix, + // check the result is the same + + Vector4 aVector( 2.043f, 12.8f, -3.872f, 1.0f ); + Vector3 aVectorRotatedByQ = q.Rotate( Vector3( aVector ) ); + Vector4 aVectorRotatedByR = rotMatrix*aVector; + DALI_TEST_EQUALS( aVectorRotatedByQ, Vector3( aVectorRotatedByR ), 0.001f, TEST_LOCATION ); + } + } + } + END_TEST; +} + +int UtcDaliQuaternionCtorTwoVectorsP(void) +{ + Vector3 v0( 1.0f, 2.0f, 3.0f ); + Vector3 v1( -2.0f, 10.0f, -1.0f ); + v0.Normalize(); + v1.Normalize(); + Quaternion q( v0, v1 ); + + DALI_TEST_EQUALS( q*v0, v1, 0.001, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionAsVectorP(void) +{ + Vector4 v( 1.0f, 0.1f, 0.2f, 0.3f ); + Quaternion q( v ); + + DALI_TEST_EQUALS( v, q.AsVector(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionToAxisAngleVector3P(void) +{ + Quaternion q( 0.932f, 1.1f, 3.4f, 2.7f ); + Radian angle; + Vector3 axis; + bool converted = q.ToAxisAngle( axis, angle ); + DALI_TEST_EQUALS( converted, true, TEST_LOCATION ); + DALI_TEST_EQUALS( angle.radian, 0.74f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( axis.x, 3.03f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( axis.y, 9.38f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( axis.z, 7.45f, 0.01f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionToAxisAngleVector3N(void) +{ + Quaternion q( 1, 2, 3, 4 ); + Radian angle; + Vector3 axis; + bool converted = q.ToAxisAngle( axis, angle ); + DALI_TEST_EQUALS( converted, false, TEST_LOCATION ); + DALI_TEST_EQUALS( angle.radian, 0.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( axis.x, 0.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( axis.y, 0.0f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( axis.z, 0.0f, 0.01f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionSetEulerP(void) +{ + // Test from euler angles + Quaternion e1; + e1.SetEuler( Dali::ANGLE_45, Dali::ANGLE_0, Dali::ANGLE_0 ); + Vector4 r1( 0.383f, 0.0f, 0.0f, 0.924f ); + + Quaternion e2; + e2.SetEuler( Dali::ANGLE_0, Radian( Degree( 75 ) ), Dali::ANGLE_0 ); + Vector4 r2( 0.0f, 0.609f, 0.0f, 0.793f ); + + Quaternion e3; + e3.SetEuler( Dali::ANGLE_0, Dali::ANGLE_0, Dali::ANGLE_135 ); + Vector4 r3( 0.0f, 0.0f, 0.924f, 0.383f ); + + Quaternion e4; + e4.SetEuler( Radian( Degree( 71 ) ), Radian( Degree( 36 ) ), Radian( Degree( 27 ) ) ); + Vector4 r4( 0.478f, 0.374f, 0.006f, 0.795f ); + + Quaternion e5; + e5.SetEuler( Radian( Degree( -31 ) ), Radian( Degree( -91 ) ), Radian( Degree( -173 ) ) ); + Vector4 r5( -0.697f, 0.145f, -0.686f, -0.149f ); + + DALI_TEST_EQUALS( e1.AsVector(), r1, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( e2.AsVector(), r2, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( e3.AsVector(), r3, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( e4.AsVector(), r4, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( e5.AsVector(), r5, 0.001, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionEulerAnglesP(void) +{ + Quaternion q1( 0.924f, 0.383f, 0.0f, 0.0f ); + Vector4 r1( Radian( Degree( 45 ) ), 0.0f, 0.0f, 0.0f ); + + Quaternion q2( 0.793f, 0.0f, 0.609f, 0.0f ); + Vector4 r2( 0.0f, Radian( Degree( 75 ) ), 0.0f, 0.0f ); + + Quaternion q3( 0.383f, 0.0f, 0.0f, 0.924f ); + Vector4 r3( 0.0f, 0.0f, Radian( Degree( 135 ) ), 0.0f ); + + Quaternion q4( 0.795f, 0.478f, 0.374f, 0.006f ); + Vector4 r4( Radian( Degree( 71 ) ), Radian( Degree( 36 ) ), Radian( Degree( 27 ) ), 0.0f ); + + Quaternion q5( -0.149f, -0.697f, 0.145f, -0.686f ); + Vector4 r5( Radian( Degree( 148.0 ) ), Radian( Degree( -88.2 ) ), Radian( Degree( 8.0 ) ), 0.0f ); + + DALI_TEST_EQUALS( q1.EulerAngles(), r1, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( q2.EulerAngles(), r2, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( q3.EulerAngles(), r3, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( q4.EulerAngles(), r4, 0.01, TEST_LOCATION ); + DALI_TEST_EQUALS( q5.EulerAngles(), r5, 0.01, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliQuaternionToMatrixP01(void) +{ + Quaternion q( Radian( 0.69813 ), Vector3( 1.0f, 0.0f, 0.0f ) ); // 40 degree rotation around X axis + + // Result calculated using a different maths library ( with appropriate row/col ordering ) + + float els[] = { 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.766f, 0.643f, 0.0f, + 0.0f, -0.643f, 0.766f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; + Matrix mRes( els ); + Matrix m( q ); + + DALI_TEST_EQUALS( m, mRes, 0.01, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionToMatrixP02(void) +{ + // rotation around arbitrary axis + Quaternion q2( Radian( -1.23918f ), Vector3( 7.0f, -13.0f, 11.0f ) ); + + float els[] = { 0.423f, -0.746f, -0.514f, 0.00f, + 0.384f, 0.662f, -0.644f, 0.00f, + 0.821f, 0.075f, 0.566f, 0.00f, + 0.000f, 0.000f, 0.000f, 1.00f }; + Matrix mRes2( els ); + + Matrix m2( q2 ); + + DALI_TEST_EQUALS( m2, mRes2, 0.01, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliQuaternionOperatorAdditionP(void) +{ + Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f ); + Quaternion q2( 0.0f, 0.609f, 0.0f, 0.793f ); + + Quaternion r1( 0.383f, 0.609f, 0.0f, 1.717f ); + + DALI_TEST_EQUALS( q1+q2, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorSubtractionP(void) +{ + Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f ); + Quaternion q2( 0.383f, 0.690f, 0.234f, 1.917f ); + + Quaternion r1( 0.0f, 0.240f, 0.111f, 0.993f ); + + DALI_TEST_EQUALS( q2-q1, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionConjugateP(void) +{ + float s1 = 0.784f; Vector3 v1( 0.045f, 0.443f, 0.432f ); + float s2 = 0.697f; Vector3 v2( 0.612, 0.344, -0.144 ); + + Quaternion q1( s1, v1.x, v1.y, v1.z ); + Quaternion q2( s2, v2.x, v2.y, v2.z ); + q1.Conjugate(); + q2.Conjugate(); + + Quaternion r1( s1, -v1.x, -v1.y, -v1.z ); + Quaternion r2( s2, -v2.x, -v2.y, -v2.z ); + + DALI_TEST_EQUALS( q1, r1, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( q2, r2, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorMultiplicationQuaternionP(void) +{ + float s1=0.784f; Vector3 v1( 0.045f, 0.443f, 0.432f ); + float s2=0.697f; Vector3 v2( 0.612, 0.344, -0.144 ); + + Quaternion q1( s1, v1.x, v1.y, v1.z ); + Quaternion q2( s2, v2.x, v2.y, v2.z ); + + Vector3 vp = v1.Cross( v2 ) + v2*s1 + v1*s2; + Quaternion r1( s1*s2-v1.Dot( v2 ), vp.x, vp.y, vp.z ); + + DALI_TEST_EQUALS( q1*q2, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + +// Quaternion * vector == Vector rotation +int UtcDaliQuaternionOperatorMultiplicationVector3P(void) +{ + // Rotation of vector p = ( x,y,z ) by Quaternion q == q [0,p] q^-1 + Vector3 v( 2, 3, 4 ); + Quaternion q( Radian( Degree( 72 ) ), Vector3::ZAXIS ); + Quaternion qI = q; + qI.Invert(); + Quaternion qv( 0.0f, v.x, v.y, v.z ); + Quaternion r1 = ( q * qv ) * qI; + + Vector3 r2 = q * v; + + DALI_TEST_EQUALS( r1.mVector.x, r2.x, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( r1.mVector.y, r2.y, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( r1.mVector.z, r2.z, 0.001, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorMultiplicationFloatP01(void) +{ + // Rotation of vector p = ( x,y,z ) by Quaternion q == q [0,p] q^-1 + Quaternion q( Vector4( 0.1f, 0.2f, 0.3f, 1.0f ) ); + Quaternion q2 = q * 2.f; + Vector4 v2( 0.2f, 0.4f, 0.6f, 2.0f ); + + DALI_TEST_EQUALS( q2.AsVector(), v2, 0.001, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorMultiplicationFloatP02(void) +{ + Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f ); + Quaternion r1( 2.0f* 0.383f, 0.0f, 0.0f, 2.0f * 0.924f ); + + DALI_TEST_EQUALS( q1 * 2.0f, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorMultiplicationFloatP03(void) +{ + Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f ); + Quaternion r1( 0.5f* 0.383f, 0.0f, 0.0f, 0.5f * 0.924f ); + + DALI_TEST_EQUALS( q1 / 2.0f, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorDivisionQuaternionP(void) +{ + Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f ); + Quaternion q2( 0.0f, 0.609f, 0.0f, 0.793f ); + + // q1 / q2 = q1 * q2^-1 + // q2^-1 = q2* / ||q2||^2 + // = Conjugate of q2 / Square of Norm of q2 + + Quaternion r1 = q2; + r1.Conjugate(); + r1 *= 1.0f/q2.LengthSquared(); + Quaternion r2 = q1 * r1; + + DALI_TEST_EQUALS( q1 / q2, r2, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorDivisionFloatP(void) +{ + Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f ); + Quaternion r1( 2.0f* 0.383f, 0.0f, 0.0f, 2.0f * 0.924f ); + + DALI_TEST_EQUALS( q1, r1/2.0f, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorDivideAssignedFloatP(void) +{ + Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f ); + Quaternion r1( 2.0f* 0.383f, 0.0f, 0.0f, 2.0f * 0.924f ); + r1 /= 2.0f; + + DALI_TEST_EQUALS( q1, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorNegationP(void) +{ + Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f ); + Quaternion r1( -0.383f, -0.0f, -0.0f, -0.924f ); + + DALI_TEST_EQUALS( -q1, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorAddAssignP(void) +{ + Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f ); + Quaternion q2( 0.0f, 0.609f, 0.0f, 0.793f ); + + Quaternion r1( 0.383f, 0.609f, 0.0f, 1.717f ); + + q1 += q2; + DALI_TEST_EQUALS( q1, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorSubtractAssignP(void) +{ + Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f ); + Quaternion q2( 0.383f, 0.690f, 0.234f, 1.917f ); + + Quaternion r1( 0.0f, 0.240f, 0.111f, 0.993f ); + q2 -= q1; + DALI_TEST_EQUALS( q2, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorMultiplyAssignQuaternionP(void) +{ + float s1=0.784f; Vector3 v1( 0.045f, 0.443f, 0.432f ); + float s2=0.697f; Vector3 v2( 0.612, 0.344, -0.144 ); + + Quaternion q1( s1, v1.x, v1.y, v1.z ); + Quaternion q2( s2, v2.x, v2.y, v2.z ); + + Quaternion r3 = q2 * q1; + q2 *= q1; + DALI_TEST_EQUALS( q2, r3, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorMultiplyAssignFloatP01(void) +{ + Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f ); + float scale = 2.5f; + Quaternion r1( scale*0.383f, scale*0.450f, scale*0.123f, scale*0.924f ); + q1 *= scale; + DALI_TEST_EQUALS( q1, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorMultiplyAssignFloatP02(void) +{ + Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f ); + float scale = 2.5f; + Quaternion r1( 0.383f/scale, 0.450f/scale, 0.123f/scale, 0.924f/scale ); + q1 /= scale; + DALI_TEST_EQUALS( q1, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOperatorEqualityP(void) +{ + Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f ); + Quaternion q2( 0.383f, 0.450f, 0.123f, 0.924f ); + Quaternion q3( 0.383f, 0.450f, 0.123f, 0.800f ); + Quaternion q4( 0.383f, 0.450f, 0.100f, 0.800f ); + Quaternion q5( 0.383f, 0.100f, 0.100f, 0.800f ); + Quaternion q6( 0.100f, 0.100f, 0.100f, 0.800f ); + + Quaternion q7( -0.383f, -0.450f, -0.123f, -0.924f ); + Quaternion q8( -0.383f, -0.450f, -0.123f, 0.924f ); + Quaternion q9( -0.383f, -0.450f, 0.123f, 0.924f ); + Quaternion q10( -0.383f, 0.450f, 0.123f, 0.924f ); + + DALI_TEST_CHECK( q1 == q2 ); + DALI_TEST_CHECK( !( q1 == q3 ) ); + DALI_TEST_CHECK( !( q1 == q4 ) ); + DALI_TEST_CHECK( !( q1 == q5 ) ); + DALI_TEST_CHECK( !( q1 == q6 ) ); + DALI_TEST_CHECK( ( q1 == q7 ) ); + DALI_TEST_CHECK( !( q1 == q8 ) ); + DALI_TEST_CHECK( !( q1 == q9 ) ); + DALI_TEST_CHECK( !( q1 == q10 ) ); + END_TEST; +} + +int UtcDaliQuaternionOperatorInequalityP(void) +{ + Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f ); + Quaternion q2( 0.383f, 0.450f, 0.123f, 0.924f ); + Quaternion q3( -0.383f, -0.0f, -0.0f, -0.924f ); + DALI_TEST_CHECK( !( q1 != q2 ) ); + DALI_TEST_CHECK( q1 != q3 ); + END_TEST; +} + +int UtcDaliQuaternionLengthP(void) +{ + Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f ); + float length = sqrtf( 0.383f*0.383f + 0.450f*0.450f + 0.123f*0.123f + 0.924f*0.924f ); + DALI_TEST_EQUALS( q1.Length(), length, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionLengthSquaredP(void) +{ + Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f ); + float lengthSquared = 0.383f*0.383f + 0.450f*0.450f + 0.123f*0.123f + 0.924f*0.924f; + DALI_TEST_EQUALS( q1.LengthSquared(), lengthSquared, 0.01f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionNormalizeP(void) +{ + Quaternion q1( 0.118f, 0.692f, -0.127f, 0.701f ); + Quaternion q2 = q1; + q2 *= 5.0f; + q2.Normalize(); + DALI_TEST_EQUALS( q1, q2, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionNormalizedP(void) +{ + Quaternion q1( 0.118f, 0.692f, -0.127f, 0.701f ); + Quaternion q2 = q1; + q2 *= 5.0f; + DALI_TEST_EQUALS( q1, q2.Normalized(), 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionIsIdentityP(void) +{ + Quaternion q( 1.0f, 0.0f, 0.0f, 0.0f ); + DALI_TEST_EQUALS( q.IsIdentity(), true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionIsIdentityN(void) +{ + Quaternion q( 1.0f, 0.1f, 0.0f, 0.0f ); + DALI_TEST_EQUALS( q.IsIdentity(), false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionInvertP(void) +{ + Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f ); + + // q1^-1 = q1* / ||q1||^2 + // = Conjugate of q1 / Square of Norm of q1 + + Quaternion r1 = q1; + r1.Conjugate(); + r1 *= 1.0f/q1.LengthSquared(); + + Quaternion q2 = q1; + q2.Invert(); + DALI_TEST_EQUALS( q2, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliQuaternionDotP(void) +{ + // q.q' = s*s' + v dot v' + float s1 = 0.784f; Vector3 v1( 0.045f, 0.443f, 0.432f ); + float s2 = 0.697f; Vector3 v2( 0.612, 0.344, -0.144 ); + + Quaternion q1( s1, v1.x, v1.y, v1.z ); + Quaternion q2( s2, v2.x, v2.y, v2.z ); + + float r1 = s1*s2 + v1.Dot( v2 ); + + DALI_TEST_EQUALS( Quaternion::Dot( q1, q2 ), r1, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliQuaternionRotateVector3P(void) +{ + // Rotation of vector p = ( x,y,z ) by Quaternion q == q [0,p] q^-1 + Vector3 v( 2, 3, 4 ); + Quaternion q( Radian( Degree( 72 ) ), Vector3::ZAXIS ); + Quaternion qI = q; + qI.Invert(); + Quaternion qv( 0.0f, v.x, v.y, v.z ); + Quaternion r1 = q * qv * qI; + + Vector3 r2 = q.Rotate( v ); + + DALI_TEST_EQUALS( r1.mVector.x, r2.x, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( r1.mVector.y, r2.y, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( r1.mVector.z, r2.z, 0.001f, TEST_LOCATION ); + + DALI_TEST_EQUALS( q.Rotate( v ), q*v, 0.001f, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliQuaternionRotateVector4P(void) +{ + // Rotation of vector p = ( x,y,z ) by Quaternion q == q [0,p] q^-1 + Vector4 v( 2, 3, 4, 5 ); + Quaternion q( Radian( Degree( 72 ) ), Vector3::ZAXIS ); + Quaternion qI = q; + qI.Invert(); + Quaternion qv( 0.0f, v.x, v.y, v.z ); + Quaternion r1 = q * qv * qI; + + Vector4 r2 = q.Rotate( v ); + + DALI_TEST_EQUALS( r1.mVector.x, r2.x, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( r1.mVector.y, r2.y, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( r1.mVector.z, r2.z, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( r1.mVector.w, 0.0f, 0.001f, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliQuaternionExpP01(void) +{ + Quaternion q1( 0.0f, 1.0f, 1.2f, 1.3f ); + Quaternion q2 = q1.Exp(); + Quaternion r2( -0.4452, 0.4406, 0.5287, 0.5728 ); + + DALI_TEST_EQUALS( q2.Length(), 1.0f, 0.01f, TEST_LOCATION ); + + DALI_TEST_EQUALS( q2, r2, 0.001f, TEST_LOCATION ); + + // Note, this trick only works when |v| < pi, which it is! + Quaternion q3 = q2.Log(); + DALI_TEST_EQUALS( q1, q3, 0.01f, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliQuaternionExpP02(void) +{ + Quaternion q1( 0.0f, 0.0f, 0.0f, 0.0f ); + Quaternion q2 = q1.Exp(); + Quaternion r2( 1.0f, 0.0f, 0.0f, 0.0f ); + + DALI_TEST_EQUALS( q2.Length(), 1.0f, 0.01f, TEST_LOCATION ); + + DALI_TEST_EQUALS( q2, r2, 0.001f, TEST_LOCATION ); + + // Note, this trick only works when |v| < pi, which it is! + Quaternion q3 = q2.Log(); + DALI_TEST_EQUALS( q1, q3, 0.01f, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliQuaternionExpN(void) +{ + Quaternion q( Radian( 0.0f ), Vector3(5.0f, 6.0f, 7.0f) ); + + // q.w is non-zero. Should assert. + try + { + q.Exp(); + DALI_TEST_CHECK( false ); + } + catch( DaliException& e ) + { + DALI_TEST_CHECK( true ); + } + END_TEST; +} + + +int UtcDaliQuaternionLogP01(void) +{ + Quaternion q( Radian( Math::PI*0.73f ), Vector3(2,3,4) ); + Quaternion q2 = q; + q2.Normalize(); + + Quaternion r = q2.Log(); + DALI_TEST_EQUALS( r.mVector.w, 0.0f, 0.01f, TEST_LOCATION ); + + Quaternion r2 = r.Exp(); + DALI_TEST_EQUALS( r2, q2, 0.01f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionLogP02(void) +{ + Quaternion q1( 1.0f, 0.0f, 0.0f, 0.0f ); + Quaternion r1( 0.0f, 0.0f, 0.0f, 0.0f ); + + Quaternion q2 = q1.Log(); + + DALI_TEST_EQUALS( q2, r1, 0.01f, TEST_LOCATION ); + + Quaternion q3 = q2.Exp(); + DALI_TEST_EQUALS( q1, q3, 0.01f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionLerpP(void) +{ + Quaternion q1( Radian( Degree( -80 ) ), Vector3( 0.0f, 0.0f, 1.0f ) ); + Quaternion q2( Radian( Degree( 80 ) ), Vector3( 0.0f, 0.0f, 1.0f ) ); + + Quaternion p = Quaternion::Lerp( q1, q2, 0.0f ); + DALI_TEST_EQUALS( p, q1, 0.001f, TEST_LOCATION ); + + p = Quaternion::Lerp( q1, q2, 1.0f ); + DALI_TEST_EQUALS( p, q2, 0.001f, TEST_LOCATION ); + + p = Quaternion::Lerp( q1, q2, 0.5f ); + Quaternion r1 = ( q1 + q2 ) * 0.5f; + r1.Normalize(); + DALI_TEST_EQUALS( p, r1, 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionSlerpP01(void) +{ + Quaternion q1(Radian(M_PI/4.0f), Vector3(0.0f, 0.0f, 1.0f)); + Quaternion q2(Radian(-M_PI/4.0f), Vector3(0.0f, 0.0f, 1.0f)); + + Quaternion q = Quaternion::Slerp( q1, q2, 0.0f ); + DALI_TEST_EQUALS( q, q1, 0.001, TEST_LOCATION ); + + q = Quaternion::Slerp( q1, q2, 1.0f ); + DALI_TEST_EQUALS( q, q2, 0.001, TEST_LOCATION ); + + // @ 25%, will be at M_PI/8 + q = Quaternion::Slerp( q1, q2, 0.25f ); + Vector3 axis; + Radian angle; + bool converted = q.ToAxisAngle( axis, angle ); + DALI_TEST_EQUALS( converted, true, TEST_LOCATION ); + DALI_TEST_EQUALS( angle.radian, Math::PI/8.0f, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( axis.x, 0.0f, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( axis.y, 0.0f, 0.001, TEST_LOCATION ); + DALI_TEST_EQUALS( axis.z, 1.0f, 0.001, TEST_LOCATION ); + END_TEST; +} + + + +int UtcDaliQuaternionSlerpP02(void) +{ + Quaternion q1( Dali::ANGLE_30, Vector3(0.0f, 0.0f, 1.0f)); + Quaternion q2( Dali::ANGLE_90, Vector3(0.0f, 0.0f, 1.0f)); + + Quaternion q = Quaternion::Slerp( q1, q2, 0.0f ); + + DALI_TEST_EQUALS( q, q1, 0.001, TEST_LOCATION ); + + q = Quaternion::Slerp( q1, q2, 1.0f ); + + DALI_TEST_EQUALS( q, q2, 0.001, TEST_LOCATION ); + + // @ 50%, will be at M_PI/3 around z + q = Quaternion::Slerp( q1, q2, 0.5f ); + + Quaternion r( Dali::ANGLE_60, Vector3( 0.0f, 0.0f, 1.0f)); + DALI_TEST_EQUALS( q, r, 0.001, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliQuaternionSlerpP03(void) +{ + Quaternion q1( Radian( Degree( 125 ) ), Vector3( 0.0f, 0.0f, 1.0f ) ); + Quaternion q2( Radian( Degree( -125 ) ), Vector3( 0.002f, 0.001f, 1.001f ) ); + + Quaternion q = Quaternion::Slerp( q1, q2, 0.0f ); + DALI_TEST_EQUALS( q, q1, 0.001, TEST_LOCATION ); + + q = Quaternion::Slerp( q1, q2, 1.0f ); + DALI_TEST_EQUALS( q, q2, 0.001, TEST_LOCATION ); + + q = Quaternion::Slerp(q1, q2, 0.05f); + Vector3 axis; + Radian angle; + bool converted = q.ToAxisAngle(axis, angle); + DALI_TEST_EQUALS(converted, true, TEST_LOCATION); + + DALI_TEST_EQUALS( axis.x, 0.0f, 0.01, TEST_LOCATION ); + DALI_TEST_EQUALS( axis.y, 0.0f, 0.01, TEST_LOCATION ); + DALI_TEST_EQUALS( axis.z, 1.0f, 0.01, TEST_LOCATION ); + END_TEST; +} + + + +int UtcDaliQuaternionSlerpP04(void) +{ + Quaternion q1( Radian( Degree( 120 ) ), Vector3( 0.0f, 0.0f, 1.0f ) ); + Quaternion q2( Radian( Degree( 130 ) ), Vector3( 0.0f, 0.0f, 1.0f ) ); + + Quaternion q = Quaternion::Slerp( q1, q2, 0.0f ); + DALI_TEST_EQUALS( q, q1, 0.001, TEST_LOCATION ); + + q = Quaternion::Slerp( q1, q2, 1.0f ); + DALI_TEST_EQUALS( q, q2, 0.001, TEST_LOCATION ); + + q = Quaternion::Slerp(q1, q2, 0.5f); + Vector3 axis; + Radian angle; + bool converted = q.ToAxisAngle(axis, angle); + DALI_TEST_EQUALS(converted, true, TEST_LOCATION); + DALI_TEST_EQUALS(angle.radian, float(Radian(Degree(125))), 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(axis.x, 0.0f, 0.01, TEST_LOCATION); + DALI_TEST_EQUALS(axis.y, 0.0f, 0.01, TEST_LOCATION); + DALI_TEST_EQUALS(axis.z, 1.0f, 0.01, TEST_LOCATION); + END_TEST; +} + + + +int UtcDaliQuaternionSlerpNoInvertP01(void) +{ + Quaternion q1( Dali::ANGLE_45, Vector3(0.0f, 0.0f, 1.0f)); + Quaternion q2(-Dali::ANGLE_45, Vector3(0.0f, 0.0f, 1.0f)); + + Quaternion q = Quaternion::SlerpNoInvert( q1, q2, 0.0f ); + DALI_TEST_EQUALS( q, q1, 0.001, TEST_LOCATION ); + + q = Quaternion::SlerpNoInvert( q1, q2, 1.0f ); + DALI_TEST_EQUALS( q, q2, 0.001, TEST_LOCATION ); + + // @ 25%, will be at M_PI/8 + q = Quaternion::SlerpNoInvert(q1, q2, 0.25f); + Vector3 axis; + Radian angle; + bool converted = q.ToAxisAngle(axis, angle); + DALI_TEST_EQUALS(converted, true, TEST_LOCATION); + DALI_TEST_EQUALS(angle.radian, Math::PI/8.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(axis.x, 0.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(axis.y, 0.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(axis.z, 1.0f, 0.001, TEST_LOCATION); + END_TEST; +} + + +int UtcDaliQuaternionSlerpNoInvertP02(void) +{ + Quaternion q1( Radian( Degree( 120 ) ), Vector3( 0.0f, 0.0f, 1.0f ) ); + Quaternion q2( Radian( Degree( 130 ) ), Vector3( 0.0f, 0.0f, 1.0f ) ); + + Quaternion q = Quaternion::SlerpNoInvert( q1, q2, 0.0f ); + DALI_TEST_EQUALS( q, q1, 0.001, TEST_LOCATION ); + + q = Quaternion::SlerpNoInvert( q1, q2, 1.0f ); + DALI_TEST_EQUALS( q, q2, 0.001, TEST_LOCATION ); + + q = Quaternion::SlerpNoInvert(q1, q2, 0.5f); + Vector3 axis; + Radian angle; + bool converted = q.ToAxisAngle(axis, angle); + DALI_TEST_EQUALS(converted, true, TEST_LOCATION); + DALI_TEST_EQUALS(angle.radian, float(Radian(Degree(125))), 0.01f, TEST_LOCATION); + DALI_TEST_EQUALS(axis.x, 0.0f, 0.01, TEST_LOCATION); + DALI_TEST_EQUALS(axis.y, 0.0f, 0.01, TEST_LOCATION); + DALI_TEST_EQUALS(axis.z, 1.0f, 0.01, TEST_LOCATION); + END_TEST; +} + + +int UtcDaliQuaternionSquadP(void) +{ + Quaternion q1( Radian( Degree( 45 ) ), Vector3( 0.0f, 0.0f, 1.0f ) ); + Quaternion q1out( Radian( Degree( 40 ) ), Vector3( 0.0f, 1.0f, 2.0f ) ); + Quaternion q2in( Radian( Degree( 35 ) ), Vector3( 0.0f, 2.0f, 3.0f ) ); + Quaternion q2( Radian( Degree( 30 ) ), Vector3( 0.0f, 1.0f, 3.0f ) ); + + Quaternion q = Quaternion::Squad( q1, q2, q1out, q2in, 0.0f ); + DALI_TEST_EQUALS( q, q1, 0.001f, TEST_LOCATION ); + + q = Quaternion::Squad( q1, q2, q1out, q2in, 1.0f ); + DALI_TEST_EQUALS( q, q2, 0.001f, TEST_LOCATION ); + + // Don't know what actual value should be, but can make some informed guesses. + q = Quaternion::Squad(q1, q2, q1out, q2in, 0.5f); + Radian angle; + Vector3 axis; + q.Normalize(); + q.ToAxisAngle( axis, angle ); + + if( angle < 0.0f ) + { + q = -q; // Might get negative quat + q.ToAxisAngle( axis, angle ); + } + float deg = Degree(angle).degree; + DALI_TEST_CHECK(deg >= 0 && deg <= 90); + DALI_TEST_CHECK(axis.y > 0); + DALI_TEST_CHECK(axis.z > 0); + END_TEST; +} + +int UtcDaliAngleBetweenP(void) +{ + Quaternion q1( ANGLE_45, ANGLE_0, ANGLE_0 ); + Quaternion q2(Radian(Degree(47)), ANGLE_0, ANGLE_0 ); + DALI_TEST_EQUALS(Quaternion::AngleBetween(q1, q2), fabsf(Radian(Degree(45)) - Radian(Degree(47))), 0.001f, TEST_LOCATION); + + Quaternion q3( Radian( Degree( 80 ) ), Vector3::YAXIS ); + Quaternion q4( Radian( Degree( 90 ) ), Vector3::YAXIS ); + DALI_TEST_EQUALS( Quaternion::AngleBetween( q3, q4 ), fabsf( Radian( Degree( 80 ) ) - Radian( Degree( 90 ) ) ), 0.001f, TEST_LOCATION ); + + Quaternion q5( Radian( Degree( 0 ) ), Vector3::YAXIS ); + Quaternion q6( Radian( Degree( 90 ) ), Vector3::XAXIS ); + DALI_TEST_EQUALS( Quaternion::AngleBetween( q5, q6 ), fabsf( Radian( Degree( 0 ) ) - Radian( Degree( 90 ) ) ), 0.001f, TEST_LOCATION ); + + Quaternion q7( Radian( Degree( 0 ) ), Vector3::YAXIS ); + Quaternion q8( Radian( Degree( 0 ) ), Vector3::XAXIS ); + DALI_TEST_EQUALS( Quaternion::AngleBetween( q7, q8 ), fabsf( Radian( Degree( 0 ) ) - Radian( Degree( 0 ) ) ), 0.001f, TEST_LOCATION ); + + Quaternion q9( Radian( Degree( 0 ) ), Vector3::XAXIS ); + Quaternion q10( Radian( Degree( 180 ) ), Vector3::XAXIS ); + DALI_TEST_EQUALS( Quaternion::AngleBetween( q9, q10 ), fabsf( Radian( Degree( 0 ) ) - Radian( Degree( 180 ) ) ), 0.001f, TEST_LOCATION ); + + Quaternion q11( Radian( Degree( 1 ) ), Vector3::YAXIS ); + Quaternion q12( Radian( Degree( 240 ) ), Vector3::YAXIS ); + DALI_TEST_EQUALS( Quaternion::AngleBetween( q11, q12 ), fabsf( Radian( Degree( 1 - 240 + 360 ) ) ), 0.001f, TEST_LOCATION ); + + Quaternion q13( Radian( Degree( 240 ) ), Vector3::YAXIS ); + Quaternion q14( Radian( Degree( 1 ) ), Vector3::YAXIS ); + DALI_TEST_EQUALS( Quaternion::AngleBetween( q13, q14 ), fabsf( Radian( Degree( 240 - 1 - 360 ) ) ), 0.001f, TEST_LOCATION ); + + Quaternion q15( Radian( Degree( 240 ) ), Vector3::YAXIS ); + Quaternion q16( Radian( Degree( 1 ) ), Vector3::ZAXIS ); + DALI_TEST_EQUALS( Quaternion::AngleBetween( q15, q16 ), Quaternion::AngleBetween( q16, q15 ), 0.001f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliQuaternionOStreamOperatorP(void) +{ + std::ostringstream oss; + + Quaternion quaternion( Dali::ANGLE_180, Vector3::YAXIS ); + + oss << quaternion; + + std::string expectedOutput = "[ Axis: [0, 1, 0], Angle: 180 degrees ]"; + + DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION ); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Radian.cpp b/automated-tests/src/dali/utc-Dali-Radian.cpp new file mode 100644 index 0000000..cfb3528 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Radian.cpp @@ -0,0 +1,150 @@ +#include + +#include +#include +#include + +using namespace Dali; + + +void utc_dali_radian_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_radian_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +// Positive test case for constructors +int UtcDaliRadianConstructors01(void) +{ + // Default constructor, does not initialise the value + Radian radian0( 0.0f ); + + // Test float assignment operator + radian0 = Math::PI; + DALI_TEST_EQUALS( float(radian0), Math::PI, 0.001f, TEST_LOCATION ); + + // Constructor from float value + Radian radian1( Math::PI ); + DALI_TEST_EQUALS( float(radian1), Math::PI, 0.001f, TEST_LOCATION ); + + // Constructor from a Degree + Radian radian2( Degree( 180.0f ) ); + DALI_TEST_EQUALS( float(radian2), Math::PI, 0.001f, TEST_LOCATION ); + + // Assignment from Degree + Radian radian3( 0.0f ); + radian3 = Degree( 180.0f ); + DALI_TEST_EQUALS( float(radian3), Math::PI, 0.001f, TEST_LOCATION ); + END_TEST; +} + +// Positive test case for comparison +int UtcDaliRadianComparison01(void) +{ + // Comparison between radians + Radian radian0( Math::PI_2 ); + Radian radian1( Math::PI_2 ); + Radian radian2( Math::PI ); + + DALI_TEST_CHECK( radian0 == radian1 ); + DALI_TEST_CHECK( radian0 != radian2 ); + + // Comparison between radian to degree + Radian radian3( Math::PI ); + Radian radian4( Math::PI_2 ); + Degree degree0( 180.0f ); + + DALI_TEST_CHECK( radian3 == Radian(degree0) ); + DALI_TEST_CHECK( radian4 != Radian(degree0) ); + + // Comparison with float + Radian radian5( Math::PI_2 ); + + DALI_TEST_CHECK( radian5 == Math::PI_2 ); + DALI_TEST_CHECK( radian5 != Math::PI ); + + END_TEST; +} + + +// test case for cast operators +int UtcDaliRadianCastOperators01(void) +{ + Radian radian0( Math::PI ); + + const float& value0( radian0.radian ); + DALI_TEST_EQUALS( value0, Math::PI, 0.001f, TEST_LOCATION ); + + radian0 = Math::PI_2; + DALI_TEST_EQUALS( value0, Math::PI_2, 0.001f, TEST_LOCATION ); + + float value1( radian0 ); + DALI_TEST_EQUALS( value1, Math::PI_2, 0.001f, TEST_LOCATION ); + + radian0 = Math::PI; + DALI_TEST_EQUALS( float(radian0), Math::PI, 0.001f, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliRadianCastOperatorEquals(void) +{ + Radian a(Math::PI_2); + Radian b(Math::PI_2); + Radian c(Math::PI); + + DALI_TEST_EQUALS( a == a, true, TEST_LOCATION ); + DALI_TEST_EQUALS( a == b, true, TEST_LOCATION ); + DALI_TEST_EQUALS( a == c, false, TEST_LOCATION ); + DALI_TEST_EQUALS( Degree(c) == c, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRadianCastOperatorNotEquals(void) +{ + Radian a(Math::PI_2); + Radian b(Math::PI_2); + Radian c(Math::PI); + + DALI_TEST_EQUALS( a != a, false, TEST_LOCATION ); + DALI_TEST_EQUALS( a != b, false, TEST_LOCATION ); + DALI_TEST_EQUALS( a != c, true, TEST_LOCATION ); + DALI_TEST_EQUALS( Degree(a) != c, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRadianCastOperatorLessThan(void) +{ + Radian a(Math::PI_4); + Radian b(Math::PI_2); + Radian c(Math::PI); + Radian d(2.0f*Math::PI); + Radian e(-Math::PI); + + DALI_TEST_EQUALS(a < a, false, TEST_LOCATION); + DALI_TEST_EQUALS(a < b, true, TEST_LOCATION); + DALI_TEST_EQUALS(a < c, true, TEST_LOCATION); + DALI_TEST_EQUALS(a < d, true, TEST_LOCATION); + DALI_TEST_EQUALS(a < e, false, TEST_LOCATION); + + DALI_TEST_EQUALS(b < a, false, TEST_LOCATION); + DALI_TEST_EQUALS(b < b, false, TEST_LOCATION); + DALI_TEST_EQUALS(c < b, false, TEST_LOCATION); + DALI_TEST_EQUALS(d < b, false, TEST_LOCATION); + DALI_TEST_EQUALS(e < b, true, TEST_LOCATION); + + DALI_TEST_EQUALS( Radian(Math::PI_2) < Degree(180.0f), true, TEST_LOCATION); + DALI_TEST_EQUALS( Radian(Math::PI_2) < Degree(90.0f), false, TEST_LOCATION); + DALI_TEST_EQUALS( Radian(Math::PI_2) > Degree(45.0f), true, TEST_LOCATION); + + DALI_TEST_EQUALS( Degree(180.0f) > Radian(Math::PI_2), true, TEST_LOCATION); + DALI_TEST_EQUALS( Degree(90.0f) > Radian(Math::PI_2), false, TEST_LOCATION); + DALI_TEST_EQUALS( Degree(45.0f) < Radian(Math::PI_2), true, TEST_LOCATION); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Random.cpp b/automated-tests/src/dali/utc-Dali-Random.cpp new file mode 100644 index 0000000..a3c8670 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Random.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + + +int UtcDaliRandomRangeMethod(void) +{ + TestApplication application; // Reset all test adapter return codes + + float a=0, b=1; + for(size_t i=0; i<100; i++) + { + float r = Dali::Random::Range(a, b); + DALI_TEST_CHECK(r >= a && r <= b); + } + + a=100; b=-100; + for(size_t i=0; i<100; i++) + { + float r = Dali::Random::Range(a, b); + DALI_TEST_CHECK(r >= b && r <= a); + } + END_TEST; +} + + +int UtcDaliRandomAxisMethod(void) +{ + TestApplication application; // Reset all test adapter return codes + + for(size_t i=0; i<100; i++) + { + Vector4 axis = Dali::Random::Axis(); + DALI_TEST_EQUALS(axis.Length(), 1.0f, 0.0001f, TEST_LOCATION); + } + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Rect.cpp b/automated-tests/src/dali/utc-Dali-Rect.cpp new file mode 100644 index 0000000..24ce9d8 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Rect.cpp @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_rect_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_rect_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +// Positive test case for a method +int UtcDaliRectCons01(void) +{ + TestApplication application; + + Rect rect; + DALI_TEST_EQUALS(rect.x, 0.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(rect.y, 0.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(rect.width, 0.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(rect.height, 0.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliRectCons02(void) +{ + TestApplication application; + + Rect rect(10.0f, 20.0f, 400.0f, 200.0f); + DALI_TEST_EQUALS(rect.x, 10.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(rect.y, 20.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(rect.width, 400.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(rect.height, 200.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliRectCons03(void) +{ + TestApplication application; + + Rect rect(10.0f, 20.0f, 400.0f, 200.0f); + + Rect r2 = rect; + + DALI_TEST_EQUALS(r2.x, 10.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(r2.y, 20.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(r2.width, 400.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(r2.height, 200.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliRectCons04(void) +{ + TestApplication application; + + Rect rect(10.0f, 20.0f, 400.0f, 200.0f); + + Rect r2(rect); + + DALI_TEST_EQUALS(r2.x, 10.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(r2.y, 20.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(r2.width, 400.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(r2.height, 200.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliRectSet(void) +{ + TestApplication application; + + Rect rect(10.0f, 20.0f, 400.0f, 200.0f); + + rect.Set(1.0f, 2.0f, 3.0f, 4.0f); + + DALI_TEST_EQUALS(rect.x, 1.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(rect.y, 2.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(rect.width, 3.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(rect.height, 4.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliRectIsEmpty(void) +{ + TestApplication application; + + Rect ri; + Rect rf(10.0f, 20.0f, 400.0f, 200.0f); + Rect rf2; + Rect rf3(10.0f, 20.0f, 0.0f, 200.0f); + Rect rf4(10.0f, 20.0f, 400.0f, 0.0f); + Rect rd(10.0, 20.0, 0.0, 200.0); + Rect ru(0u, 0u, 4u, 0u); + + DALI_TEST_CHECK(!rf.IsEmpty()); + DALI_TEST_CHECK(rf2.IsEmpty()); + DALI_TEST_CHECK(rf3.IsEmpty()); + DALI_TEST_CHECK(rf4.IsEmpty()); + DALI_TEST_CHECK(ri.IsEmpty()); + DALI_TEST_CHECK(rd.IsEmpty()); + DALI_TEST_CHECK(ru.IsEmpty()); + END_TEST; +} + +int UtcDaliRectLeft(void) +{ + TestApplication application; + + Rect rf(10.0f, 20.0f, 400.0f, 200.0f); + + DALI_TEST_EQUALS(rf.Left(), 10.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliRectRight(void) +{ + TestApplication application; + + Rect rf(10.0f, 20.0f, 400.0f, 200.0f); + + DALI_TEST_EQUALS(rf.Right(), 410.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliRectTop(void) +{ + TestApplication application; + + Rect rf(10.0f, 20.0f, 400.0f, 200.0f); + + DALI_TEST_EQUALS(rf.Top(), 20.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliRectBottom(void) +{ + TestApplication application; + + Rect rf(10.0f, 20.0f, 400.0f, 200.0f); + + DALI_TEST_EQUALS(rf.Bottom(), 220.0f, 0.001, TEST_LOCATION); + END_TEST; +} + + +int UtcDaliRectArea(void) +{ + TestApplication application; + + Rect rf(10.0f, 20.0f, 400.0f, 200.0f); + + DALI_TEST_EQUALS(rf.Area(), 80000.0f, 0.001, TEST_LOCATION); + END_TEST; +} + + +int UtcDaliRectIntersects(void) +{ + TestApplication application; + + Rect rf1( 10.0f, 20.0f, 200.0f, 200.0f); + Rect rf2( 10.0f, 120.0f, 200.0f, 200.0f); + Rect rf3( 10.0f, -80.0f, 200.0f, 200.0f); + Rect rf4(110.0f, 20.0f, 200.0f, 200.0f); + Rect rf5(-90.0f, 20.0f, 200.0f, 200.0f); + Rect rf6(1000.0f, 1200.0f, 10.0f, 10.0f); + + DALI_TEST_CHECK(rf1.Intersects(rf2)); + DALI_TEST_CHECK(rf1.Intersects(rf3)); + DALI_TEST_CHECK(rf1.Intersects(rf4)); + DALI_TEST_CHECK(rf1.Intersects(rf5)); + DALI_TEST_CHECK(!rf1.Intersects(rf6)); + END_TEST; +} + + + +int UtcDaliRectContains(void) +{ + TestApplication application; + + Rect rf1( 10.0f, 20.0f, 200.0f, 200.0f); + + Rect rf2( 10.0f, 120.0f, 200.0f, 200.0f); + Rect rf3( 10.0f, -80.0f, 200.0f, 200.0f); + Rect rf4(110.0f, 20.0f, 200.0f, 200.0f); + Rect rf5(-90.0f, 20.0f, 200.0f, 200.0f); + Rect rf6(1000.0f, 1200.0f, 10.0f, 10.0f); + + Rect rf7( 50.0f, 70.0f, 50.0f, 50.0f); + + Rect rf8( 10.0f, 20.0f, 100.0f, 100.0f); + Rect rf9( 110.0f, 20.0f, 100.0f, 100.0f); + Rect rf10( 110.0f, 120.0f, 100.0f, 100.0f); + Rect rf11( 10.0f, 120.0f, 100.0f, 100.0f); + + DALI_TEST_CHECK(rf1.Contains(rf1)); + DALI_TEST_CHECK(!rf1.Contains(rf2)); + DALI_TEST_CHECK(!rf1.Contains(rf3)); + DALI_TEST_CHECK(!rf1.Contains(rf4)); + DALI_TEST_CHECK(!rf1.Contains(rf5)); + DALI_TEST_CHECK(!rf1.Contains(rf6)); + + DALI_TEST_CHECK(rf1.Contains(rf7)); + + DALI_TEST_CHECK(rf1.Contains(rf8)); + DALI_TEST_CHECK(rf1.Contains(rf9)); + DALI_TEST_CHECK(rf1.Contains(rf10)); + DALI_TEST_CHECK(rf1.Contains(rf11)); + END_TEST; +} + + +int UtcDaliRectOperatorNotEquals(void) +{ + TestApplication application; + + Rect rf1( 10.0f, 20.0f, 200.0f, 200.0f); + Rect rf2( 10.0f, 120.0f, 200.0f, 200.0f); + Rect rf3( 10.0f, -80.0f, 200.0f, 200.0f); + Rect rf4(110.0f, 20.0f, 200.0f, 200.0f); + Rect rf5(-90.0f, 20.0f, 200.0f, 200.0f); + Rect rf6(1000.0f, 1200.0f, 10.0f, 10.0f); + Rect rf7( 50.0f, 70.0f, 50.0f, 50.0f); + Rect rf8( 10.0f, 20.0f, 100.0f, 100.0f); + Rect rf9( 110.0f, 20.0f, 100.0f, 100.0f); + Rect rf10( 110.0f, 120.0f, 100.0f, 100.0f); + Rect rf11( 10.0f, 120.0f, 100.0f, 100.0f); + + DALI_TEST_CHECK(rf1 != rf2); + DALI_TEST_CHECK(rf1 != rf3); + DALI_TEST_CHECK(rf1 != rf4); + DALI_TEST_CHECK(rf1 != rf5); + DALI_TEST_CHECK(rf1 != rf6); + DALI_TEST_CHECK(rf1 != rf7); + DALI_TEST_CHECK(rf1 != rf8); + DALI_TEST_CHECK(rf1 != rf9); + DALI_TEST_CHECK(rf1 != rf10); + DALI_TEST_CHECK(rf1 != rf11); + END_TEST; +} + + +int UtcDaliRectOperatorEquals(void) +{ + TestApplication application; + + Rect rf1( 10.0f, 20.0f, 200.0f, 200.0f); + Rect rf1p( 10.0f, 20.0f, 200.0f, 200.0f); + + Rect rf2(110.0f, 20.0f, 200.0f, 200.0f); + Rect rf3( 10.0f, 120.0f, 200.0f, 200.0f); + Rect rf4( 10.0f, 20.0f, 300.0f, 200.0f); + Rect rf5( 10.0f, 20.0f, 200.0f, 500.0f); + + Rect rf6( 0.0f, 0.0f, 9.0f, 10.0f); + + DALI_TEST_CHECK(rf1 == rf1p); + DALI_TEST_CHECK(rf1 == rf1); + DALI_TEST_CHECK(!(rf1 == rf2)); + DALI_TEST_CHECK(!(rf1 == rf3)); + DALI_TEST_CHECK(!(rf1 == rf4)); + DALI_TEST_CHECK(!(rf1 == rf5)); + DALI_TEST_CHECK(!(rf1 == rf6)); + + + // integers + Rect ri1( 10, 20, 200, 200 ); + Rect ri1p( 10, 20, 200, 200 ); + + DALI_TEST_CHECK(ri1 == ri1p); + END_TEST; +} + +int UtcDaliRectOStreamOperatorP(void) +{ + TestApplication application; + std::ostringstream oss; + + Rect rect( 1, 2, 10, 10 ); + + oss << rect; + + std::string expectedOutput = "[1, 2, 10, 10]"; + + DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-RenderTask.cpp b/automated-tests/src/dali/utc-Dali-RenderTask.cpp new file mode 100644 index 0000000..74bd263 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-RenderTask.cpp @@ -0,0 +1,3456 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#define BOOLSTR(x) ((x)?"T":"F") + + +using namespace Dali; + +void utc_dali_render_task_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_render_task_cleanup(void) +{ + test_return_value = TET_PASS; +} + +/** + * APIs: + * + * Constructor, Destructor, DownCast, New, copy constructor, assignment operator + * + * SetSourceActor 2+ve, 1-ve + * GetSourceActor 1+ve, 1-ve + * SetExclusive 2+ve, 0-ve + * IsExclusive 2+ve, 0-ve + * SetInputEnabled 1+ve, 0-ve + * GetInputEnabled 1+ve, 0-ve + * SetCameraActor 1+ve, 1-ve + * GetCameraActor 1+ve, 1-ve + * SetTargetFrameBuffer 1+ve, 1-ve + * GetTargetFrameBuffer 1+ve, 1-ve + * SetScreenToFrameBufferFunction 1+ve, 1-ve + * GetScreenToFrameBufferFunction 1+ve, 1-ve + * SetScreenToFrameBufferMappingActor 1+ve, 1-ve + * GetScreenToFrameBufferMappingActor 1+ve, 1-ve + * SetViewportPosition 1+ve + * GetCurrentViewportPosition 1+ve + * SetViewportSize 1+ve + * GetCurrentViewportSize 1+ve + * SetViewport 2+ve, 1-ve + * GetViewport 2+ve, 1-ve + * SetClearColor 1+ve, 1-ve + * GetClearColor 1+ve, 1-ve + * SetClearEnabled 1+ve, 1-ve + * GetClearEnabled 1+ve, 1-ve + * SetCullMode + * GetCullMode + * SetRefreshRate Many + * GetRefreshRate 1+ve + * FinishedSignal 1+ve + */ + +namespace // unnamed namespace +{ + +const int RENDER_FRAME_INTERVAL = 16; ///< Duration of each frame in ms. (at approx 60FPS) + +/* + * Simulate time passed by. + * + * @note this will always process at least 1 frame (1/60 sec) + * + * @param application Test application instance + * @param duration Time to pass in milliseconds. + * @return The actual time passed in milliseconds + */ +int Wait(TestApplication& application, int duration = 0) +{ + int time = 0; + + for(int i = 0; i <= ( duration / RENDER_FRAME_INTERVAL); i++) + { + application.SendNotification(); + application.Render(RENDER_FRAME_INTERVAL); + time += RENDER_FRAME_INTERVAL; + } + + return time; +} + +struct RenderTaskFinished +{ + RenderTaskFinished( bool& finished ) + : finished( finished ) + { + } + + void operator()( RenderTask& renderTask ) + { + finished = true; + } + + bool& finished; +}; + +struct RenderTaskFinishedRemoveSource +{ + RenderTaskFinishedRemoveSource( bool& finished ) + : finished( finished ), + finishedOnce(false) + { + } + + void operator()( RenderTask& renderTask ) + { + DALI_TEST_CHECK(finishedOnce == false); + finished = true; + finishedOnce = true; + Actor srcActor = renderTask.GetSourceActor(); + UnparentAndReset(srcActor); + } + + bool& finished; + bool finishedOnce; +}; + +struct RenderTaskFinishedRenderAgain +{ + RenderTaskFinishedRenderAgain( bool& finished ) + : finished( finished ), + finishedOnce(false) + { + } + + void operator()( RenderTask& renderTask ) + { + DALI_TEST_CHECK(finishedOnce == false); + finished = true; + finishedOnce = true; + renderTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + } + + bool& finished; + bool finishedOnce; +}; + + +bool TestScreenToFrameBufferFunction( Vector2& coordinates ) +{ + coordinates = coordinates + Vector2( 1, 2 ); + + return true; +} + +ImageActor CreateLoadingImage(TestApplication& application, std::string filename, ResourceImage::LoadPolicy loadPolicy, Image::ReleasePolicy releasePolicy) +{ + Image image = ResourceImage::New(filename, loadPolicy, releasePolicy); + DALI_TEST_CHECK( image ); + application.SendNotification(); + application.Render(16); + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + ImageActor actor = ImageActor::New(image); + actor.SetSize( 80, 80 ); + application.SendNotification(); + application.Render(16); + return actor; +} + +Sampler CreateSamplerWithLoadingImage(TestApplication& application, std::string filename, ResourceImage::LoadPolicy loadPolicy, Image::ReleasePolicy releasePolicy) +{ + Image image = ResourceImage::New(filename, loadPolicy, releasePolicy); + DALI_TEST_CHECK( image ); + application.SendNotification(); + application.Render(16); + DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + + Sampler sampler = Sampler::New( image, "sTexture" ); + application.SendNotification(); + application.Render(16); + return sampler; +} + +void CompleteImageLoad(TestApplication& application, Integration::ResourceId resourceId, Integration::ResourceTypeId requestType) +{ + std::vector ids; + ids.push_back( 23 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD ); + Integration::ResourcePointer resource(bitmap); + bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80); + + application.GetPlatform().SetResourceLoaded(resourceId, requestType, resource); +} + +void FailImageLoad(TestApplication& application, Integration::ResourceId resourceId ) +{ + application.GetPlatform().SetResourceLoadFailed(resourceId, Integration::FailureUnknown); +} + +void ReloadImage(TestApplication& application, ResourceImage image) +{ + application.GetPlatform().ClearReadyResources(); + application.GetPlatform().DiscardRequest(); + application.GetPlatform().ResetTrace(); + application.GetPlatform().SetClosestImageSize(Vector2(80.0f, 80.0f)); // Ensure reload is called. + image.Reload(); +} + +RenderTask CreateRenderTask(TestApplication& application, + CameraActor offscreenCamera, + Actor rootActor, // Reset default render task to point at this actor + Actor secondRootActor, // Source actor + unsigned int refreshRate, + bool glSync) +{ + // Change main render task to use a different root + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + taskList.GetTask(0u).SetSourceActor( rootActor ); + + FrameBufferImage frameBufferImage; + if( glSync ) + { + NativeImageInterfacePtr testNativeImagePtr = TestNativeImage::New(10, 10); + frameBufferImage= FrameBufferImage::New( *(testNativeImagePtr.Get()) ); + } + else + { + frameBufferImage = FrameBufferImage::New( 10, 10 ); + } + + // Don't draw output framebuffer // ' + + RenderTask newTask = taskList.CreateTask(); + newTask.SetCameraActor( offscreenCamera ); + newTask.SetSourceActor( secondRootActor ); + newTask.SetInputEnabled( false ); + newTask.SetClearColor( Vector4( 0.f, 0.f, 0.f, 0.f ) ); + newTask.SetClearEnabled( true ); + newTask.SetExclusive( true ); + newTask.SetRefreshRate( refreshRate ); + newTask.SetTargetFrameBuffer( frameBufferImage ); + return newTask; +} + +bool UpdateRender(TestApplication& application, TraceCallStack& callStack, bool testDrawn, bool& finishedSig, bool testFinished, bool testKeepUpdating ) +{ + finishedSig = false; + callStack.Reset(); + application.Render(16); + application.SendNotification(); + + bool sigPassed = false; + if( testFinished ) + { + sigPassed = finishedSig; + } + else + { + sigPassed = ! finishedSig; + } + + bool drawResult = callStack.FindMethod("DrawElements") || callStack.FindMethod("DrawArrays"); + + bool drawPassed = false; + if( testDrawn ) + { + drawPassed = drawResult; + } + else + { + drawPassed = !drawResult; + } + + bool keepUpdating = (application.GetUpdateStatus() != 0); + bool keepUpdatingPassed = false; + if( testKeepUpdating ) + { + keepUpdatingPassed = keepUpdating; + } + else + { + keepUpdatingPassed = !keepUpdating; + } + + bool result = (sigPassed && drawPassed && keepUpdatingPassed); + + tet_printf("UpdateRender: Expected: Draw:%s Signal:%s Keep Updating: %s Actual: Draw:%s Signal:%s KeepUpdating: %s %s\n", + BOOLSTR(testDrawn), BOOLSTR(testFinished), BOOLSTR(testKeepUpdating), + BOOLSTR(drawResult), BOOLSTR(finishedSig), BOOLSTR(keepUpdating), + result ? "Passed":"Failed"); + + return result; +} + +// The functor to be used in the hit-test algorithm to check whether the actor is hittable. +bool IsActorHittableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType type) +{ + bool hittable = false; + + switch (type) + { + case Dali::HitTestAlgorithm::CHECK_ACTOR: + { + // Check whether the actor is visible and not fully transparent. + if( actor.IsVisible() + && actor.GetCurrentWorldColor().a > 0.01f) // not FULLY_TRANSPARENT + { + + hittable = true; + } + break; + } + case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE: + { + if( actor.IsVisible() ) // Actor is visible, if not visible then none of its children are visible. + { + hittable = true; + } + break; + } + default: + { + break; + } + } + + return hittable; +} + +} // unnamed namespace + + +/****************************************************************************************************/ +/****************************************************************************************************/ +/******************************** TEST CASES BELOW **********************************************/ +/****************************************************************************************************/ +/****************************************************************************************************/ + +int UtcDaliRenderTaskDownCast01(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::DownCast()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + BaseHandle base = taskList.GetTask( 0u ); + DALI_TEST_CHECK( base ); + + RenderTask task = RenderTask::DownCast( base ); + DALI_TEST_CHECK( task ); + + // Try calling a method + DALI_TEST_CHECK( task.GetSourceActor() ); + END_TEST; +} + +int UtcDaliRenderTaskDownCast02(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::DownCast()"); + + Actor actor = Actor::New(); + + RenderTask task = RenderTask::DownCast( actor ); + DALI_TEST_CHECK( ! task ); + + END_TEST; +} + +int UtcDaliRenderTaskSetSourceActorN(void) +{ + TestApplication application; + tet_infoline("Testing RenderTask::SetSourceActor() Negative - try with empty actor handle"); + Stage stage = Stage::GetCurrent(); + + Actor srcActor; + + RenderTaskList taskList = stage.GetRenderTaskList(); + RenderTask renderTask = taskList.CreateTask(); + renderTask.SetSourceActor(srcActor); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( ! renderTask.GetSourceActor() ); + END_TEST; +} + + +int UtcDaliRenderTaskSetSourceActorP01(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetSourceActor() Positive - check that setting a non-renderable actor stops existing source actor being rendered "); + + Stage stage = Stage::GetCurrent(); + + const std::vector& boundTextures = application.GetGlAbstraction().GetBoundTextures( GL_TEXTURE0 ); + + RenderTaskList taskList = stage.GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + Actor actor = task.GetSourceActor(); + DALI_TEST_CHECK( actor ); + + std::vector ids; + ids.push_back( 7 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + + BufferImage img = BufferImage::New( 1,1 ); + ImageActor newActor = ImageActor::New( img ); + newActor.SetSize(1,1); + stage.Add( newActor ); + + Actor nonRenderableActor = Actor::New(); + stage.Add( nonRenderableActor ); + + // Stop the newActor from being rendered by changing the source actor + DALI_TEST_CHECK( nonRenderableActor ); + task.SetSourceActor( nonRenderableActor ); + DALI_TEST_CHECK( task.GetSourceActor() != actor ); + DALI_TEST_CHECK( task.GetSourceActor() == nonRenderableActor ); + + // Update & Render nothing! + application.GetGlAbstraction().ClearBoundTextures(); + application.SendNotification(); + application.Render(); + + // Check that nothing was rendered + DALI_TEST_EQUALS( boundTextures.size(), 0u, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliRenderTaskSetSourceActorP02(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetSourceActor() Positive - check that switching source from a non-renderable to a renderable actor causes the texture to be drawn"); + + Stage stage = Stage::GetCurrent(); + + const std::vector& boundTextures = application.GetGlAbstraction().GetBoundTextures( GL_TEXTURE0 ); + + RenderTaskList taskList = stage.GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + Actor actor = task.GetSourceActor(); + DALI_TEST_CHECK( actor ); + + std::vector ids; + ids.push_back( 7 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + + BufferImage img = BufferImage::New( 1,1 ); + ImageActor newActor = ImageActor::New( img ); + newActor.SetSize(1,1); + stage.Add( newActor ); + + Actor nonRenderableActor = Actor::New(); + stage.Add( nonRenderableActor ); + + // Stop the newActor from being rendered by changing the source actor + DALI_TEST_CHECK( nonRenderableActor ); + task.SetSourceActor( nonRenderableActor ); + DALI_TEST_CHECK( task.GetSourceActor() != actor ); + DALI_TEST_CHECK( task.GetSourceActor() == nonRenderableActor ); + + // Update & Render nothing! + application.GetGlAbstraction().ClearBoundTextures(); + application.SendNotification(); + application.Render(); + + // Check that nothing was rendered + DALI_TEST_EQUALS( boundTextures.size(), 0u, TEST_LOCATION ); + + // Set newActor as the new source Actor + task.SetSourceActor( newActor ); + DALI_TEST_CHECK( task.GetSourceActor() != actor ); + DALI_TEST_CHECK( task.GetSourceActor() == newActor ); + + // Update & Render the newActor + application.GetGlAbstraction().ClearBoundTextures(); + application.SendNotification(); + application.Render(); + + // Check that the newActor was rendered + DALI_TEST_EQUALS( boundTextures.size(), 1u, TEST_LOCATION ); + if ( boundTextures.size() ) + { + DALI_TEST_EQUALS( boundTextures[0], 7u, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliRenderTaskSetSourceActorOffStage(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetSourceActor (on/off stage testing)"); + + Stage stage = Stage::GetCurrent(); + + const std::vector& boundTextures = application.GetGlAbstraction().GetBoundTextures( GL_TEXTURE0 ); + + RenderTaskList taskList = stage.GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + Actor actor = task.GetSourceActor(); + DALI_TEST_CHECK( actor ); + + std::vector ids; + GLuint expectedTextureId( 3 ); + ids.push_back( expectedTextureId ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + + BufferImage img = BufferImage::New( 1,1 ); + ImageActor newActor = ImageActor::New( img ); + newActor.SetSize(1,1); + task.SetSourceActor( newActor ); + // Don't add newActor to stage yet //' + + // Update & Render with the actor initially off-stage + application.GetGlAbstraction().ClearBoundTextures(); + application.SendNotification(); + application.Render(); + + // Check that nothing was rendered + DALI_TEST_EQUALS( boundTextures.size(), 0u, TEST_LOCATION ); + + // Now add to stage + stage.Add( newActor ); + + // Update & Render with the actor on-stage + application.GetGlAbstraction().ClearBoundTextures(); + application.SendNotification(); + application.Render(); + + // Check that the newActor was rendered + DALI_TEST_EQUALS( boundTextures.size(), 1u, TEST_LOCATION ); + if ( boundTextures.size() ) + { + DALI_TEST_EQUALS( boundTextures[0], expectedTextureId, TEST_LOCATION ); + } + + // Now remove from stage + stage.Remove( newActor ); + + // Update & Render with the actor off-stage + application.GetGlAbstraction().ClearBoundTextures(); + application.SendNotification(); + application.Render(); + END_TEST; +} + +int UtcDaliRenderTaskSetSourceActorEmpty(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetSourceActor (empty handle case)"); + + Stage stage = Stage::GetCurrent(); + + const std::vector& boundTextures = application.GetGlAbstraction().GetBoundTextures( GL_TEXTURE0 ); + + RenderTaskList taskList = stage.GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + Actor actor = task.GetSourceActor(); + DALI_TEST_CHECK( actor ); + + std::vector ids; + GLuint expectedTextureId( 5 ); + ids.push_back( expectedTextureId ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + + BufferImage img = BufferImage::New( 1,1 ); + ImageActor newActor = ImageActor::New( img ); + newActor.SetSize(1,1); + stage.Add( newActor ); + + Actor nonRenderableActor = Actor::New(); + stage.Add( nonRenderableActor ); + + // Set with empty handle + task.SetSourceActor( Actor() ); + DALI_TEST_CHECK( ! task.GetSourceActor() ); + + // Update & Render nothing! + application.GetGlAbstraction().ClearBoundTextures(); + application.SendNotification(); + application.Render(); + + // Check that nothing was rendered + DALI_TEST_EQUALS( boundTextures.size(), 0u, TEST_LOCATION ); + + // Set with non-empty handle + task.SetSourceActor( newActor ); + DALI_TEST_CHECK( task.GetSourceActor() == newActor ); + + // Update & Render the newActor + application.GetGlAbstraction().ClearBoundTextures(); + application.SendNotification(); + application.Render(); + + // Check that the newActor was rendered + DALI_TEST_EQUALS( boundTextures.size(), 1u, TEST_LOCATION ); + if ( boundTextures.size() ) + { + DALI_TEST_EQUALS( boundTextures[0], expectedTextureId, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliRenderTaskGetSourceActorP01(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetSourceActor() Check the default render task has a valid source actor"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + Actor actor = task.GetSourceActor(); + DALI_TEST_CHECK( actor ); + + // By default the entire scene should be rendered + Actor root = Stage::GetCurrent().GetLayer( 0 ); + DALI_TEST_CHECK( root == actor ); + END_TEST; +} + +int UtcDaliRenderTaskGetSourceActorP02(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetSourceActor() Create a new render task, Add a new actor to the stage and set it as the source of the new render task. Get its source actor and check that it is equivalent to what was set."); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask task = taskList.CreateTask(); + Actor actor = Actor::New(); + Stage::GetCurrent().Add(actor); + task.SetSourceActor( actor ); + + DALI_TEST_EQUALS( actor, task.GetSourceActor(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRenderTaskGetSourceActorN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetSourceActor() Try with empty handle"); + + RenderTask task; + try + { + Actor actor = task.GetSourceActor(); + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliRenderTaskSetExclusive(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetExclusive() Check that exclusion works"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + // Manipulate the GenTextures behaviour, to identify different ImageActors + + std::vector ids; + ids.push_back( 8 ); // 8 = actor1 + ids.push_back( 9 ); // 9 = actor2 + ids.push_back( 10 ); // 10 = actor3 + application.GetGlAbstraction().SetNextTextureIds( ids ); + + BufferImage img1 = BufferImage::New( 1,1 ); + ImageActor actor1 = ImageActor::New( img1 ); + actor1.SetSize(1,1); + Stage::GetCurrent().Add( actor1 ); + + // Update & Render actor1 + application.SendNotification(); + application.Render(); + + // Check that the actor1 was rendered + const std::vector& boundTextures = application.GetGlAbstraction().GetBoundTextures( GL_TEXTURE0 ); + DALI_TEST_EQUALS( boundTextures.size(), 1u, TEST_LOCATION ); + + if ( boundTextures.size() ) + { + DALI_TEST_EQUALS( boundTextures[0], 8u/*unique to actor1*/, TEST_LOCATION ); + } + + BufferImage img2 = BufferImage::New( 1,1 ); + ImageActor actor2 = ImageActor::New( img2 ); + actor2.SetSize(1,1); + + // Force actor2 to be rendered before actor1 + Layer layer = Layer::New(); + Stage::GetCurrent().Add( layer ); + layer.Add( actor2 ); + layer.LowerToBottom(); + + // Update & Render + application.GetGlAbstraction().ClearBoundTextures(); + application.SendNotification(); + application.Render(); + + // Check that the actors were rendered + DALI_TEST_EQUALS( boundTextures.size(), 2u, TEST_LOCATION ); + + if ( boundTextures.size() ) + { + DALI_TEST_EQUALS( boundTextures[0], 9u/*unique to actor2*/, TEST_LOCATION ); + DALI_TEST_EQUALS( boundTextures[1], 8u/*unique to actor1*/, TEST_LOCATION ); + } + + BufferImage img3 = BufferImage::New( 1,1 ); + ImageActor actor3 = ImageActor::New( img3 ); + actor3.SetSize(1,1); + + // Force actor3 to be rendered before actor2 + layer = Layer::New(); + Stage::GetCurrent().Add( layer ); + layer.Add( actor3 ); + layer.LowerToBottom(); + + // Update & Render all actors + application.GetGlAbstraction().ClearBoundTextures(); + application.SendNotification(); + application.Render(); + + // Check that the actors were rendered + DALI_TEST_EQUALS( boundTextures.size(), 3u, TEST_LOCATION ); + + if ( boundTextures.size() ) + { + DALI_TEST_EQUALS( boundTextures[0], 10u/*unique to actor3*/, TEST_LOCATION ); + DALI_TEST_EQUALS( boundTextures[1], 9u/*unique to actor2*/, TEST_LOCATION ); + DALI_TEST_EQUALS( boundTextures[2], 8u/*unique to actor1*/, TEST_LOCATION ); + } + + // Both actors are now connected to the root node + // Setup 2 render-tasks - the first will render from the root-node, and the second from actor2 + + // Not exclusive is the default + RenderTask task1 = taskList.GetTask( 0u ); + DALI_TEST_CHECK( false == task1.IsExclusive() ); + + RenderTask task2 = taskList.CreateTask(); + DALI_TEST_CHECK( false == task2.IsExclusive() ); + task2.SetSourceActor( actor2 ); + + // Task1 should render all actors, and task 2 should render only actor2 + + application.GetGlAbstraction().ClearBoundTextures(); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( boundTextures.size(), 4u, TEST_LOCATION ); + + if ( boundTextures.size() == 4 ) + { + // Test that task 1 renders actor3, then actor2 & then actor1 + DALI_TEST_CHECK( boundTextures[0] == 10u ); + DALI_TEST_CHECK( boundTextures[1] == 9u ); + DALI_TEST_CHECK( boundTextures[2] == 8u ); + + // Test that task 2 renders actor2 + DALI_TEST_EQUALS( boundTextures[3], 9u, TEST_LOCATION ); + } + + // Make actor2 exclusive to task2 + + task2.SetExclusive( true ); + DALI_TEST_CHECK( true == task2.IsExclusive() ); + + // Task1 should render only actor1, and task 2 should render only actor2 + + application.GetGlAbstraction().ClearBoundTextures(); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( boundTextures.size(), 3u, TEST_LOCATION ); + if ( boundTextures.size() == 3 ) + { + // Test that task 1 renders actor3 & actor1 + DALI_TEST_CHECK( boundTextures[0] == 10u ); + DALI_TEST_CHECK( boundTextures[1] == 8u ); + + // Test that task 2 renders actor2 + DALI_TEST_CHECK( boundTextures[2] == 9u ); + } + END_TEST; +} + +int UtcDaliRenderTaskSetExclusive02(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetExclusive() Check that changing from exclusive to not-exclusive works"); + + std::vector ids; + ids.push_back( 8 ); // 8 = actor1 + application.GetGlAbstraction().SetNextTextureIds( ids ); + + BufferImage img1 = BufferImage::New( 1,1 ); + ImageActor actor1 = ImageActor::New( img1 ); + actor1.SetSize(1,1); + Stage::GetCurrent().Add( actor1 ); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask task = taskList.CreateTask(); + + task.SetSourceActor( actor1 ); + task.SetExclusive(true); // Actor should only render once + + TestGlAbstraction& gl = application.GetGlAbstraction(); + TraceCallStack& drawTrace = gl.GetDrawTrace(); + drawTrace.Enable(true); + + // Update & Render actor1 + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( drawTrace.CountMethod("DrawArrays"), 1, TEST_LOCATION ); + + // Set task to non-exclusive - actor1 should render twice: + drawTrace.Reset(); + task.SetExclusive(false); + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( drawTrace.CountMethod("DrawArrays"), 2, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRenderTaskSetExclusiveN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetExclusive() on empty handle"); + + RenderTask task; + try + { + task.SetExclusive(true); + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliRenderTaskIsExclusive01(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::IsExclusive() Check default values are non-exclusive"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + // Not exclusive is the default + RenderTask task = taskList.GetTask( 0u ); + DALI_TEST_CHECK( false == task.IsExclusive() ); + + RenderTask newTask = taskList.CreateTask(); + DALI_TEST_CHECK( false == newTask.IsExclusive() ); + + END_TEST; +} + +int UtcDaliRenderTaskIsExclusive02(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::IsExclusive() Check the getter returns set values"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + // Not exclusive is the default + RenderTask newTask = taskList.CreateTask(); + DALI_TEST_EQUALS( newTask.IsExclusive(), false, TEST_LOCATION ); + + newTask.SetExclusive(true); + DALI_TEST_EQUALS( newTask.IsExclusive(), true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRenderTaskIsExclusiveN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::IsExclusive() on empty handle"); + + RenderTask task; + try + { + bool x = task.IsExclusive(); + x=x; + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliRenderTaskSetInputEnabled(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetInputEnabled()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + // Input is enabled by default + RenderTask task = taskList.GetTask( 0u ); + DALI_TEST_CHECK( true == task.GetInputEnabled() ); + + task.SetInputEnabled( false ); + DALI_TEST_CHECK( false == task.GetInputEnabled() ); + + task.SetInputEnabled( true ); + DALI_TEST_CHECK( true == task.GetInputEnabled() ); + END_TEST; +} + +int UtcDaliRenderTaskGetInputEnabled(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetInputEnabled()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + // Input is enabled by default + RenderTask task = taskList.GetTask( 0u ); + DALI_TEST_EQUALS( true, task.GetInputEnabled(), TEST_LOCATION ); + + RenderTask newTask = taskList.CreateTask(); + DALI_TEST_EQUALS( true, newTask.GetInputEnabled(), TEST_LOCATION ); + + newTask.SetInputEnabled(false); + DALI_TEST_EQUALS( false, newTask.GetInputEnabled(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRenderTaskSetCameraActorP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetCameraActor()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + Actor defaultCameraActor = task.GetCameraActor(); + DALI_TEST_CHECK( defaultCameraActor ); + + CameraActor newCameraActor = CameraActor::New(); + DALI_TEST_CHECK( newCameraActor ); + + task.SetCameraActor( newCameraActor ); + DALI_TEST_CHECK( task.GetCameraActor() != defaultCameraActor ); + DALI_TEST_EQUALS( task.GetCameraActor(), newCameraActor, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliRenderTaskSetCameraActorN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetCameraActor() with empty actor handle"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + Actor actor = task.GetCameraActor(); + DALI_TEST_CHECK( actor ); + + CameraActor cameraActor; + + task.SetCameraActor( cameraActor ); + DALI_TEST_EQUALS( (bool)task.GetCameraActor(), false, TEST_LOCATION ); + DALI_TEST_EQUALS( task.GetCameraActor(), cameraActor, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliRenderTaskGetCameraActorP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetCameraActor()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + CameraActor actor = task.GetCameraActor(); + DALI_TEST_CHECK( actor ); + DALI_TEST_EQUALS( actor.GetProjectionMode(), Dali::Camera::PERSPECTIVE_PROJECTION, TEST_LOCATION ); + DALI_TEST_GREATER( actor.GetFieldOfView(), 0.0f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRenderTaskGetCameraActorN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetCameraActor() with empty handle"); + RenderTask task; + + try + { + Actor actor = task.GetCameraActor(); + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliRenderTaskSetTargetFrameBufferP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetTargetFrameBuffer()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + FrameBufferImage newImage = FrameBufferImage::New(); + task.SetTargetFrameBuffer( newImage ); + DALI_TEST_CHECK( task.GetTargetFrameBuffer() == newImage ); + END_TEST; +} + +int UtcDaliRenderTaskSetTargetFrameBufferN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetTargetFrameBuffer()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + FrameBufferImage newImage; // Empty handle + task.SetTargetFrameBuffer( newImage ); + DALI_TEST_EQUALS( (bool)task.GetTargetFrameBuffer(), false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRenderTaskGetTargetFrameBufferP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetTargetFrameBuffer()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask newTask = taskList.CreateTask(); + FrameBufferImage fb = FrameBufferImage::New(128, 128, Pixel::RGBA8888); + newTask.SetTargetFrameBuffer( fb ); + DALI_TEST_EQUALS( newTask.GetTargetFrameBuffer(), fb, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRenderTaskGetTargetFrameBufferN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetTargetFrameBuffer()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + // By default render-tasks do not render off-screen + FrameBufferImage image = task.GetTargetFrameBuffer(); + DALI_TEST_CHECK( !image ); + + END_TEST; +} + +int UtcDaliRenderTaskSetScreenToFrameBufferFunctionP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetScreenToFrameBufferFunction()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + task.SetScreenToFrameBufferFunction( TestScreenToFrameBufferFunction ); + + Vector2 coordinates( 5, 10 ); + Vector2 convertedCoordinates( 6, 12 ); // + Vector(1, 2) + + RenderTask::ScreenToFrameBufferFunction func = task.GetScreenToFrameBufferFunction(); + DALI_TEST_CHECK( func( coordinates ) ); + DALI_TEST_CHECK( coordinates == convertedCoordinates ); + + task.SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION ); + func = task.GetScreenToFrameBufferFunction(); + DALI_TEST_CHECK( func( coordinates ) ); + + task.SetScreenToFrameBufferFunction( RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ); + func = task.GetScreenToFrameBufferFunction(); + DALI_TEST_CHECK( ! func( coordinates ) ); + END_TEST; +} + +int UtcDaliRenderTaskSetScreenToFrameBufferFunctionN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetScreenToFrameBufferFunction()"); + + RenderTask task; // Empty handle + try + { + task.SetScreenToFrameBufferFunction( TestScreenToFrameBufferFunction ); + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliRenderTaskGetScreenToFrameBufferFunctionP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetScreenToFrameBufferFunction()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + Vector2 originalCoordinates( 5, 10 ); + Vector2 coordinates( 5, 10 ); + + RenderTask::ScreenToFrameBufferFunction func = task.GetScreenToFrameBufferFunction(); + DALI_TEST_CHECK( !func( coordinates ) ); // conversion should fail by default + DALI_TEST_CHECK( coordinates == originalCoordinates ); // coordinates should not be modified + END_TEST; +} + +int UtcDaliRenderTaskGetScreenToFrameBufferFunctionN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetScreenToFrameBufferFunction() on empty handle"); + + RenderTask task; + try + { + RenderTask::ScreenToFrameBufferFunction func = task.GetScreenToFrameBufferFunction(); + func=func; + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + END_TEST; +} + + +int UtcDaliRenderTaskGetScreenToFrameBufferMappingActorP(void) +{ + TestApplication application; + tet_infoline("Testing RenderTask::GetScreenToFrameBufferMappingActor "); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask renderTask = taskList.CreateTask(); + Actor mappingActor = Actor::New(); + renderTask.SetScreenToFrameBufferMappingActor(mappingActor); + + DALI_TEST_EQUALS( mappingActor, renderTask.GetScreenToFrameBufferMappingActor(), TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliRenderTaskGetScreenToFrameBufferMappingActorN(void) +{ + TestApplication application; + tet_infoline("Testing RenderTask::GetScreenToFrameBufferMappingActor with empty task handle"); + + RenderTask task; + try + { + Actor mappingActor; + task.SetScreenToFrameBufferMappingActor(mappingActor); + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliRenderTaskGetScreenToFrameBufferMappingActor02N(void) +{ + TestApplication application; + tet_infoline("Testing RenderTask::GetScreenToFrameBufferMappingActor with empty task handle"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask renderTask = taskList.CreateTask(); + Actor actor; + renderTask.SetScreenToFrameBufferMappingActor(actor); + + DALI_TEST_EQUALS( (bool)renderTask.GetScreenToFrameBufferMappingActor(), false, TEST_LOCATION); + END_TEST; +} + +int UtcDaliRenderTaskGetViewportP01(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetViewport() on default task"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask task = taskList.GetTask( 0u ); + Viewport viewport = task.GetViewport(); + + // By default the viewport should match the stage width/height + Vector2 stageSize = Stage::GetCurrent().GetSize(); + Viewport expectedViewport( 0, 0, stageSize.width, stageSize.height ); + DALI_TEST_CHECK( viewport == expectedViewport ); + END_TEST; +} + +int UtcDaliRenderTaskGetViewportP02(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetViewport() on new task"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask task = taskList.CreateTask(); + Viewport viewport = task.GetViewport(); + + // By default the viewport should match the stage width/height + Vector2 stageSize = Stage::GetCurrent().GetSize(); + Viewport expectedViewport( 0, 0, stageSize.width, stageSize.height ); + DALI_TEST_CHECK( viewport == expectedViewport ); + END_TEST; +} + +int UtcDaliRenderTaskGetViewportN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetViewport() on empty handle"); + + RenderTask task; + try + { + Viewport viewport = task.GetViewport(); + viewport = viewport; + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + END_TEST; +} + + +int UtcDaliRenderTaskSetViewportP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetViewport()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + Vector2 stageSize = Stage::GetCurrent().GetSize(); + Viewport newViewport( 0, 0, stageSize.width * 0.5f, stageSize.height * 0.5f ); + task.SetViewport( newViewport ); + + // Update (viewport is a property) + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( task.GetViewport() == newViewport ); + END_TEST; +} + +int UtcDaliRenderTaskSetViewportN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetViewport()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task; + try + { + Vector2 stageSize = Stage::GetCurrent().GetSize(); + Viewport newViewport( 0, 0, stageSize.width * 0.5f, stageSize.height * 0.5f ); + task.SetViewport( newViewport ); + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + + END_TEST; +} + + +int UtcDaliRenderTaskSetViewportPosition(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetViewportPosition()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + Viewport viewport = task.GetViewport(); + + // By default the viewport should match the stage width/height + + Vector2 stageSize = Stage::GetCurrent().GetSize(); + Viewport expectedViewport( 0, 0, stageSize.width, stageSize.height ); + DALI_TEST_CHECK( viewport == expectedViewport ); + + // 'Setter' test + Vector2 newPosition(25.0f, 50.0f); + task.SetViewportPosition( newPosition ); + + // Update (viewport is a property) + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( task.GetCurrentViewportPosition(), newPosition, Math::MACHINE_EPSILON_1, TEST_LOCATION ); + + // Set by Property test + Vector2 newPosition2(32.0f, 32.0f); + task.SetProperty( RenderTask::Property::VIEWPORT_POSITION, newPosition2 ); + + // Update + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( task.GetCurrentViewportPosition(), newPosition2, Math::MACHINE_EPSILON_1, TEST_LOCATION ); + + Vector2 newPosition3(64.0f, 0.0f); + Animation animation = Animation::New(1.0f); + animation.AnimateTo( Property( task, RenderTask::Property::VIEWPORT_POSITION ), newPosition3, AlphaFunction::LINEAR ); + animation.Play(); + + // Perform 1000ms worth of updates at which point animation should have completed. + Wait(application, 1000); + DALI_TEST_EQUALS( task.GetCurrentViewportPosition(), newPosition3, Math::MACHINE_EPSILON_1, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRenderTaskSetViewportSize(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetViewportSize()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + + Viewport viewport = task.GetViewport(); + + // By default the viewport should match the stage width/height + + Vector2 stageSize = Stage::GetCurrent().GetSize(); + Viewport expectedViewport( 0, 0, stageSize.width, stageSize.height ); + DALI_TEST_CHECK( viewport == expectedViewport ); + + Vector2 newSize(128.0f, 64.0f); + task.SetViewportSize( newSize ); + + // Update (viewport is a property) + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( task.GetCurrentViewportSize(), newSize, Math::MACHINE_EPSILON_1, TEST_LOCATION ); + + // Set by Property test + Vector2 newSize2(50.0f, 50.0f); + task.SetProperty( RenderTask::Property::VIEWPORT_SIZE, newSize2 ); + + // Update + application.SendNotification(); + application.Render(); + + DALI_TEST_EQUALS( task.GetCurrentViewportSize(), newSize2, Math::MACHINE_EPSILON_1, TEST_LOCATION ); + + Vector2 newSize3(10.0f, 10.0f); + Animation animation = Animation::New(1.0f); + animation.AnimateTo( Property( task, RenderTask::Property::VIEWPORT_SIZE ), newSize3, AlphaFunction::LINEAR ); + animation.Play(); + + // Perform 1000ms worth of updates at which point animation should have completed. + Wait(application, 1000); + DALI_TEST_EQUALS( task.GetCurrentViewportSize(), newSize3, Math::MACHINE_EPSILON_1, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRenderTaskSetClearColorP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetClearColor()"); + + Vector4 testColor( 1.0f, 2.0f, 3.0f, 4.0f ); + Vector4 testColor2( 5.0f, 6.0f, 7.0f, 8.0f ); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + DALI_TEST_CHECK( task.GetClearColor() != testColor ); + + task.SetClearColor( testColor ); + + // Wait a frame. + Wait(application); + + DALI_TEST_EQUALS( task.GetClearColor(), testColor, TEST_LOCATION ); + + task.SetProperty( RenderTask::Property::CLEAR_COLOR, testColor2 ); + + // Wait a frame. + Wait(application); + + DALI_TEST_EQUALS( task.GetClearColor(), testColor2, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRenderTaskSetClearColorN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetClearColor() on empty handle"); + + RenderTask task; + try + { + task.SetClearColor( Vector4::ZERO ); + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliRenderTaskGetClearColorP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetClearColor()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask task = taskList.GetTask( 0u ); + DALI_TEST_EQUALS( task.GetClearColor(), RenderTask::DEFAULT_CLEAR_COLOR, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRenderTaskGetClearColorN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetClearColor()"); + + RenderTask task; + try + { + Vector4 color = task.GetClearColor(); + color = color; + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliRenderTaskSetClearEnabledP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetClearEnabled()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + DALI_TEST_CHECK( !task.GetClearEnabled() ); // defaults to false + + task.SetClearEnabled( true ); + DALI_TEST_EQUALS( task.GetClearEnabled(), true, TEST_LOCATION ); + + task.SetClearEnabled( false ); + DALI_TEST_EQUALS( task.GetClearEnabled(), false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRenderTaskSetClearEnabledN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetClearEnabled() with empty handle"); + + RenderTask task; + try + { + task.SetClearEnabled(true); + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliRenderTaskGetClearEnabledP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetClearEnabled()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + RenderTask task = taskList.GetTask( 0u ); + DALI_TEST_CHECK( !task.GetClearEnabled() ); // defaults to false + END_TEST; +} + + +int UtcDaliRenderTaskGetClearEnabledN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetClearEnabled() with empty handle"); + + RenderTask task; + try + { + bool x = task.GetClearEnabled(); + x=x; + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliRenderTaskSetCullModeP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetCullMode()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask task = taskList.GetTask( 0u ); + DALI_TEST_EQUALS( task.GetCullMode(), true, TEST_LOCATION ); + + task.SetCullMode( false ); + + DALI_TEST_EQUALS( task.GetCullMode(), false, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliRenderTaskSetCullModeN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetCullMode() on empty handle"); + + RenderTask task; + try + { + task.SetCullMode( false ); + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliRenderTaskGetCullModeP(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetCullMode()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask task = taskList.GetTask( 0u ); + DALI_TEST_EQUALS( task.GetCullMode(), true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRenderTaskGetCullModeN(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetCullMode() with empty handle"); + + RenderTask task; + try + { + bool x = task.GetCullMode(); + x=x; + } + catch (Dali::DaliException(e)) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION); + } + END_TEST; +} + + +int UtcDaliRenderTaskSetRefreshRate(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SetRefreshRate()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + // By default tasks will be processed every frame + RenderTask task = taskList.GetTask( 0u ); + DALI_TEST_CHECK( RenderTask::REFRESH_ALWAYS == task.GetRefreshRate() ); + + task.SetRefreshRate( 2u ); // every-other frame + DALI_TEST_CHECK( 2u == task.GetRefreshRate() ); + + task.SetRefreshRate( RenderTask::REFRESH_ALWAYS ); + DALI_TEST_CHECK( RenderTask::REFRESH_ALWAYS == task.GetRefreshRate() ); + END_TEST; +} + +int UtcDaliRenderTaskGetRefreshRate(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::GetRefreshRate()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + + // By default tasks will be processed every frame + RenderTask task = taskList.GetTask( 0u ); + DALI_TEST_CHECK( RenderTask::REFRESH_ALWAYS == task.GetRefreshRate() ); + + RenderTask newTask = taskList.CreateTask(); + DALI_TEST_CHECK( RenderTask::REFRESH_ALWAYS == newTask.GetRefreshRate() ); + END_TEST; +} + +int UtcDaliRenderTaskSignalFinished(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SignalFinished()"); + + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction(); + + CameraActor offscreenCameraActor = CameraActor::New(); + + Stage::GetCurrent().Add( offscreenCameraActor ); + + BufferImage image = BufferImage::New( 10, 10 ); + ImageActor rootActor = ImageActor::New( image ); + rootActor.SetSize( 10, 10 ); + Stage::GetCurrent().Add( rootActor ); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + NativeImageInterfacePtr testNativeImagePtr = TestNativeImage::New(10, 10); + FrameBufferImage frameBufferImage = FrameBufferImage::New( *testNativeImagePtr.Get() ); + + // Flush all outstanding messages + application.SendNotification(); + application.Render(); + + RenderTask newTask = taskList.CreateTask(); + newTask.SetCameraActor( offscreenCameraActor ); + newTask.SetSourceActor( rootActor ); + newTask.SetInputEnabled( false ); + newTask.SetClearColor( Vector4( 0.f, 0.f, 0.f, 0.f ) ); + newTask.SetClearEnabled( true ); + newTask.SetExclusive( true ); + newTask.SetRefreshRate( RenderTask::REFRESH_ONCE ); + newTask.SetTargetFrameBuffer( frameBufferImage ); + + // Framebuffer doesn't actually get created until Connected, i.e. by previous line + + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + + // Flush the queue and render. + application.SendNotification(); + + // 1 render to process render task, then wait for sync before finished msg is sent + // from update to the event thread. + + application.Render(); + application.SendNotification(); + DALI_TEST_CHECK( !finished ); + + Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + application.Render(); + DALI_TEST_EQUALS( (application.GetUpdateStatus() & Integration::KeepUpdating::RENDER_TASK_SYNC), Integration::KeepUpdating::RENDER_TASK_SYNC, TEST_LOCATION ); + application.SendNotification(); + DALI_TEST_CHECK( !finished ); + + application.Render(); + DALI_TEST_EQUALS( (application.GetUpdateStatus() & Integration::KeepUpdating::RENDER_TASK_SYNC), Integration::KeepUpdating::RENDER_TASK_SYNC, TEST_LOCATION ); + application.SendNotification(); + DALI_TEST_CHECK( ! finished ); + + sync.SetObjectSynced( lastSyncObj, true ); + + application.Render(); + application.SendNotification(); + DALI_TEST_CHECK( !finished ); + + application.Render(); + application.SendNotification(); + DALI_TEST_CHECK( finished ); + finished = false; + + application.Render(); // Double check no more finished signal + application.SendNotification(); + DALI_TEST_CHECK( ! finished ); + END_TEST; +} + + +int UtcDaliRenderTaskContinuous01(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Continuous using loading image\nPRE: render task not ready (source actor not staged)\nPOST:continuous renders, no Finished signal"); + + // SETUP AN OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected, KeepUpdating + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, false ) ); + application.GetPlatform().ClearReadyResources(); + + // ADD SOURCE ACTOR TO STAGE - expect continuous renders to start, no finished signal + Stage::GetCurrent().Add(secondRootActor); + application.SendNotification(); + + // CONTINUE PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + END_TEST; +} + + +int UtcDaliRenderTaskContinuous02(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Continuous using loading image\nPRE: render task not ready (source actor not visible)\nPOST:continuous renders, no Finished signal"); + + // SETUP AN OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + Stage::GetCurrent().Add(secondRootActor); + secondRootActor.SetVisible(false); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected, KeepUpdating + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, false ) ); + application.GetPlatform().ClearReadyResources(); + + // MAKE SOURCE ACTOR VISIBLE - expect continuous renders to start, no finished signal + secondRootActor.SetVisible(true); + application.SendNotification(); + + // CONTINUE PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + END_TEST; +} + +int UtcDaliRenderTaskContinuous03(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Continuous using loading image\nPRE: render task not ready (camera actor not staged)\nPOST:continuous renders, no Finished signal"); + + // SETUP AN OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, false ) ); + application.GetPlatform().ClearReadyResources(); + + // ADD CAMERA ACTOR TO STAGE - expect continuous renders to start, no finished signal + Stage::GetCurrent().Add( offscreenCameraActor ); + application.SendNotification(); + + // CONTINUE PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + END_TEST; +} + + +int UtcDaliRenderTaskContinuous04(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Continuous using loading image\nPRE: Resource not ready\nPOST:continuous renders, no Finished signal"); + + // SETUP AN OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING - expect 'continuous' renders to start, no finished signal + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + END_TEST; +} + +int UtcDaliRenderTaskContinous05(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Continuous using Mesh which accesses texture through sampler with loading image\n" + "PRE: Resource not ready\nPOST:continuous renders, no Finished signal"); + + // SETUP AN OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + + Material material = CreateMaterial(1.0f); + Sampler sampler = CreateSamplerWithLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + material.AddSampler( sampler ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New(geometry, material); + Actor secondRootActor = Actor::New(); + secondRootActor.AddRenderer(renderer); + secondRootActor.SetSize(100, 100); + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING - expect 'continuous' renders to start, no finished signal + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + + END_TEST; +} + + +int UtcDaliRenderTaskOnce01(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once GlSync, using loading image\nPRE: Resources not ready, Source not visible\nPOST: Finished signal sent once only"); + + // SETUP AN OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction(); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ONCE, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // MAKE SOURCE VISIBLE + secondRootActor.SetVisible(true); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING - expect no rendering yet + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + application.GetPlatform().ClearReadyResources(); + sync.SetObjectSynced( lastSyncObj, true ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + END_TEST; +} + +int UtcDaliRenderTaskOnce02(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once GlSync, using Mesh which accesses texture through sampler with loading image.\n" + "PRE: Resources not ready\nPOST: Finished signal sent once only"); + + // SETUP AN OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction(); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + + Material material = CreateMaterial(1.0f); + Sampler sampler = CreateSamplerWithLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + material.AddSampler( sampler ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New(geometry, material); + Actor secondRootActor = Actor::New(); + secondRootActor.AddRenderer(renderer); + secondRootActor.SetSize(100, 100); + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ONCE, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING - expect no rendering yet + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + application.GetPlatform().ClearReadyResources(); + sync.SetObjectSynced( lastSyncObj, true ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + + END_TEST; +} + +int UtcDaliRenderTaskOnce03(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once GlSync, using loading image. Switch from render always after ready to render once\n" + "PRE: Render task ready, Image not loaded\n" + "POST: Finished signal sent only once"); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction(); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + application.GetPlatform().ClearReadyResources(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); // Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + sync.SetObjectSynced( lastSyncObj, true ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + + END_TEST; +} + + +int UtcDaliRenderTaskOnce04(void) +{ + TestApplication application; + tet_infoline("Testing RenderTask Render Once GlSync, using Mesh which accesses texture through sampler with loading image.\n" + "Switch from render always after ready to render once\n" + "PRE: Render task ready, Image not loaded\n" + "POST: Finished signal sent only once"); + + // SETUP AN OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction(); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + + Material material = CreateMaterial(1.0f); + Sampler sampler = CreateSamplerWithLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + material.AddSampler( sampler ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New(geometry, material); + Actor secondRootActor = Actor::New(); + secondRootActor.AddRenderer(renderer); + secondRootActor.SetSize(100, 100); + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + application.GetPlatform().ClearReadyResources(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); // Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + sync.SetObjectSynced( lastSyncObj, true ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + + END_TEST; +} + +int UtcDaliRenderTaskOnce05(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once GlSync\n" + "Switch from Render always after ready to render once with resources unready\n" + "PRE: Everything ready to render\n" + "POST: Finished signal sent once"); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction(); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // CHANGE TO RENDER ONCE + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); // Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + application.GetPlatform().ClearReadyResources(); + + sync.SetObjectSynced( lastSyncObj, true ); + + // Expect: No draw - we've just drawn our render task once, above. No finished signal - + // we won't read the gl sync until the next frame. Continue rendering - we're waiting for + // the sync + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // Expect: 1 final draw - this Update doesn't update the scene, hence render instructions + // from last frame but 1 are still present. + // Finished signal should be true - we've just done the sync. + // Should now stop rendering and updating - nothing left to do. + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, true, false ) ); + + END_TEST; +} + +#if 0 +//int UtcDaliRenderTaskOnce06(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once GlSync\n" + "During RenderOnce, make ready resources unready before sending first finished signal\n" + "PRE: Everything ready.\n" + "POST: Finished signal sent only once"); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction(); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + application.Render(); + + Stage::GetCurrent().Add(secondRootActor); + application.GetPlatform().ClearReadyResources(); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + + // CHANGE TO RENDER ONCE, RESOURCES BECOME NOT READY + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + + // Doesn't work... + ReloadImage(application, secondRootActor.GetImage()); + application.SendNotification(); // Input, Expected Input, Expected + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_EQUALS( secondRootActor.GetImage().GetLoadingState(), Dali::ResourceLoading, TEST_LOCATION); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + application.GetPlatform().ClearReadyResources(); + Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + sync.SetObjectSynced( lastSyncObj, true ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, true ) ); + + // Finished rendering - expect no more renders, no more signals: + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + END_TEST; +} +#endif + +int UtcDaliRenderTaskOnce07(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once GLSync\n" + "Render once, Second call to SetRefreshRate(ONCE) triggers only one more finished signal\n" + "PRE: Everything ready\n" + "POST: exactly 1 finished signal per call to SetRefreshRate(ONCE)"); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction(); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + application.Render(); + application.GetPlatform().ClearReadyResources(); + + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + + // CHANGE TO RENDER ONCE, + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + sync.SetObjectSynced( lastSyncObj, true ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + sync.SetObjectSynced( lastSyncObj, true ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + END_TEST; +} + +int UtcDaliRenderTaskOnce08(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once GLSync\n" + "Render once, Call to SetRefreshRate(ONCE) in Finished signal callback triggers " + "another render & another finished signal\n" + "PRE: Everything ready\n" + "POST: exactly 1 finished signal per call to SetRefreshRate(ONCE)"); + + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction(); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + application.Render(); + application.GetPlatform().ClearReadyResources(); + + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + + ConnectionTracker connectionTracker; + RenderTaskFinishedRenderAgain renderTaskFinishedRenderAgain( finished ); + newTask.FinishedSignal().Connect( &connectionTracker, renderTaskFinishedRenderAgain ); + + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj == NULL ); + + // CHANGE TO RENDER ONCE, + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + sync.SetObjectSynced( lastSyncObj, true ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + application.SendNotification(); + + // Expect SetRefreshRate to have been called again + // Prevent next finished signal calling refresh once again + RenderTaskFinished renderTaskFinished( finished ); + connectionTracker.DisconnectAll(); + newTask.FinishedSignal().Connect( &connectionTracker, renderTaskFinished ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + sync.SetObjectSynced( lastSyncObj, true ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + END_TEST; +} + + +int UtcDaliRenderTaskOnce09(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once GlSync\n" + "SetRefreshRate(ONCE) again before first finished signal has been sent.\n" + "PRE: resources ready\n" + "POST: Only 1 finished signal sent."); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction(); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + application.Render(); + application.GetPlatform().ClearReadyResources(); + + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + + // CHANGE TO RENDER ONCE, + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + sync.SetObjectSynced( lastSyncObj, true ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + + END_TEST; +} + +int UtcDaliRenderTaskOnce10(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once GlSync\n" + "SetRefreshRate(ONCE), resource load failed completes render task.\n" + "PRE: resources not ready\n" + "POST: Only 1 finished signal sent."); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction(); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // CHANGE TO RENDER ONCE, + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + tet_printf(" FailImageLoad\n"); + + FailImageLoad(application, imageRequestId); // Need to run Update again for this to complete + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); // nothing to draw + application.SendNotification(); + + // Drawing empty framebuffer, so will still get a GL sync + Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + sync.SetObjectSynced( lastSyncObj, true ); + + // Expect finished signal, as all resources are complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + + END_TEST; +} + +int UtcDaliRenderTaskOnceNoSync01(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once, using loading image\nPRE: Resources not ready, Source not visible\nPOST: Finished signal sent once only"); + + // SETUP AN OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ONCE, false); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING - expect immediate rendering yet + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + application.GetPlatform().ClearReadyResources(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + END_TEST; +} + +int UtcDaliRenderTaskOnceNoSync02(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once, using Mesh which accesses texture through sampler with loading image.\n" + "PRE: Resources not ready\nPOST: Finished signal sent once only"); + // SETUP AN OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + + Material material = CreateMaterial(1.0f); + Sampler sampler = CreateSamplerWithLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + material.AddSampler( sampler ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New(geometry, material); + Actor secondRootActor = Actor::New(); + secondRootActor.AddRenderer(renderer); + secondRootActor.SetSize(100, 100); + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ONCE, false); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING - expect immediate rendering yet + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + application.GetPlatform().ClearReadyResources(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + + END_TEST; +} + +int UtcDaliRenderTaskOnceNoSync03(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once, using loading image. Switch from render always after ready to render once\n" + "PRE: Render task ready, Image not loaded\n" + "POST: Finished signal sent only once"); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + application.GetPlatform().ClearReadyResources(); + + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); // Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + END_TEST; +} + +int UtcDaliRenderTaskOnceNoSync04(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once, using Mesh which accesses texture through sampler with loading image.\n" + "Switch from render always after ready to render once\n" + "PRE: Render task ready, Image not loaded\n" + "POST: Finished signal sent only once"); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + + Material material = CreateMaterial(1.0f); + Sampler sampler = CreateSamplerWithLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + material.AddSampler( sampler ); + + Geometry geometry = CreateQuadGeometry(); + Renderer renderer = Renderer::New(geometry, material); + Actor secondRootActor = Actor::New(); + secondRootActor.AddRenderer(renderer); + secondRootActor.SetSize(100, 100); + Stage::GetCurrent().Add(secondRootActor); + + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + application.GetPlatform().ClearReadyResources(); + + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); // Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + END_TEST; +} + +int UtcDaliRenderTaskOnceNoSync05(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once\n" + "Switch from Render always after ready to render once with resources unready\n" + "PRE: Everything ready to render\n" + "POST: Finished signal sent once"); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // CHANGE TO RENDER ONCE + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); // Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + application.GetPlatform().ClearReadyResources(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + END_TEST; +} + +#if 0 +//int UtcDaliRenderTaskOnceNoSync06(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once\n" + "During RenderOnce, make ready resources unready before sending first finished signal\n" + "PRE: Everything ready.\n" + "POST: Finished signal sent only once"); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + application.Render(); + application.GetPlatform().ClearReadyResources(); + + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + + // CHANGE TO RENDER ONCE, RESOURCES BECOME NOT READY + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + + // Doesn't work... + ReloadImage(application, secondRootActor.GetImage()); + application.SendNotification(); // Input, Expected Input, Expected + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_EQUALS( secondRootActor.GetImage().GetLoadingState(), Dali::ResourceLoading, TEST_LOCATION); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // FINISH RESOURCE LOADING + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, true, true ) ); + application.GetPlatform().ClearReadyResources(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + END_TEST; +} +#endif + +int UtcDaliRenderTaskOnceNoSync07(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once\n" + "Render once, Second call to SetRefreshRate(ONCE) triggers only one more finished signal\n" + "PRE: Everything ready\n" + "POST: exactly 1 finished signal per call to SetRefreshRate(ONCE)"); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + application.Render(); + application.GetPlatform().ClearReadyResources(); + + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + + // CHANGE TO RENDER ONCE, + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + END_TEST; +} + +int UtcDaliRenderTaskOnceNoSync08(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once\n" + "Render once, Call to SetRefreshRate(ONCE) in Finished signal callback triggers\n" + "another render & another finished signal\n" + "PRE: Everything ready\n" + "POST: exactly 1 finished signal per call to SetRefreshRate(ONCE)"); + + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + application.Render(); + application.GetPlatform().ClearReadyResources(); + + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false); + bool finished = false; + + ConnectionTracker connectionTracker; + RenderTaskFinishedRenderAgain renderTaskFinishedRenderAgain( finished ); + newTask.FinishedSignal().Connect( &connectionTracker, renderTaskFinishedRenderAgain ); + + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + + // CHANGE TO RENDER ONCE, + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + + // Expect SetRefreshRate to have been called again + // Prevent next finished signal calling refresh once again + RenderTaskFinished renderTaskFinished( finished ); + connectionTracker.DisconnectAll(); + newTask.FinishedSignal().Connect( &connectionTracker, renderTaskFinished ); + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + END_TEST; +} + + +int UtcDaliRenderTaskOnceNoSync09(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once\n" + "SetRefreshRate(ONCE) again before first finished signal has been sent.\n" + "PRE: resources ready\n" + "POST: Only 1 finished signal sent."); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + application.Render(); + application.GetPlatform().ClearReadyResources(); + + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, false ) ); + + // CHANGE TO RENDER ONCE, + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + END_TEST; +} + +int UtcDaliRenderTaskOnceNoSync10(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once\n" + "SetRefreshRate(ONCE), resource load failed, completes render task.\n" + "PRE: resources not ready\n" + "POST: Only 1 finished signal sent."); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor rootActor = Actor::New(); + Stage::GetCurrent().Add( rootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Stage::GetCurrent().Add(secondRootActor); + + RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false); + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + // CHANGE TO RENDER ONCE, + newTask.SetRefreshRate(RenderTask::REFRESH_ONCE); + application.SendNotification(); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); + + FailImageLoad(application, imageRequestId); // Need to run Update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, false, true ) ); // nothing to draw + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, finished, true, false ) ); + + END_TEST; +} + + + +int UtcDaliRenderTaskOnceChain01(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask Render Once Chained render tasks\n" + "SetRefreshRate(ONCE), resource load completes, both render tasks render.\n" + "PRE: resources not ready\n" + "POST: 2 finished signals sent."); + + // SETUP A CONTINUOUS OFFSCREEN RENDER TASK + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace(); + drawTrace.Enable(true); + + Actor defaultRootActor = Actor::New(); // Root for default RT + Stage::GetCurrent().Add( defaultRootActor ); + + CameraActor offscreenCameraActor = CameraActor::New(); + Stage::GetCurrent().Add( offscreenCameraActor ); + ImageActor firstRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED); + Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest(); + Integration::ResourceId imageRequestId = imageRequest->GetId(); + Integration::ResourceTypeId imageType = imageRequest->GetType()->id; + Stage::GetCurrent().Add(firstRootActor); + + // first render task + RenderTask firstTask = CreateRenderTask(application, offscreenCameraActor, defaultRootActor, firstRootActor, RenderTask::REFRESH_ONCE, false); + bool firstFinished = false; + RenderTaskFinished renderTask1Finished( firstFinished ); + firstTask.FinishedSignal().Connect( &application, renderTask1Finished ); + + // Second render task + FrameBufferImage fbo = firstTask.GetTargetFrameBuffer(); + ImageActor secondRootActor = ImageActor::New( fbo ); + Stage::GetCurrent().Add(secondRootActor); + RenderTask secondTask = CreateRenderTask(application, offscreenCameraActor, defaultRootActor, secondRootActor, RenderTask::REFRESH_ONCE, false); + bool secondFinished = false; + RenderTaskFinished renderTask2Finished( secondFinished ); + secondTask.FinishedSignal().Connect( &application, renderTask2Finished ); + + application.SendNotification(); + + // START PROCESS/RENDER Input, Expected Input, Expected + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, firstFinished, false, true ) ); + DALI_TEST_CHECK( secondFinished == false ); + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, firstFinished, false, true ) ); + DALI_TEST_CHECK( secondFinished == false ); + + CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete + DALI_TEST_CHECK( UpdateRender(application, drawTrace, true, firstFinished, false, true ) ); + DALI_TEST_CHECK( secondFinished == false ); + application.GetPlatform().ClearReadyResources(); + + DALI_TEST_CHECK( UpdateRender(application, drawTrace, false, firstFinished, true, false ) ); + DALI_TEST_CHECK( secondFinished == true ); + + END_TEST; +} + +int UtcDaliRenderTaskProperties(void) +{ + TestApplication application; + + RenderTask task = Stage::GetCurrent().GetRenderTaskList().CreateTask(); + + Property::IndexContainer indices; + task.GetPropertyIndices( indices ); + DALI_TEST_CHECK( indices.Size() ); + DALI_TEST_EQUALS( indices.Size(), task.GetPropertyCount(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRenderTaskSetScreenToFrameBufferMappingActor(void) +{ + TestApplication application; + tet_infoline("Testing RenderTask::SetScreenToFrameBufferMappingActor "); + + Stage stage = Stage::GetCurrent(); + Size stageSize = stage.GetSize(); + Actor mappingActor = Actor::New(); + Vector2 scale( 0.6f, 0.75f); + Vector2 offset( stageSize.x*0.1f, stageSize.y*0.15f); + mappingActor.SetSize( stageSize * scale ); + mappingActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + mappingActor.SetPosition( offset.x, offset.y ); + stage.Add( mappingActor ); + + Actor offscreenActor = Actor::New(); + offscreenActor.SetSize( stageSize ); + offscreenActor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + stage.Add( offscreenActor ); + + RenderTaskList taskList = stage.GetRenderTaskList(); + RenderTask renderTask = taskList.CreateTask(); + FrameBufferImage frameBufferImage = FrameBufferImage::New(stageSize.width*scale.x, stageSize.height*scale.y, Pixel::A8, Image::NEVER); + renderTask.SetSourceActor( offscreenActor ); + renderTask.SetExclusive( true ); + renderTask.SetInputEnabled( true ); + renderTask.SetTargetFrameBuffer( frameBufferImage ); + renderTask.SetRefreshRate( RenderTask::REFRESH_ONCE ); + renderTask.SetScreenToFrameBufferMappingActor( mappingActor ); + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + + // Render and notify + application.SendNotification(); + application.Render(); + application.Render(); + application.SendNotification(); + + Vector2 screenCoordinates( stageSize.x * 0.05f, stageSize.y * 0.05f ); + Dali::HitTestAlgorithm::Results results; + DALI_TEST_CHECK( !results.actor ); + DALI_TEST_EQUALS( Vector2::ZERO, results.actorCoordinates, 0.1f, TEST_LOCATION ); + // miss expected, results not changed + DALI_TEST_CHECK( false == Dali::HitTestAlgorithm::HitTest( renderTask, screenCoordinates, results, IsActorHittableFunction ) ); + DALI_TEST_CHECK( !results.actor ); + DALI_TEST_EQUALS( Vector2::ZERO, results.actorCoordinates, 0.1f, TEST_LOCATION ); + + screenCoordinates.x = stageSize.x * 0.265f; + screenCoordinates.y = stageSize.y * 0.33f; + results.actor = Actor(); + results.actorCoordinates = Vector2::ZERO; + // hit expected, results changed + DALI_TEST_CHECK( true == Dali::HitTestAlgorithm::HitTest( renderTask, screenCoordinates, results, IsActorHittableFunction ) ); + DALI_TEST_CHECK( results.actor == offscreenActor ); + DALI_TEST_EQUALS( (screenCoordinates-offset)/scale , results.actorCoordinates, 0.1f, TEST_LOCATION ); + + screenCoordinates.x = stageSize.x * 0.435f; + screenCoordinates.y = stageSize.y * 0.52f; + // hit expected, results changed + DALI_TEST_CHECK( true == Dali::HitTestAlgorithm::HitTest( renderTask, screenCoordinates, results, IsActorHittableFunction ) ); + DALI_TEST_CHECK( results.actor == offscreenActor ); + const Vector2 expectedCoordinates = (screenCoordinates-offset)/scale; + DALI_TEST_EQUALS( expectedCoordinates , results.actorCoordinates, 0.1f, TEST_LOCATION ); + + screenCoordinates.x = stageSize.x * 0.65f; + screenCoordinates.y = stageSize.y * 0.95f; + // miss expected, results not changed + DALI_TEST_CHECK( false == Dali::HitTestAlgorithm::HitTest( renderTask, screenCoordinates, results, IsActorHittableFunction ) ); + DALI_TEST_CHECK( results.actor == offscreenActor ); + DALI_TEST_EQUALS( expectedCoordinates , results.actorCoordinates, 0.1f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliRenderTaskFinishInvisibleSourceActor(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTask::SignalFinished()"); + + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); + TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction(); + + CameraActor offscreenCameraActor = CameraActor::New(); + + Stage::GetCurrent().Add( offscreenCameraActor ); + + BufferImage image = BufferImage::New( 10, 10 ); + ImageActor rootActor = ImageActor::New( image ); + rootActor.SetSize( 10, 10 ); + rootActor.SetVisible(false); + Stage::GetCurrent().Add( rootActor ); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + NativeImageInterfacePtr testNativeImagePtr = TestNativeImage::New(10, 10); + FrameBufferImage frameBufferImage = FrameBufferImage::New( *testNativeImagePtr.Get() ); + + // Flush all outstanding messages + application.SendNotification(); + application.Render(); + + RenderTask newTask = taskList.CreateTask(); + newTask.SetCameraActor( offscreenCameraActor ); + newTask.SetSourceActor( rootActor ); + newTask.SetInputEnabled( false ); + newTask.SetClearColor( Vector4( 0.f, 0.f, 0.f, 0.f ) ); + newTask.SetClearEnabled( true ); + newTask.SetExclusive( true ); + newTask.SetRefreshRate( RenderTask::REFRESH_ONCE ); + newTask.SetTargetFrameBuffer( frameBufferImage ); + + // Framebuffer doesn't actually get created until Connected, i.e. by previous line + + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + + // Flush the queue and render. + application.SendNotification(); + + // 1 render to process render task, then wait for sync before finished msg is sent + // from update to the event thread. + + application.Render(); + application.SendNotification(); + DALI_TEST_CHECK( !finished ); + + Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject(); + DALI_TEST_CHECK( lastSyncObj != NULL ); + + application.Render(); + DALI_TEST_EQUALS( (application.GetUpdateStatus() & Integration::KeepUpdating::RENDER_TASK_SYNC), Integration::KeepUpdating::RENDER_TASK_SYNC, TEST_LOCATION ); + application.SendNotification(); + DALI_TEST_CHECK( !finished ); + + application.Render(); + DALI_TEST_EQUALS( (application.GetUpdateStatus() & Integration::KeepUpdating::RENDER_TASK_SYNC), Integration::KeepUpdating::RENDER_TASK_SYNC, TEST_LOCATION ); + application.SendNotification(); + DALI_TEST_CHECK( ! finished ); + + sync.SetObjectSynced( lastSyncObj, true ); + + application.Render(); + application.SendNotification(); + DALI_TEST_CHECK( !finished ); + + application.Render(); + application.SendNotification(); + DALI_TEST_CHECK( finished ); + finished = false; + + application.Render(); // Double check no more finished signal + application.SendNotification(); + DALI_TEST_CHECK( ! finished ); + + END_TEST; +} + +int UtcDaliRenderTaskFinishMissingImage(void) +{ + TestApplication application; + + // Previously we had bugs where not having a resource ID would cause render-tasks to wait forever + tet_infoline("Testing RenderTask::SignalFinished() when an ImageActor has no Image set"); + + Stage stage = Stage::GetCurrent(); + + BufferImage image = BufferImage::New( 10, 10 ); + ImageActor rootActor = ImageActor::New( image ); + rootActor.SetSize( 10, 10 ); + stage.Add( rootActor ); + + ImageActor actorWithMissingImage = ImageActor::New( Image() ); + actorWithMissingImage.SetSize( 10, 10 ); + stage.Add( actorWithMissingImage ); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask newTask = taskList.CreateTask(); + newTask.SetInputEnabled( false ); + newTask.SetClearColor( Vector4( 0.f, 0.f, 0.f, 0.f ) ); + newTask.SetClearEnabled( true ); + newTask.SetExclusive( true ); + newTask.SetRefreshRate( RenderTask::REFRESH_ONCE ); + + bool finished = false; + RenderTaskFinished renderTaskFinished( finished ); + newTask.FinishedSignal().Connect( &application, renderTaskFinished ); + + // 1 render to process render task, then 1 before finished msg is sent from update to the event thread. + application.SendNotification(); + application.Render(); + application.Render(); + + application.SendNotification(); + DALI_TEST_CHECK( finished ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-RenderTaskList.cpp b/automated-tests/src/dali/utc-Dali-RenderTaskList.cpp new file mode 100644 index 0000000..2d69397 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-RenderTaskList.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_render_task_list_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_render_task_list_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliRenderTaskListDefaultConstructor(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTaskList::RenderTaskList()"); + + RenderTaskList taskList; + + DALI_TEST_CHECK( ! taskList ); + END_TEST; +} + +int UtcDaliRenderTaskListCopyConstructor(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTaskList::RenderTaskList(const RenderTaskList& handle)"); + + RenderTaskList taskList1; + + RenderTaskList taskList2( taskList1 ); + + DALI_TEST_CHECK( ! taskList2 ); + END_TEST; +} + +int UtcDaliRenderTaskListAssignment(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTaskList::RenderTaskList(const RenderTaskList& handle)"); + + RenderTaskList taskList1; + + RenderTaskList taskList2; + + taskList1 = taskList2; + + DALI_TEST_CHECK( ! taskList1 ); + END_TEST; +} + + +int UtcDaliRenderTaskListDownCast(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTaskList::DownCast()"); + + BaseHandle base = Stage::GetCurrent().GetRenderTaskList(); + + RenderTaskList taskList = RenderTaskList::DownCast( base ); + + DALI_TEST_CHECK( taskList ); + + // Try calling a method + DALI_TEST_CHECK( 1u == taskList.GetTaskCount() ); + END_TEST; +} + +int UtcDaliRenderTaskListCreateTask(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTaskList::CreateTask()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + DALI_TEST_CHECK( 1u == taskList.GetTaskCount() ); + + taskList.CreateTask(); + DALI_TEST_CHECK( 2u == taskList.GetTaskCount() ); + END_TEST; +} + +int UtcDaliRenderTaskListRemoveTask(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTaskList::RemoveTask()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + DALI_TEST_CHECK( 1u == taskList.GetTaskCount() ); + + RenderTask newTask = taskList.CreateTask(); + DALI_TEST_CHECK( 2u == taskList.GetTaskCount() ); + + taskList.RemoveTask( newTask ); + DALI_TEST_CHECK( 1u == taskList.GetTaskCount() ); + END_TEST; +} + +int UtcDaliRenderTaskListGetTaskCount(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTaskList::GetTaskCount()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + DALI_TEST_CHECK( 1u == taskList.GetTaskCount() ); + + taskList.RemoveTask( taskList.GetTask(0u) ); + DALI_TEST_CHECK( 0u == taskList.GetTaskCount() ); + END_TEST; +} + +int UtcDaliRenderTaskListGetTask(void) +{ + TestApplication application; + + tet_infoline("Testing RenderTaskList::GetTask()"); + + RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList(); + RenderTask defaultTask = taskList.GetTask( 0u ); + DALI_TEST_CHECK( 1u == taskList.GetTaskCount() ); + DALI_TEST_CHECK( defaultTask ); + DALI_TEST_CHECK( defaultTask == taskList.GetTask( 0u ) ); + + RenderTask newTask = taskList.CreateTask(); + DALI_TEST_CHECK( 2u == taskList.GetTaskCount() ); + + RenderTask temp = taskList.GetTask( 0u ); + RenderTask temp2 = taskList.GetTask( 1u ); + + DALI_TEST_CHECK( newTask ); + DALI_TEST_CHECK( defaultTask != newTask ); + DALI_TEST_CHECK( taskList.GetTask( 0u ) == defaultTask ); + DALI_TEST_CHECK( taskList.GetTask( 1u ) == newTask ); + DALI_TEST_CHECK( taskList.GetTask( 1u ) != defaultTask ); + + taskList.RemoveTask( taskList.GetTask(0u) ); + DALI_TEST_CHECK( 1u == taskList.GetTaskCount() ); + DALI_TEST_CHECK( taskList.GetTask( 0u ) != defaultTask ); + DALI_TEST_CHECK( taskList.GetTask( 0u ) == newTask ); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-ResourceImage.cpp b/automated-tests/src/dali/utc-Dali-ResourceImage.cpp new file mode 100644 index 0000000..df2ee7e --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-ResourceImage.cpp @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + +using namespace Dali; + +void utc_dali_resource_image_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_resource_image_cleanup(void) +{ + test_return_value = TET_PASS; +} + +static const char* gTestImageFilename = "icon_wrt.png"; + +namespace +{ + +void LoadBitmapResource(TestPlatformAbstraction& platform) +{ + Integration::ResourceRequest* request = platform.GetRequest(); + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD ); + Integration::ResourcePointer resource(bitmap); + bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80); + + if(request) + { + platform.SetResourceLoaded(request->GetId(), request->GetType()->id, resource); + } +} + +} // namespace + + +// 1.1 +int UtcDaliResourceImageNew01(void) +{ + TestApplication application; + + tet_infoline("UtcDaliResourceImageNew01 - ResourceImage::New(const std::string&)"); + + // invoke default handle constructor + ResourceImage image; + + DALI_TEST_CHECK( !image ); + + // initialise handle + image = ResourceImage::New(gTestImageFilename); + + DALI_TEST_CHECK( image ); + END_TEST; +} + +// 1.2 +int UtcDaliResourceImageNew02(void) +{ + TestApplication application; + + tet_infoline("UtcDaliREsourceImageNew02 - ResourceImage New( const std::string& url, ImageDimensions size, FittingMode scalingMode, SamplingMode samplingMode, bool orientationCorrection = true )"); + + // invoke default handle constructor + ResourceImage image; + + DALI_TEST_CHECK( !image ); + + // initialise handle + image = ResourceImage::New(gTestImageFilename, ImageDimensions( 128, 256 ), FittingMode::FIT_HEIGHT ); + + DALI_TEST_CHECK( image ); + END_TEST; +} + +// 1.3 +int UtcDaliResourceImageNewWithPolicies01(void) +{ + TestApplication application; + TestPlatformAbstraction& platform = application.GetPlatform(); + + // testing delayed loading + tet_infoline("UtcDaliResourceImageNewWithPolicies01 - Load image with LoadPolicy::OnDemand, ReleasePolicy::Never"); + DALI_TEST_CHECK( !platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + ResourceImage image = ResourceImage::New(gTestImageFilename, ResourceImage::ON_DEMAND, Image::NEVER); + + DALI_TEST_CHECK( image ); + + application.SendNotification(); + application.Render(16); + + // request file loading only when actor added to stage + DALI_TEST_CHECK( !platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + + ImageActor actor = ImageActor::New(image); + + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + + DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + + // testing ReleasePolicy::Never + // fake loading image + std::vector ids; + ids.push_back( 23 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + LoadBitmapResource( platform ); + + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) ); + + // never discard texture + Stage::GetCurrent().Remove(actor); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) ); + END_TEST; +} + +// 1.4 +int UtcDaliResourceImageNewWithPolicies02(void) +{ + TestApplication application; + TestPlatformAbstraction& platform = application.GetPlatform(); + const Vector2 closestImageSize( 80, 45); + platform.SetClosestImageSize(closestImageSize); + + // testing resource deletion when taken off stage + tet_infoline("UtcDaliResourceImageNewWithPolicies02 - Load image with LoadPolicy::OnDemand, ReleasePolicy::Unused"); + + ResourceImage image = ResourceImage::New(gTestImageFilename, ResourceImage::ON_DEMAND, Image::UNUSED); + + DALI_TEST_CHECK( image ); + + application.SendNotification(); + application.Render(16); + + // request file loading only when actor added to stage + DALI_TEST_CHECK( !platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + + ImageActor actor = ImageActor::New(image); + + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + + DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + + // testing ReleasePolicy::Unused + // fake loading image + std::vector ids; + ids.push_back( 23 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + LoadBitmapResource( platform ); + + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) ); + + // discard texture when actor comes off stage + Stage::GetCurrent().Remove(actor); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + DALI_TEST_CHECK ( application.GetGlAbstraction().CheckTextureDeleted(23) ); + END_TEST; +} + +// 1.5 +int UtcDaliResourceImageNewWithPolicies03(void) +{ + TestApplication application; + TestPlatformAbstraction& platform = application.GetPlatform(); + const Vector2 closestImageSize( 80, 45); + platform.SetClosestImageSize(closestImageSize); + + // load immediately -> resource deletion when taken off stage -> put actor back on stage -> load resource again + tet_infoline("UtcDaliResourceImageNewWithPolicies03 - Load image with LoadPolicy::Immediate, ReleasePolicy::Unused"); + + ResourceImage image = ResourceImage::New(gTestImageFilename, ResourceImage::IMMEDIATE, Image::UNUSED); + + DALI_TEST_CHECK( image ); + + application.SendNotification(); + application.Render(16); + + // request file loading immediately + DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + + ImageActor actor = ImageActor::New(image); + + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + + // testing ReleasePolicy::Unused + // fake loading image + std::vector ids; + ids.push_back( 23 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + LoadBitmapResource( platform ); + + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) ); + + // discard texture when actor comes off stage + Stage::GetCurrent().Remove(actor); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + DALI_TEST_CHECK ( application.GetGlAbstraction().CheckTextureDeleted(23) ); + + // check load request when actor added back to stage + application.GetPlatform().ResetTrace(); + + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + + DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + END_TEST; +} + +// 1.6 +int UtcDaliResourceImageNewWithPolicies04(void) +{ + TestApplication application; + TestPlatformAbstraction& platform = application.GetPlatform(); + + // load immediately, don't release texture when off stage + tet_infoline("UtcDaliResourceImageNewWithPolicies03 - Load image with LoadPolicy::Immediate, ReleasePolicy::Never"); + + ResourceImage image = ResourceImage::New(gTestImageFilename, ResourceImage::IMMEDIATE, Image::NEVER); + + DALI_TEST_CHECK( image ); + + application.SendNotification(); + application.Render(16); + + // request file loading immediately + DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + + ImageActor actor = ImageActor::New(image); + + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + + // testing ReleasePolicy::Never + // fake loading image + std::vector ids; + ids.push_back( 23 ); + application.GetGlAbstraction().SetNextTextureIds( ids ); + LoadBitmapResource(platform); + + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) ); + + // texture is not discarded + Stage::GetCurrent().Remove(actor); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) ); + + // no load request when actor added back to stage + application.GetPlatform().ResetTrace(); + + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + + DALI_TEST_CHECK( !platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) ); + END_TEST; +} + +// 1.7 +int UtcDaliResourceImageDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::ResourceImage::DownCast()"); + + ResourceImage image = ResourceImage::New(gTestImageFilename); + + BaseHandle object(image); + + ResourceImage image2 = ResourceImage::DownCast(object); + DALI_TEST_CHECK(image2); + + ResourceImage image3 = DownCast< ResourceImage >(object); + DALI_TEST_CHECK(image3); + + BaseHandle unInitializedObject; + ResourceImage image4 = ResourceImage::DownCast(unInitializedObject); + DALI_TEST_CHECK(!image4); + + ResourceImage image5 = DownCast< ResourceImage >(unInitializedObject); + DALI_TEST_CHECK(!image5); + + Image image6 = ResourceImage::New(gTestImageFilename); + ResourceImage image7 = ResourceImage::DownCast(image6); + DALI_TEST_CHECK(image7); + END_TEST; +} + +// 1.8 +int UtcDaliResourceImageGetImageSize(void) +{ + TestApplication application; + TestPlatformAbstraction& platform = application.GetPlatform(); + + tet_infoline("UtcDaliResourceImageGetImageSize - ResourceImage::GetImageSize()"); + + Vector2 testSize(8.0f, 16.0f); + platform.SetClosestImageSize(testSize); + + const ImageDimensions size = ResourceImage::GetImageSize(gTestImageFilename); + + DALI_TEST_CHECK( application.GetPlatform().GetTrace().FindMethod("GetClosestImageSize")); + DALI_TEST_EQUALS( Vector2( size.GetX(), size.GetY() ), testSize, TEST_LOCATION); + END_TEST; +} + +// 1.9 +int UtcDaliResourceImageGetUrl(void) +{ + TestApplication application; + + tet_infoline("UtcDaliResourceImageGetFilename - ResourceImage::GetUrl()"); + + // invoke default handle constructor + ResourceImage image; + + DALI_TEST_CHECK( !image ); + + // initialise handle + image = ResourceImage::New(gTestImageFilename); + + DALI_TEST_EQUALS( image.GetUrl(), gTestImageFilename, TEST_LOCATION); + END_TEST; +} + +// 1.10 +int UtcDaliResourceImageGetLoadingState01(void) +{ + TestApplication application; + tet_infoline("UtcDaliResourceImageGetLoadingState01"); + + ResourceImage image = ResourceImage::New(gTestImageFilename); + DALI_TEST_CHECK(image.GetLoadingState() == ResourceLoading); + application.SendNotification(); + application.Render(16); + + // simulate load success + TestPlatformAbstraction& platform = application.GetPlatform(); + LoadBitmapResource( platform ); + application.Render(16); + application.SendNotification(); + + // Test state == ResourceLoadingSucceeded + DALI_TEST_CHECK(image.GetLoadingState() == ResourceLoadingSucceeded); + END_TEST; +} + +// 1.11 +int UtcDaliResourceImageGetLoadingState02(void) +{ + TestApplication application; + + tet_infoline("UtcDaliResourceImageGetLoadingState02"); + + // invoke default handle constructor + ResourceImage image; + + DALI_TEST_CHECK( !image ); + + // initialise handle + image = ResourceImage::New(gTestImageFilename); + + // Test state == ResourceLoading + DALI_TEST_CHECK(image.GetLoadingState() == ResourceLoading); + application.SendNotification(); + application.Render(16); + + // simulate load failure + Integration::ResourceRequest* request = application.GetPlatform().GetRequest(); + if(request) + { + application.GetPlatform().SetResourceLoadFailed(request->GetId(), Integration::FailureUnknown); + } + application.Render(16); + application.SendNotification(); + + // Test state == ResourceLoadingFailed + DALI_TEST_CHECK(image.GetLoadingState() == ResourceLoadingFailed); + END_TEST; +} + +// 1.12 +int UtcDaliResourceImageGetLoadPolicy(void) +{ + TestApplication application; + + tet_infoline("UtcDaliImageGetLoadPolicy"); + + ResourceImage image = ResourceImage::New(gTestImageFilename, ResourceImage::ON_DEMAND, Image::NEVER); + + DALI_TEST_CHECK( image ); + + DALI_TEST_CHECK( ResourceImage::ON_DEMAND == image.GetLoadPolicy()); + END_TEST; +} + +static bool SignalLoadFlag = false; + +static void SignalLoadHandler(ResourceImage image) +{ + tet_infoline("Received image load finished signal"); + + SignalLoadFlag = true; +} + +// 1.13 +int UtcDaliResourceImageSignalLoadingFinished(void) +{ + TestApplication application; + + tet_infoline("UtcDaliResourceImageSignalLoadingFinished"); + + SignalLoadFlag = false; + + ResourceImage image = ResourceImage::New(gTestImageFilename); + + image.LoadingFinishedSignal().Connect( SignalLoadHandler ); + application.SendNotification(); + application.Render(16); + + Integration::ResourceRequest* request = application.GetPlatform().GetRequest(); + if(request) + { + application.GetPlatform().SetResourceLoaded(request->GetId(), request->GetType()->id, Integration::ResourcePointer(Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD))); + } + + application.Render(16); + application.SendNotification(); + + DALI_TEST_CHECK( SignalLoadFlag == true ); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-ShaderEffect.cpp b/automated-tests/src/dali/utc-Dali-ShaderEffect.cpp new file mode 100644 index 0000000..0ce5d47 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-ShaderEffect.cpp @@ -0,0 +1,949 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_shader_effect_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_shader_effect_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +static const char* VertexSource = +"This is a custom vertex shader\n" +"made on purpose to look nothing like a normal vertex shader inside dali\n"; + +static const char* FragmentSource = +"This is a custom fragment shader\n" +"made on purpose to look nothing like a normal fragment shader inside dali\n"; + +const int GETSOURCE_BUFFER_SIZE = 0x10000; + + +struct TestConstraintToVector3 +{ + TestConstraintToVector3(Vector3 target) + : mTarget(target) + { + } + + void operator()( Vector3& current, const PropertyInputContainer& /* inputs */ ) + { + current = mTarget; + } + + Vector3 mTarget; +}; + +struct TestConstraintFromPositionToVector3 +{ + TestConstraintFromPositionToVector3() + { + } + + void operator()( Vector3& current, const PropertyInputContainer& inputs ) + { + current = inputs[0]->GetVector3(); + } +}; + +struct TestConstraintToVector3Double +{ + TestConstraintToVector3Double(Vector3 target) + : mTarget(target) + { + } + + void operator()( Vector3& current, const PropertyInputContainer& /* inputs */ ) + { + current = mTarget * 2.0f; + } + + Vector3 mTarget; +}; + +static const char* TestImageFilename = "icon_wrt.png"; + +Integration::Bitmap* CreateBitmap( unsigned int imageHeight, unsigned int imageWidth, unsigned int initialColor ) +{ + Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN ); + Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, imageWidth,imageHeight,imageWidth,imageHeight ); + unsigned int bytesPerPixel = GetBytesPerPixel( Pixel::RGBA8888 ); + + memset( pixbuffer, initialColor , imageHeight*imageWidth*bytesPerPixel); + + return bitmap; +} + +} // anon namespace + + +int UtcDaliShaderEffectMethodNew01(void) +{ + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK(effect); + END_TEST; +} + +int UtcDaliShaderEffectMethodNew02(void) +{ + TestApplication application; + + ShaderEffect effect; + + try + { + // New must be called to create a ShaderEffect or it wont be valid. + effect.SetUniform( "uUniform", 0 ); + DALI_TEST_CHECK( false ); + } + catch (Dali::DaliException& e) + { + // Tests that a negative test of an assertion succeeds + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_CHECK( !effect ); + } + END_TEST; +} + +int UtcDaliShaderEffectMethodNew05(void) +{ + TestApplication application; + + // heap constructor / destructor + DefaultFunctionCoverage shaderEffect; + + END_TEST; +} + +int UtcDaliShaderEffectMethodDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::ShaderEffect::DownCast()"); + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + + BaseHandle object(effect); + + ShaderEffect effect2 = ShaderEffect::DownCast(object); + DALI_TEST_CHECK(effect2); + + ShaderEffect effect3 = DownCast< ShaderEffect >(object); + DALI_TEST_CHECK(effect3); + + BaseHandle unInitializedObject; + ShaderEffect effect4 = ShaderEffect::DownCast(unInitializedObject); + DALI_TEST_CHECK(!effect4); + + ShaderEffect effect5 = DownCast< ShaderEffect >(unInitializedObject); + DALI_TEST_CHECK(!effect5); + END_TEST; +} + +int UtcDaliShaderEffectMethodDelete01(void) +{ + TestApplication application; + + // get the default shaders built, this is not required but makes it + // easier to debug the TET case and isolate the custom shader compilation. + application.SendNotification(); + application.Render(); + + GLuint beforeShaderCompiled = application.GetGlAbstraction().GetLastShaderCompiled(); + + // create a new shader effect + // the vertex and fragment shader will be cached in the ShaderFactory + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + + // destroy the shader effect + effect.Reset(); + + // Create the same shader effect again, this should now use the cached version + // held in the shader factory + effect= ShaderEffect::New( VertexSource, FragmentSource ); + + // Compile the shader effect + application.SendNotification(); + application.Render(); + + GLuint lastShaderCompiled = application.GetGlAbstraction().GetLastShaderCompiled(); + // no shaders were compiled as they are now compiled on demand and this shader was not used + DALI_TEST_EQUALS( beforeShaderCompiled, lastShaderCompiled, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliShaderEffectMethodSetUniformFloat(void) +{ + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + effect.SetUniform( "uFloat", 1.0f ); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uFloat", 1.0f ) ); + END_TEST; +} + +int UtcDaliShaderEffectMethodSetUniformVector2(void) +{ + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + effect.SetUniform( "uVec2", Vector2( 2.0f, 3.0f ) ); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uVec2", Vector2( 2.0f, 3.0f ) ) ); + END_TEST; +} + +int UtcDaliShaderEffectMethodSetUniformVector3(void) +{ + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + effect.SetUniform( "uVec3", Vector3( 4.0f, 5.0f, 6.0f ) ); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uVec3", Vector3( 4.0f, 5.0f, 6.0f ) ) ); + END_TEST; +} + +int UtcDaliShaderEffectMethodSetUniformVector4(void) +{ + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + effect.SetUniform( "uVec4", Vector4( 7.0f, 8.0f, 9.0f, 10.0f ) ); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uVec4", Vector4( 7.0f, 8.0f, 9.0f, 10.0f ) ) ); + END_TEST; +} + +int UtcDaliShaderEffectMethodSetUniformMatrix(void) +{ + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + effect.SetUniform( "uModelView", Matrix::IDENTITY ); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uModelView", Matrix::IDENTITY ) ); + END_TEST; +} + +int UtcDaliShaderEffectMethodSetUniformMatrix3(void) +{ + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + Matrix3 matIdentity(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f); + effect.SetUniform( "uMatrix3", matIdentity ); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( application.GetGlAbstraction().CheckUniformValue("uMatrix3", matIdentity) ); + END_TEST; +} + +int UtcDaliShaderEffectMethodSetUniformViewport(void) +{ + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + effect.SetUniform( "uVec2", Vector2( 0.0f, 0.0f ), ShaderEffect::COORDINATE_TYPE_VIEWPORT_POSITION ); + effect.SetUniform( "uVec2Dir", Vector2( 1.0f, 2.0f ), ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION ); + + application.SendNotification(); + application.Render(); + + const Vector2& stageSize(Stage::GetCurrent().GetSize()); + + DALI_TEST_CHECK( application.GetGlAbstraction().CheckUniformValue( "uVec2", Vector2( stageSize.x/2, -stageSize.y/2 ) ) ); + + DALI_TEST_CHECK( application.GetGlAbstraction().CheckUniformValue( "uVec2Dir", Vector2( -1.0f, 2.0f ) ) ); + + // change coordinate types + effect.SetUniform( "uVec2", Vector2( 0.1f, 0.2f ), ShaderEffect::COORDINATE_TYPE_DEFAULT ); + effect.SetUniform( "uVec2Dir", Vector2( 1.0f, 2.0f ), ShaderEffect::COORDINATE_TYPE_VIEWPORT_POSITION ); + actor.SetPixelArea( ImageActor::PixelArea( 0, 0, 10, 10 ) ); + + application.SendNotification(); + application.Render(); + + Vector2 outValue; + application.GetGlAbstraction().GetUniformValue( "uVec2", outValue ); + DALI_TEST_EQUALS( outValue, Vector2( 0.1f, 0.2f ), TEST_LOCATION ); + + application.GetGlAbstraction().GetUniformValue( "uVec2Dir", outValue ); + DALI_TEST_EQUALS( outValue, Vector2( stageSize.x *.5f - 1.f, -stageSize.y * .5f + 2.f), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliShaderEffectMethodSetEffectImage(void) +{ + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + effect.SetEffectImage(image); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + + GLuint programId, uniformId; + bool uniformWasSet = application.GetGlAbstraction().GetUniformIds( "sEffect", programId, uniformId ); + // we dont care about the value of the sampler uniform as thats internal to DALi core and subject to change + DALI_TEST_CHECK( uniformWasSet ); + END_TEST; +} + +int UtcDaliShaderEffectMethodSetEffectImageAndDelete(void) +{ + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + + BufferImage effectImage = CreateBufferImage(); + effect.SetEffectImage(effectImage); + + ImageActor actor = ImageActor::New(); + + actor.SetShaderEffect(effect); + effect.Reset(); + + Stage::GetCurrent().Add(actor); + + // do an update / render cycle + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + application.SendNotification(); + application.Render(16); + + printf("removing image actor from stage and Reseting handle\n"); + Stage::GetCurrent().Remove(actor); + actor.Reset(); + + tet_printf("### Update & Render \n"); + + application.SendNotification(); + application.Render(16); + + tet_printf("#### Update Only \n"); + + tet_printf("effectImage.Reset \n"); + + // this releases the effect texture resource, + // Update will send a DispatchDiscardTexture message to render + effectImage.Reset(); + application.SendNotification(); + application.UpdateOnly(16); + + tet_printf("#### Update Only \n"); + + // at this point shader is deleted, during clear discard queue + // and it sends a Shader:: DispatchRemoveObserver message to render thread + application.UpdateOnly(16); + + tet_printf("#### Render Only \n"); + // This is where it used to crash, there is a message in the queue to perform DispatchDiscardTexture + // which tries to call observer->TextureDiscarded, where observer == shader that was deleted + // in previous update. + application.RenderOnly(); + + + // process the discard texture message + application.RenderOnly(); + application.SendNotification(); + application.Render(16); + + tet_result(TET_PASS); + + END_TEST; +} + +int UtcDaliShaderEffectMethodApplyConstraint(void) +{ + // Test whether Shader's uniform can be constrained to a stationary constraint. + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + effect.SetUniform( "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + Property::Index uVecProperty = effect.GetPropertyIndex("uVec3"); + + application.SendNotification(); + application.Render(); + + // Test effects of SetUniform... + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ) ); + + Constraint constraint = Constraint::New( effect, uVecProperty, TestConstraintToVector3(Vector3(4.0f, 9.0f, 16.0f)) ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + // Test effects of Constraint. + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uVec3", Vector3( 4.0f, 9.0f, 16.0f ) ) ); + END_TEST; +} + +int UtcDaliShaderEffectMethodApplyConstraintOffStage(void) +{ + // The same test as UtcDaliShaderEffectMethodApplyConstraint, + // except the Actor is off-stage when the constraint is applied to the shader + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + effect.SetUniform( "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + // Note - Do not add actor to stage here + + Property::Index uVecProperty = effect.GetPropertyIndex("uVec3"); + + Constraint constraint = Constraint::New( effect, uVecProperty, TestConstraintToVector3(Vector3(4.0f, 9.0f, 16.0f)) ); + constraint.Apply(); + + // Note - Now we add the actor (after constraint was applied to the shader) + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + + // Test effects of Constraint. + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uVec3", Vector3( 4.0f, 9.0f, 16.0f ) ) ); + END_TEST; +} + +int UtcDaliShaderEffectMethodApplyConstraintFromActor(void) +{ + // Test whether Shader's uniform can be constrained to Actor's position. + TestApplication application; + + const Vector3 targetPosition = Vector3( 100.0f, 70.0f, 20.0f); + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + effect.SetUniform( "uVec3", Vector3( 50.0f, 25.0f, 0.0f ) ); + + ImageActor actor = ImageActor::New( image ); + actor.SetPosition(targetPosition); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + Property::Index uVecProperty = effect.GetPropertyIndex("uVec3"); + + Constraint constraint = Constraint::New( effect, uVecProperty, TestConstraintFromPositionToVector3() ); + constraint.AddSource( Source( actor, Actor::Property::POSITION ) ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + // Test effects of Constraint. + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uVec3", targetPosition ) ); + END_TEST; +} + +int UtcDaliShaderEffectMethodApplyConstraintFromActor2(void) +{ + // Test whether Shader's uniform can be constrained to Actor's position. + // While Actor's position is constrained to another point * 2.0f + TestApplication application; + + const Vector3 targetPosition = Vector3( 25.0f, 36.0f, 49.0f ); + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + effect.SetUniform( "uVec3", Vector3( 50.0f, 25.0f, 0.0f ) ); + + ImageActor actor = ImageActor::New( image ); + actor.SetPosition(Vector3( 100.0f, 70.0f, 20.0f)); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + Property::Index uVecProperty = effect.GetPropertyIndex("uVec3"); + + Constraint shaderConstraint = Constraint::New( effect, uVecProperty, TestConstraintFromPositionToVector3() ); + shaderConstraint.AddSource( Source(actor, Actor::Property::POSITION) ); + shaderConstraint.Apply(); + + Constraint actorConstraint = Constraint::New( actor, Actor::Property::POSITION, TestConstraintToVector3Double(targetPosition) ); + actorConstraint.Apply(); + + application.SendNotification(); + application.Render(); + + // Test effects of Constraint. + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uVec3", targetPosition * 2.0f ) ); + END_TEST; +} + +int UtcDaliShaderEffectMethodRemoveConstraints(void) +{ + // Test if constrains can be removed before they are ever applyed. + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + effect.SetUniform( "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + Property::Index uVecProperty = effect.GetPropertyIndex("uVec3"); + + application.SendNotification(); + application.Render(); + + // Test effects of SetUniform... + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ) ); + + Constraint constraint = Constraint::New( effect, uVecProperty, TestConstraintToVector3(Vector3(4.0f, 9.0f, 16.0f)) ); + constraint.Apply(); + + // Remove the constraints + effect.RemoveConstraints(); + + application.SendNotification(); + application.Render(); + + // Test effects of Constraint. + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ) ); + END_TEST; +} + +int UtcDaliShaderEffectMethodRemoveConstraints2(void) +{ + // Test whether Shader's uniform constrains can be removed after they are applyed. + TestApplication application; + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + + effect.SetUniform( "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ); + + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + Property::Index uVecProperty = effect.GetPropertyIndex("uVec3"); + + application.SendNotification(); + application.Render(); + + // Test effects of SetUniform... + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ) ); + + Constraint constraint = Constraint::New( effect, uVecProperty, TestConstraintToVector3(Vector3(4.0f, 9.0f, 16.0f)) ); + constraint.Apply(); + + application.SendNotification(); + application.Render(); + + // Reset the value and remove the constraints + effect.SetUniform( "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ); + effect.RemoveConstraints(); + + application.SendNotification(); + application.Render(); + + // Test effects of Constraint. + DALI_TEST_CHECK( + application.GetGlAbstraction().CheckUniformValue( + "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ) ); + END_TEST; +} + +int UtcDaliShaderEffectPropertyIndices(void) +{ + TestApplication application; + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + + Property::IndexContainer indices; + effect.GetPropertyIndices( indices ); + DALI_TEST_CHECK( indices.Size() ); + DALI_TEST_EQUALS( indices.Size(), effect.GetPropertyCount(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliShaderBinaries(void) +{ + TestApplication application; + // these will not affect the "first round" of dali render as core is already initialized and it has queried the defaults + application.GetGlAbstraction().SetBinaryFormats( 1 ); + application.GetGlAbstraction().SetNumBinaryFormats( 1 ); + application.GetGlAbstraction().SetProgramBinaryLength( 1 ); + + GLuint lastShaderCompiledBefore = application.GetGlAbstraction().GetLastShaderCompiled(); + + ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource ); + DALI_TEST_CHECK( effect ); + + BufferImage image = CreateBufferImage(); + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(16); + // binary was not requested by DALi + DALI_TEST_CHECK( !(application.GetGlAbstraction().GetProgramBinaryCalled()) ); + + GLuint lastShaderCompiledAfter = application.GetGlAbstraction().GetLastShaderCompiled(); + + // check that the shader was compiled + DALI_TEST_EQUALS( lastShaderCompiledAfter, lastShaderCompiledBefore + 2, TEST_LOCATION ); + + // simulate context loss to get core to re-initialize its GL + application.GetCore().ContextDestroyed(); + application.GetCore().ContextCreated(); + + application.SendNotification(); + application.Render(16); + + // shader is recompiled + GLuint finalShaderCompiled = application.GetGlAbstraction().GetLastShaderCompiled(); + // check that the shader was compiled + DALI_TEST_EQUALS( lastShaderCompiledAfter + 2, finalShaderCompiled, TEST_LOCATION ); + + // binary was requested by DALi + DALI_TEST_CHECK( application.GetGlAbstraction().GetProgramBinaryCalled() ); + + END_TEST; +} + +int UtcDaliShaderEffectFromPropertiesP(void) +{ + TestApplication application; + tet_infoline("UtcDaliShaderEffectFromProperties01()"); + + std::string fragmentShaderPrefix = "#define TEST_FS 1\n#extension GL_OES_standard_derivatives : enable"; + std::string vertexShaderPrefix = "#define TEST_VS 1"; + std::string vertexShader(VertexSource); + std::string fragmentShader(FragmentSource); + + // Call render to compile default shaders. + application.SendNotification(); + application.Render(); + + GLuint lastShaderCompiledBefore = application.GetGlAbstraction().GetLastShaderCompiled(); + + // create from type registry + + TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( "ShaderEffect" ); + DALI_TEST_CHECK( typeInfo ); + ShaderEffect effect = ShaderEffect::DownCast( typeInfo.CreateInstance() ); + DALI_TEST_CHECK( effect ); + + Property::Value programValue = Property::Value(Property::MAP); + Property::Map* programMap = programValue.GetMap(); + DALI_TEST_CHECK( programMap ); + + programMap->Insert("vertex", vertexShader); + programMap->Insert("fragment", fragmentShader); + + programMap->Insert("vertex-prefix", vertexShaderPrefix); + programMap->Insert("fragment-prefix", fragmentShaderPrefix); + + effect.SetProperty(effect.GetPropertyIndex("program"), programValue); + + Property::Value imageValue = Property::Value(Property::MAP); + Property::Map* imageMap = imageValue.GetMap(); + DALI_TEST_CHECK( imageMap ); + imageMap->Insert("filename", Property::Value(TestImageFilename)); + effect.SetProperty(effect.GetPropertyIndex("image"), imageValue); + + // do a update & render to get the image request + application.SendNotification(); + application.Render(); + + Integration::ResourceRequest* request = application.GetPlatform().GetRequest(); + // create the image + Integration::Bitmap* bitmap = CreateBitmap( 10, 10, 0xFF ); + Integration::ResourcePointer resourcePtr(bitmap); + TestPlatformAbstraction& platform = application.GetPlatform(); + platform.SetResourceLoaded(request->GetId(), request->GetType()->id, resourcePtr); + + BufferImage image(CreateBufferImage()); + ImageActor actor = ImageActor::New( image ); + actor.SetSize( 100.0f, 100.0f ); + actor.SetName("TestImageFilenameActor"); + actor.SetShaderEffect(effect); + Stage::GetCurrent().Add(actor); + + application.SendNotification(); + application.Render(); + GLuint lastShaderCompiledAfter = application.GetGlAbstraction().GetLastShaderCompiled(); + + // we should have compiled 2 shaders. + DALI_TEST_EQUALS(lastShaderCompiledAfter, lastShaderCompiledBefore + 2, TEST_LOCATION ); + + std::string actualVertexShader = application.GetGlAbstraction().GetShaderSource( lastShaderCompiledBefore + 1 ); + DALI_TEST_EQUALS( vertexShaderPrefix, actualVertexShader.substr( 0, vertexShaderPrefix.length() ), TEST_LOCATION ); + DALI_TEST_EQUALS( vertexShader, actualVertexShader.substr( actualVertexShader.length() - vertexShader.length() ), TEST_LOCATION ); + + std::string actualFragmentShader = application.GetGlAbstraction().GetShaderSource( lastShaderCompiledBefore + 2 ); + DALI_TEST_EQUALS( fragmentShaderPrefix, actualFragmentShader.substr( 0, fragmentShaderPrefix.length() ), TEST_LOCATION ); + DALI_TEST_EQUALS( fragmentShader, actualFragmentShader.substr( actualFragmentShader.length() - fragmentShader.length() ), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliShaderEffectFromPropertiesN(void) +{ + try + { + TestApplication application; + tet_infoline("UtcDaliShaderEffectFromProperties02()"); + + // Call render to compile default shaders. + application.SendNotification(); + application.Render(); + + // create from type registry (currently only way to get ShaderEffect with no shader setup in constructor + TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( "ShaderEffect" ); + DALI_TEST_CHECK( typeInfo ); + ShaderEffect effect = ShaderEffect::DownCast( typeInfo.CreateInstance() ); + DALI_TEST_CHECK( effect ); + + Property::Value programValue = Property::Value(Property::MAP); + Property::Map* programMap = programValue.GetMap(); + DALI_TEST_CHECK( programMap ); + + programMap->Insert("vertex", std::string(VertexSource)); + programMap->Insert("fragment", std::string(FragmentSource)); + + // use wrong index on purpose + effect.SetProperty(effect.GetPropertyIndex("program") + 1, programValue ); + + tet_result( TET_FAIL ); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + } + END_TEST; +} + +int UtcDaliShaderEffectFromProperties2N(void) +{ + try + { + TestApplication application; + tet_infoline("UtcDaliShaderEffectFromProperties03()"); + + // Call render to compile default shaders. + application.SendNotification(); + application.Render(); + + // create from type registry (currently only way to get ShaderEffect with no shader setup in constructor + TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( "ShaderEffect" ); + DALI_TEST_CHECK( typeInfo ); + ShaderEffect effect = ShaderEffect::DownCast( typeInfo.CreateInstance() ); + DALI_TEST_CHECK( effect ); + + // dont set unknown + effect.SetProperty( effect.GetPropertyIndex("geometry-hints"), "HINT_2" ); + + tet_result( TET_FAIL ); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + } + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-SignalTemplates.cpp b/automated-tests/src/dali/utc-Dali-SignalTemplates.cpp new file mode 100644 index 0000000..e1e20d5 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-SignalTemplates.cpp @@ -0,0 +1,2228 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include "signal-helper.h" + +using namespace Dali; + +bool StaticFunctionHandlers::staticFunctionHandled; + +void utc_dali_signal_templates_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_signal_templates_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace { + + +bool wasStaticVoidCallbackVoidCalled = false; +bool wasStaticFloatCallbackVoidCalled = false; +bool wasStaticVoidCallbackIntValueCalled = false; +int staticIntValue = 0; +bool wasStaticFloatCallbackFloatValueFloatValueCalled = false; +float staticFloatValue1 = 0.0f; +float staticFloatValue2 = 0.0f; + +void StaticVoidCallbackVoid() +{ + wasStaticVoidCallbackVoidCalled = true; +} + +void AlternativeVoidCallbackVoid() +{ +} + +float StaticFloatCallbackVoid() +{ + wasStaticFloatCallbackVoidCalled = true; + return 7.0f; +} + +void StaticVoidCallbackIntValue( int value ) +{ + wasStaticVoidCallbackIntValueCalled = true; + staticIntValue = value; +} + +float StaticFloatCallbackFloatValueFloatValue( float value1, float value2 ) +{ + wasStaticFloatCallbackFloatValueFloatValueCalled = true; + staticFloatValue1 = value1; + staticFloatValue2 = value2; + return value1 + value2; +} + +} // anon namespace + + + +/******************************************* + * + * Start of Utc test cases. + * Test cases performed in order of API listed in dali-signal.h + * UtcDaliSignal + FunctionName + P=positive test, N = Negative test + * + */ + +int UtcDaliSignalEmptyP(void) +{ + TestApplication app; // Create core for debug logging + + // Test that Empty() is true, when no slots connected to the signal + + { + TestSignals::VoidRetNoParamSignal signal; + DALI_TEST_CHECK( signal.Empty() ); + } + + // Test that Empty() is true, when a slot has connected and disconnected + { + TestSignals::VoidRetNoParamSignal signal; + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::VoidSlotVoid ); + signal.Disconnect( &handler, &TestSlotHandler::VoidSlotVoid ); + DALI_TEST_CHECK( signal.Empty() ); + } + + END_TEST; +} + +int UtcDaliSignalEmptyN(void) +{ + TestApplication app; // Create core for debug logging + + // Test that Empty() is false after signal connection + TestSignals::VoidRetNoParamSignal signal; + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::VoidSlotVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + + END_TEST; +} + +int UtcDaliSignalGetConnectionCountP(void) +{ + TestApplication app; // Create core for debug logging + + TestSignals::VoidRetNoParamSignal signal; + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::VoidSlotVoid ); + DALI_TEST_CHECK( signal.GetConnectionCount() == 1 ); + + TestSlotHandler handler2; + signal.Connect( &handler2, &TestSlotHandler::VoidSlotVoid ); + DALI_TEST_CHECK( signal.GetConnectionCount() == 2 ); + + END_TEST; +} + +int UtcDaliSignalGetConnectionCountN(void) +{ + TestApplication app; // Create core for debug logging + TestSignals::VoidRetNoParamSignal signal; + DALI_TEST_CHECK( signal.GetConnectionCount() == 0 ); + END_TEST; +} + +/** + * there are 5 different connection functions + * we go through them here in order of definition in dali-signal.h + */ +int UtcDaliSignalConnectP01(void) +{ + TestApplication app; // Create core for debug logging + + // test static function: void Connect( void (*func)() ) + TestSignals::VoidRetNoParamSignal signal; + signal.Connect( StaticVoidCallbackVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + + + END_TEST; +} + +int UtcDaliSignalConnectN01(void) +{ + // difficult to perform a negative test on Connect as no checks are performed + // when creating a callback for a null function ( during Connect). + // so we test an assert on Emit + TestApplication app; // Create core for debug logging + + TestSignals::VoidRetNoParamSignal signal; + signal.Connect( NULL ); + try + { + signal.Emit(); + } + catch (Dali::DaliException& e) + { + // Tests that a negative test of an assertion succeeds + DALI_TEST_PRINT_ASSERT( e ); + tet_result(TET_PASS); + } + END_TEST; +} + + +int UtcDaliSignalConnectP02(void) +{ + TestApplication app; // Create core for debug logging + + // test member function: Connect( X* obj, void (X::*func)() )) + TestSignals::VoidRetNoParamSignal signal; + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::VoidSlotVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + signal.Emit(); + DALI_TEST_CHECK( handler.mHandled == true ); + END_TEST; +} + +int UtcDaliSignalConnectN02(void) +{ + TestApplication app; // Create core for debug logging + + TestSignals::VoidRetNoParamSignal signal; + try + { + // test member function: Connect( X* obj, void (X::*func)() )) with NULL object + signal.Connect( static_cast(NULL), &TestSlotHandler::VoidSlotVoid ); + } + catch (Dali::DaliException& e) + { + // Tests that a negative test of an assertion succeeds + DALI_TEST_PRINT_ASSERT( e ); + tet_result(TET_PASS); + } + END_TEST; +} + + +int UtcDaliSignalConnectP03(void) +{ + TestApplication app; // Create core for debug logging + + // test slot delegate: Connect( SlotDelegate& delegate, void (X::*func)() ) + TestSignals::VoidRetNoParamSignal signal; + TestSlotDelegateHandler handler; + signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + signal.Emit(); + DALI_TEST_CHECK( handler.mHandled == true ); + + END_TEST; +} + +int UtcDaliSignalConnectN03(void) +{ + TestApplication app; // Create core for debug logging + // the delegate is passed by reference, so you can't pass null. + tet_result( TET_PASS ); + END_TEST; +} + +int UtcDaliSignalConnectP04(void) +{ + TestApplication app; // Create core for debug logging + + // test function object: Connect( ConnectionTrackerInterface* connectionTracker, const X& func ) + TestSlotHandler handler; + TestSignals::VoidRetNoParamSignal signal; + bool functorCalled(false); + TestFunctor functor( functorCalled ); + signal.Connect( &handler, functor ); + DALI_TEST_CHECK( ! signal.Empty() ); + signal.Emit(); + DALI_TEST_CHECK( functorCalled == true ); + + END_TEST; +} + +int UtcDaliSignalConnectN04(void) +{ + // for negative test we try to connect a null connection tracker to the signal + TestSignals::VoidRetNoParamSignal signal; + TestSlotHandler *nullHandler( NULL ); + try + { + signal.Connect( nullHandler , &TestSlotHandler::VoidSlotVoid ); + } + catch (Dali::DaliException& e) + { + // Tests that a negative test of an assertion succeeds + DALI_TEST_PRINT_ASSERT( e ); + tet_result( TET_PASS ); + } + + END_TEST; + +} + +int UtcDaliSignalConnectP05(void) +{ + TestApplication app; // Create core for debug logging + + // test function object using FunctorDelegate. + // :Connect( ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate ) + { + TestSlotHandler handler; + TestSignals::VoidRetNoParamSignal signal; + bool functorDelegateCalled(false); + signal.Connect( &handler, FunctorDelegate::New( VoidFunctorVoid(functorDelegateCalled) )); + DALI_TEST_CHECK( ! signal.Empty() ); + signal.Emit(); + DALI_TEST_CHECK( functorDelegateCalled == true ); + } + { + TestSlotHandler handler; + TestSignals::VoidRet1ValueParamSignal signal; + bool functorDelegateCalled(false); + signal.Connect( &handler, FunctorDelegate::New( VoidFunctorVoid(functorDelegateCalled) )); + DALI_TEST_CHECK( ! signal.Empty() ); + signal.Emit(1); + } + END_TEST; +} + +int UtcDaliSignalConnectN05(void) +{ + TestApplication app; // Create core for debug logging + + // for negative test we try to connect a null connection tracker to the signal + // :Connect( ConnectionTrackerInterface == NULL, FunctorDelegate* delegate ) + TestSlotHandler *nullHandler( NULL ); + TestSignals::VoidRetNoParamSignal signal; + bool functorDelegateCalled(false); + try + { + signal.Connect( nullHandler, FunctorDelegate::New( VoidFunctorVoid(functorDelegateCalled) )); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + tet_result( TET_PASS ); + } + END_TEST; +} + + +/** + * there 3 different disconnect functions + * we go through them here in order of definition in dali-signal.h + */ +int UtcDaliSignalDisconnectP01(void) +{ + TestApplication app; // Create core for debug logging + + // test static function: Disconnect( void (*func)( Arg0 arg0 ) ) + + TestSignals::VoidRetNoParamSignal signal; + signal.Connect( StaticVoidCallbackVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + signal.Disconnect( StaticVoidCallbackVoid ); + DALI_TEST_CHECK( signal.Empty() ); + + END_TEST; + + } +int UtcDaliSignalDisconnectN01(void) +{ + TestApplication app; // Create core for debug logging + + // 1. Disconnect using the function + TestSignals::VoidRetNoParamSignal signal; + signal.Connect( StaticVoidCallbackVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + + signal.Disconnect( AlternativeVoidCallbackVoid ); + + DALI_TEST_CHECK( ! signal.Empty() ); + + END_TEST; +} + +int UtcDaliSignalDisconnectP02(void) +{ + TestApplication app; // Create core for debug logging + + // test member function: Disconnect( X* obj, void (X::*func)( Arg0 arg0 ) ) + TestSignals::VoidRetNoParamSignal signal; + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::VoidSlotVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + signal.Disconnect( &handler, &TestSlotHandler::VoidSlotVoid ); + DALI_TEST_CHECK( signal.Empty() ); + + END_TEST; + +} +int UtcDaliSignalDisconnectN02(void) +{ + TestApplication app; // Create core for debug logging + + // 1. Disconnect using a null connection tracker + TestSignals::VoidRetNoParamSignal signal; + TestSlotHandler handler; + + signal.Connect( &handler , &TestSlotHandler::VoidSlotVoid ); + DALI_TEST_CHECK( !signal.Empty() ); + + try + { + TestSlotHandler* nullHandler( NULL ); + signal.Disconnect( nullHandler , &TestSlotHandler::VoidSlotVoid ); + } + catch(Dali::DaliException& e) + { + // Tests that a negative test of an assertion succeeds + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_CHECK( !signal.Empty() ); + } + END_TEST; +} + +int UtcDaliSignalDisconnectP03(void) +{ + TestApplication app; // Create core for debug logging + + // test slot delegate: Disconnect( SlotDelegate& delegate, void (X::*func)( Arg0 arg0 ) ) + TestSignals::VoidRetNoParamSignal signal; + TestSlotDelegateHandler handler; + signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + signal.Disconnect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid ); + DALI_TEST_CHECK( signal.Empty() ); + + END_TEST; +} + +int UtcDaliSignalDisconnectN03(void) +{ + TestApplication app; // Create core for debug logging + + // try to disconnect from the wrong signal + TestSignals::VoidRetNoParamSignal signal; + TestSlotDelegateHandler handler; + signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid ); + + // use different signal + signal.Disconnect( handler.mSlotDelegate , &TestSlotDelegateHandler::AlternativeVoidSlotVoid ); + + DALI_TEST_CHECK( !signal.Empty() ); + + END_TEST; + +} + +/******************************************* + * + * End of Utc test cases for the individual API's of Signals + * The following testing Signals functionality as a whole + * + * + */ + +int UtcDaliSignalEmptyCheckSlotDestruction(void) +{ + // Test that signal disconnect works when slot is destroyed (goes out of scope) + { + TestSignals::VoidRetNoParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::VoidSlotVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + signal.Emit(); + } + + { + TestSignals::VoidRet1ValueParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::VoidSlotIntValue ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + signal.Emit( 10 ); + } + + { + TestSignals::VoidRet1RefParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::VoidSlotIntRef ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + int temp( 5 ); + signal.Emit( temp ); + } + + { + TestSignals::VoidRet2ValueParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::VoidSlotIntValueIntValue ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + signal.Emit( 1, 2 ); + } + + { + TestSignals::BoolRet1ValueParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::BoolSlotFloatValue ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + bool blah = signal.Emit( 1.0f ); + DALI_TEST_CHECK( ! blah ); + } + + { + TestSignals::BoolRet2ValueParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::BoolSlotFloatValueIntValue ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + bool blah = signal.Emit( 1.0f, 2 ); + DALI_TEST_CHECK( ! blah ); + } + + { + TestSignals::IntRet2ValueParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::IntSlotFloatValueIntValue ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + int blah = signal.Emit( 10.0f, 100 ); + DALI_TEST_CHECK( 0 == blah ); + } + + { + TestSignals::FloatRet0ParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotHandler handler; + signal.Connect( &handler, &TestSlotHandler::FloatSlotVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + float blah = signal.Emit(); + DALI_TEST_CHECK( 0.0f == blah ); + } + + { + TestSignals::FloatRet2ValueParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotHandler handler; + signal.Connect(&handler, &TestSlotHandler::FloatSlotFloatValueFloatValue); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + float blah = signal.Emit( 3.0f, 4.0f ); + DALI_TEST_CHECK( 0.0f == blah ); + } + END_TEST; +} + +// Positive test case for a method +int UtcDaliSignalConnectAndEmit01P(void) +{ + // Test basic signal emission for each slot type + + TestSignals signals; + + { + TestSlotHandler handlers; + signals.SignalVoidNone().Connect(&handlers, &TestSlotHandler::VoidSlotVoid); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.EmitVoidSignalVoid(); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + + // Test double emission + handlers.mHandled = false; + signals.EmitVoidSignalVoid(); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotHandler handlers; + signals.SignalVoid1Ref().Connect(&handlers, &TestSlotHandler::VoidSlotIntRef); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + int x = 7; + signals.EmitVoidSignalIntRef(x); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 7, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotHandler handlers; + signals.SignalVoid1Value().Connect(&handlers, &TestSlotHandler::VoidSlotIntValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.EmitVoidSignal1IntValue(5); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 5, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotHandler handlers; + signals.SignalVoid2Value().Connect(&handlers, &TestSlotHandler::VoidSlotIntValueIntValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.EmitVoidSignal2IntValue(6, 7); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 6, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam2, 7, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotHandler handlers; + signals.SignalBool1Value().Connect(&handlers, &TestSlotHandler::BoolSlotFloatValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + + handlers.mBoolReturn = true; + DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(5.0f), true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION ); + + // repeat with opposite return value + handlers.mBoolReturn = false; + handlers.mHandled = false; + DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(6.0f), false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 6.0f, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotHandler handlers; + signals.SignalBool2Value().Connect(&handlers, &TestSlotHandler::BoolSlotFloatValueIntValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mBoolReturn = true; + DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValueIntValue(5.0f, 10), true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam2, 10, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotHandler handlers; + signals.SignalInt2Value().Connect(&handlers, &TestSlotHandler::IntSlotFloatValueIntValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mIntReturn = 27; + int x = signals.EmitIntSignalFloatValueIntValue(33.5f, 5); + DALI_TEST_EQUALS( x, 27, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 33.5f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam2, 5, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotHandler handlers; + signals.SignalFloat0().Connect(&handlers, &TestSlotHandler::FloatSlotVoid); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mFloatReturn = 27.0f; + float f = signals.EmitFloat0Signal(); + DALI_TEST_EQUALS( f, 27.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotHandler handlers; + signals.SignalFloat2Value().Connect(&handlers, &TestSlotHandler::FloatSlotFloatValueFloatValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mFloatReturn = 27.0f; + float f = signals.EmitFloat2VSignal(5, 33.0f); + DALI_TEST_EQUALS( f, 27.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 33.0f, 0.001f, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotHandler handlers; + signals.VoidSignalFloatValue3().Connect(&handlers, &TestSlotHandler::VoidSlotFloatValue3); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.EmitVoidSignalFloatValue3(5, 33.0f, 100.0f); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 33.0f, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam3, 100.0f, 0.001f, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotHandler handlers; + signals.SignalFloat3Value().Connect(&handlers, &TestSlotHandler::FloatSlotFloatValue3); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mFloatReturn = 27.0f; + float returnValue = signals.EmitFloat3VSignal(5, 33.0f, 100.0f); + DALI_TEST_EQUALS( returnValue, 27.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 33.0f, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam3, 100.0f, 0.001f, TEST_LOCATION ); + } + signals.CheckNoConnections(); + END_TEST; +} + +int UtcDaliSignalConnectAndEmit02P(void) +{ + // testing connection of static functions + TestSignals signals; + StaticFunctionHandlers handlers; + + // void ( void ) + signals.SignalVoidNone().Connect( &StaticFunctionHandlers::VoidSlotVoid ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION ); + signals.EmitVoidSignalVoid(); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION ); + + + // void ( p1 ) + handlers.Reset(); + signals.SignalVoid1Value().Connect( &StaticFunctionHandlers::VoidSlot1Param ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION ); + signals.EmitVoidSignal1IntValue( 1 ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION ); + + // void ( p1, p2 ) + handlers.Reset(); + signals.SignalVoid2Value().Connect( &StaticFunctionHandlers::VoidSlot2Param ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION ); + signals.EmitVoidSignal2IntValue( 1, 2 ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION ); + + + // void ( p1, p2, p3 ) + handlers.Reset(); + signals.SignalVoid3Value().Connect( &StaticFunctionHandlers::VoidSlot3Param ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION ); + signals.EmitVoidSignal3IntValue( 1, 2, 3 ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION ); + + // ret ( ) + handlers.Reset(); + signals.SignalFloat0().Connect( &StaticFunctionHandlers::RetSlot0Param ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION ); + signals.EmitFloat0Signal(); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION ); + + // ret ( p1 ) + handlers.Reset(); + signals.SignalFloat1Value().Connect( &StaticFunctionHandlers::RetSlot1Param ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION ); + signals.EmitFloat1VSignal( 1.f ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION ); + + // ret ( p1, p2 ) + handlers.Reset(); + signals.SignalFloat2Value().Connect( &StaticFunctionHandlers::RetSlot2Param ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION ); + signals.EmitFloat2VSignal( 1.f, 2.f ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION ); + + + // ret ( p1, p2, p3 ) + handlers.Reset(); + signals.SignalFloat3Value().Connect( &StaticFunctionHandlers::RetSlot3Param ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION ); + signals.EmitFloat3VSignal( 1.f, 2.f, 3.f ); + DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION ); + + END_TEST; + +} + + +int UtcDaliSignalDisconnect(void) +{ + // Test that callbacks don't occur if a signal is disconnected before emission + + TestSignals signals; + + { + TestSlotHandler handlers; + signals.SignalVoidNone().Connect(&handlers, &TestSlotHandler::VoidSlotVoid); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.SignalVoidNone().Disconnect(&handlers, &TestSlotHandler::VoidSlotVoid); + signals.EmitVoidSignalVoid(); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + signals.SignalVoid1Ref().Connect(&handlers, &TestSlotHandler::VoidSlotIntRef); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + int r = 7; + handlers.mIntReturn = 5; + signals.SignalVoid1Ref().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntRef); + signals.EmitVoidSignalIntRef(r); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( r, 7, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + signals.SignalVoid1Value().Connect(&handlers, &TestSlotHandler::VoidSlotIntValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.SignalVoid1Value().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntValue); + signals.EmitVoidSignal1IntValue(5); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + signals.SignalVoid2Value().Connect(&handlers, &TestSlotHandler::VoidSlotIntValueIntValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.SignalVoid2Value().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntValueIntValue); + signals.EmitVoidSignal2IntValue(5, 10); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam2, 0, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + signals.SignalBool1Value().Connect(&handlers, &TestSlotHandler::BoolSlotFloatValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mBoolReturn = true; + signals.SignalBool1Value().Disconnect(&handlers, &TestSlotHandler::BoolSlotFloatValue); + DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(5.0f), false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + signals.SignalBool2Value().Connect(&handlers, &TestSlotHandler::BoolSlotFloatValueIntValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mBoolReturn = true; + signals.SignalBool2Value().Disconnect(&handlers, &TestSlotHandler::BoolSlotFloatValueIntValue); + DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValueIntValue(5.0f, 10), false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam2, 0, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + signals.SignalInt2Value().Connect(&handlers, &TestSlotHandler::IntSlotFloatValueIntValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mIntReturn = 27; + signals.SignalInt2Value().Disconnect(&handlers, &TestSlotHandler::IntSlotFloatValueIntValue); + signals.EmitIntSignalFloatValueIntValue(5, 33.0f); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + signals.SignalFloat0().Connect(&handlers, &TestSlotHandler::FloatSlotVoid); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mFloatReturn = 27.0f; + signals.SignalFloat0().Disconnect(&handlers, &TestSlotHandler::FloatSlotVoid); + signals.EmitFloat0Signal(); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + signals.SignalFloat2Value().Connect(&handlers, &TestSlotHandler::FloatSlotFloatValueFloatValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mFloatReturn = 27.0f; + signals.SignalFloat2Value().Disconnect(&handlers, &TestSlotHandler::FloatSlotFloatValueFloatValue); + signals.EmitFloat2VSignal(5, 33.0f); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliSignalDisconnect2(void) +{ + // Test that nothing happens when attempting to disconnect an unconnected slot + + TestSignals signals; + { + TestSlotHandler handlers; + signals.SignalVoidNone().Disconnect(&handlers, &TestSlotHandler::VoidSlotVoid); + signals.EmitVoidSignalVoid(); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + int r = 7; + signals.SignalVoid1Ref().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntRef); + signals.EmitVoidSignalIntRef(r); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( r, 7, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + signals.SignalVoid1Value().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntValue); + signals.EmitVoidSignal1IntValue(5); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + signals.SignalVoid2Value().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntValueIntValue); + signals.EmitVoidSignal2IntValue(5, 10); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam2, 0, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + handlers.mBoolReturn = true; + signals.SignalBool1Value().Disconnect(&handlers, &TestSlotHandler::BoolSlotFloatValue); + DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(5.0f), false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + handlers.mBoolReturn = true; + signals.SignalBool2Value().Disconnect(&handlers, &TestSlotHandler::BoolSlotFloatValueIntValue); + DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValueIntValue(5.0f, 10), false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam2, 0, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + handlers.mIntReturn = 27; + signals.SignalInt2Value().Disconnect(&handlers, &TestSlotHandler::IntSlotFloatValueIntValue); + signals.EmitIntSignalFloatValueIntValue(5, 33.0f); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + handlers.mFloatReturn = 27.0f; + signals.SignalFloat2Value().Disconnect(&handlers, &TestSlotHandler::FloatSlotFloatValueFloatValue); + signals.EmitFloat2VSignal(5, 33.0f); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + handlers.mFloatReturn = 27.0f; + signals.SignalFloat0().Disconnect(&handlers, &TestSlotHandler::FloatSlotVoid); + signals.EmitFloat0Signal(); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliSignalDisconnect3(void) +{ + // Test that callbacks stop after a signal is disconnected + + TestSignals signals; + + { + TestSlotHandler handlers; + signals.SignalVoidNone().Connect(&handlers, &TestSlotHandler::VoidSlotVoid); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + + // Emit first + signals.EmitVoidSignalVoid(); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + + // Disconnect and emit again + handlers.mHandled = false; + signals.SignalVoidNone().Disconnect(&handlers, &TestSlotHandler::VoidSlotVoid); + signals.EmitVoidSignalVoid(); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + } + + { + TestSlotHandler handlers; + signals.SignalVoid1Ref().Connect(&handlers, &TestSlotHandler::VoidSlotIntRef); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + int r = 7; + + // Emit first + signals.EmitVoidSignalIntRef(r); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 7, TEST_LOCATION ); + + // Disconnect and emit again + handlers.mHandled = false; + handlers.mIntParam1 = 0; + signals.SignalVoid1Ref().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntRef); + signals.EmitVoidSignalIntRef(r); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( r, 7, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliSignalCustomConnectionTracker(void) +{ + // Test slot destruction + { + TestSignals::VoidRetNoParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestBasicConnectionTrackerInterface customTracker; + signal.Connect( &customTracker, &TestBasicConnectionTrackerInterface::VoidSlotVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + signal.Emit(); + } + + TestBasicConnectionTrackerInterface customTracker2; + + // Test signal emission & destruction + { + TestSignals::VoidRetNoParamSignal signal; + DALI_TEST_CHECK( signal.Empty() ); + DALI_TEST_EQUALS( 0u, customTracker2.GetConnectionCount(), TEST_LOCATION ); + + signal.Connect( &customTracker2, &TestBasicConnectionTrackerInterface::VoidSlotVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + DALI_TEST_EQUALS( 1u, customTracker2.GetConnectionCount(), TEST_LOCATION ); + + DALI_TEST_EQUALS( customTracker2.mCallbackHandled, false, TEST_LOCATION ); + signal.Emit(); + DALI_TEST_EQUALS( customTracker2.mCallbackHandled, true, TEST_LOCATION ); + } + DALI_TEST_EQUALS( 0u, customTracker2.GetConnectionCount(), TEST_LOCATION ); + + // Test for removing a null callback + { + TestBasicConnectionTrackerInterface customTracker3; + + TestSignals::VoidRetNoParamSignal signal; + DALI_TEST_CHECK( signal.Empty() ); + DALI_TEST_EQUALS( 0u, customTracker3.GetConnectionCount(), TEST_LOCATION ); + + signal.Connect( &customTracker3, &TestBasicConnectionTrackerInterface::VoidSlotVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + DALI_TEST_EQUALS( 1u, customTracker3.GetConnectionCount(), TEST_LOCATION ); + try + { + // should assert + customTracker3.RemoveNullCallback(); + tet_result( TET_FAIL ); + } + catch (Dali::DaliException& e) + { + tet_result( TET_PASS ); + } + } + + END_TEST; +} + +int UtcDaliSignalMultipleConnections(void) +{ + // Test that multiple callbacks can be connected to the same signal + + TestSignals signals; + + { + TestSlotHandler handler1; + signals.SignalVoidNone().Connect( &handler1, &TestSlotHandler::VoidSlotVoid ); + DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION ); + + TestSlotHandler handler2; + signals.SignalVoidNone().Connect( &handler2, &TestSlotHandler::VoidSlotVoid ); + DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION ); + + signals.EmitVoidSignalVoid(); + DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mHandled, true, TEST_LOCATION ); + + // Remove first connection and repeat + handler1.Reset(); + handler2.Reset(); + signals.SignalVoidNone().Disconnect( &handler1, &TestSlotHandler::VoidSlotVoid ); + + signals.EmitVoidSignalVoid(); + DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mHandled, true, TEST_LOCATION ); + } + + { + TestSlotHandler handler1; + signals.SignalVoid1Ref().Connect( &handler1, &TestSlotHandler::VoidSlotIntRef ); + DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION ); + + TestSlotHandler handler2; + signals.SignalVoid1Ref().Connect( &handler2, &TestSlotHandler::VoidSlotIntRef ); + DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION ); + + int x = 7; + signals.EmitVoidSignalIntRef(x); + DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler1.mIntParam1, 7, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mIntParam1, 7, TEST_LOCATION ); + + // Remove second connection and repeat + handler1.Reset(); + handler2.Reset(); + x = 8; + signals.SignalVoid1Ref().Disconnect( &handler2, &TestSlotHandler::VoidSlotIntRef ); + + signals.EmitVoidSignalIntRef(x); + DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler1.mIntParam1, 8, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mIntParam1, 0, TEST_LOCATION ); + } + + { + TestSlotHandler handler1; + signals.SignalVoid1Value().Connect( &handler1, &TestSlotHandler::VoidSlotIntValue ); + DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION ); + + TestSlotHandler handler2; + signals.SignalVoid1Value().Connect( &handler2, &TestSlotHandler::VoidSlotIntValue ); + DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION ); + + TestSlotHandler handler3; + signals.SignalVoid1Value().Connect( &handler3, &TestSlotHandler::VoidSlotIntValue ); + DALI_TEST_EQUALS( handler3.mHandled, false, TEST_LOCATION ); + + signals.EmitVoidSignal1IntValue( 5 ); + DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler1.mIntParam1, 5, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mIntParam1, 5, TEST_LOCATION ); + DALI_TEST_EQUALS( handler3.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler3.mIntParam1, 5, TEST_LOCATION ); + + // Remove middle connection and repeat + handler1.Reset(); + handler2.Reset(); + handler3.Reset(); + signals.SignalVoid1Value().Disconnect( &handler2, &TestSlotHandler::VoidSlotIntValue ); + + signals.EmitVoidSignal1IntValue( 6 ); + DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler1.mIntParam1, 6, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mIntParam1, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( handler3.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler3.mIntParam1, 6, TEST_LOCATION ); + } + + // Test that multiple callbacks are disconnected when a signal is destroyed + + TestSlotHandler handler4; + TestSlotHandler handler5; + TestSlotHandler handler6; + + { + TestSignals::VoidRet1ValueParamSignal tempSignal; + + DALI_TEST_EQUALS( handler4.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( handler5.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( handler6.GetConnectionCount(), 0u, TEST_LOCATION ); + + tempSignal.Connect( &handler4, &TestSlotHandler::VoidSlotIntValue ); + tempSignal.Connect( &handler5, &TestSlotHandler::VoidSlotIntValue ); + tempSignal.Connect( &handler6, &TestSlotHandler::VoidSlotIntValue ); + + DALI_TEST_EQUALS( handler4.GetConnectionCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( handler5.GetConnectionCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( handler6.GetConnectionCount(), 1u, TEST_LOCATION ); + } + // End of tempSignal lifetime + + DALI_TEST_EQUALS( handler4.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( handler5.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( handler6.GetConnectionCount(), 0u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSignalMultipleConnections2(void) +{ + TestSignals signals; + + // Test that connecting the same callback twice is a NOOP + { + TestSlotHandler handler1; + + // Note the double connection is intentional + signals.SignalVoid1Value().Connect( &handler1, &TestSlotHandler::VoidSlotIntValue ); + signals.SignalVoid1Value().Connect( &handler1, &TestSlotHandler::VoidSlotIntValue ); + DALI_TEST_EQUALS( handler1.mHandledCount, 0, TEST_LOCATION ); + + signals.EmitVoidSignal1IntValue( 6 ); + DALI_TEST_EQUALS( handler1.mHandledCount, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( handler1.mIntParam1, 6, TEST_LOCATION ); + + // Calling Disconnect once should be enough + signals.SignalVoid1Value().Disconnect( &handler1, &TestSlotHandler::VoidSlotIntValue ); + DALI_TEST_CHECK( signals.SignalVoid1Value().Empty() ); + handler1.mIntParam1 = 0; + + signals.EmitVoidSignal1IntValue( 7 ); + DALI_TEST_EQUALS( handler1.mHandledCount, 1/*not incremented since last check*/, TEST_LOCATION ); + DALI_TEST_EQUALS( handler1.mIntParam1, 0, TEST_LOCATION ); + } + + // Test automatic disconnect after multiple Connect() calls + { + TestSlotHandler handler2; + signals.SignalVoid1Value().Connect( &handler2, &TestSlotHandler::VoidSlotIntValue ); + signals.SignalVoid1Value().Connect( &handler2, &TestSlotHandler::VoidSlotIntValue ); + + TestSlotHandler handler3; + signals.SignalBool1Value().Connect( &handler3, &TestSlotHandler::BoolSlotFloatValue ); + signals.SignalBool1Value().Connect( &handler3, &TestSlotHandler::BoolSlotFloatValue ); + + DALI_TEST_EQUALS( handler2.mHandledCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( handler3.mHandledCount, 0, TEST_LOCATION ); + DALI_TEST_CHECK( ! signals.SignalVoid1Value().Empty() ); + DALI_TEST_CHECK( ! signals.SignalBool1Value().Empty() ); + } + DALI_TEST_CHECK( signals.SignalVoid1Value().Empty() ); + DALI_TEST_CHECK( signals.SignalBool1Value().Empty() ); + + // Should be NOOP + signals.EmitVoidSignal1IntValue( 1 ); + signals.EmitBoolSignalFloatValue( 1.0f ); + + // Test that connecting the same callback 10 times is a NOOP + TestSlotHandler handler4; + DALI_TEST_EQUALS( handler4.mHandledCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( handler4.mFloatParam1, 0.0f, TEST_LOCATION ); + + signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue ); + signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue ); + signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue ); + signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue ); + signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue ); + signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue ); + signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue ); + signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue ); + signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue ); + signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue ); + + signals.EmitBoolSignalFloatValue( 2.0f ); + DALI_TEST_EQUALS( handler4.mHandledCount, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( handler4.mFloatParam1, 2.0f, TEST_LOCATION ); + + // Calling Disconnect once should be enough + signals.SignalBool1Value().Disconnect( &handler4, &TestSlotHandler::BoolSlotFloatValue ); + DALI_TEST_CHECK( signals.SignalBool1Value().Empty() ); + + signals.EmitBoolSignalFloatValue( 3.0f ); + DALI_TEST_EQUALS( handler4.mHandledCount, 1/*not incremented since last check*/, TEST_LOCATION ); + DALI_TEST_EQUALS( handler4.mFloatParam1, 2.0f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSignalMultipleConnections3(void) +{ + TestSignals signals; + + // Test connecting two difference callbacks for the same ConnectionTracker + + TestSlotHandler handler1; + + { + TestSignals::VoidRet1ValueParamSignal tempSignal; + + DALI_TEST_EQUALS( handler1.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( handler1.mHandledCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( handler1.mIntParam1, 0, TEST_LOCATION ); + + // Note that the duplicate connection is deliberate + tempSignal.Connect( &handler1, &TestSlotHandler::VoidSlotIntValue ); + tempSignal.Connect( &handler1, &TestSlotHandler::VoidDuplicateSlotIntValue ); + + DALI_TEST_EQUALS( handler1.GetConnectionCount(), 2u, TEST_LOCATION ); + DALI_TEST_EQUALS( handler1.mHandledCount, 0, TEST_LOCATION ); + + tempSignal.Emit( 10 ); + + DALI_TEST_EQUALS( handler1.mHandledCount, 2, TEST_LOCATION ); + DALI_TEST_EQUALS( handler1.mIntParam1, 10, TEST_LOCATION ); + DALI_TEST_EQUALS( handler1.mIntParam2, 10, TEST_LOCATION ); + } + // End of tempSignal lifetime + + DALI_TEST_EQUALS( handler1.GetConnectionCount(), 0u, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliSignalDisconnectStatic(void) +{ + // void Func() + + { + TestSignals::VoidRetNoParamSignal signal; + DALI_TEST_CHECK( signal.Empty() ); + + signal.Connect( StaticVoidCallbackVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + + wasStaticVoidCallbackVoidCalled = false; + signal.Emit(); + DALI_TEST_EQUALS( wasStaticVoidCallbackVoidCalled, true, TEST_LOCATION ); + + signal.Disconnect( StaticVoidCallbackVoid ); + DALI_TEST_CHECK( signal.Empty() ); + + wasStaticVoidCallbackVoidCalled = false; + signal.Emit(); + DALI_TEST_EQUALS( wasStaticVoidCallbackVoidCalled, false, TEST_LOCATION ); + } + + // float Func() + + { + TestSignals::FloatRet0ParamSignal signal; + DALI_TEST_CHECK( signal.Empty() ); + + signal.Connect( StaticFloatCallbackVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + + wasStaticFloatCallbackVoidCalled = false; + float result = signal.Emit(); + DALI_TEST_EQUALS( wasStaticFloatCallbackVoidCalled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( result, 7.0f, TEST_LOCATION ); + + signal.Disconnect( StaticFloatCallbackVoid ); + DALI_TEST_CHECK( signal.Empty() ); + + wasStaticFloatCallbackVoidCalled = false; + result = signal.Emit(); + DALI_TEST_EQUALS( wasStaticFloatCallbackVoidCalled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( result, 0.0f, TEST_LOCATION ); + } + + // void Func( int ) + + { + TestSignals::VoidRet1ValueParamSignal signal; + DALI_TEST_CHECK( signal.Empty() ); + + signal.Connect( StaticVoidCallbackIntValue ); + DALI_TEST_CHECK( ! signal.Empty() ); + + wasStaticVoidCallbackIntValueCalled = false; + staticIntValue = 0; + signal.Emit( 10 ); + DALI_TEST_EQUALS( wasStaticVoidCallbackIntValueCalled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( staticIntValue, 10, TEST_LOCATION ); + + signal.Disconnect( StaticVoidCallbackIntValue ); + DALI_TEST_CHECK( signal.Empty() ); + + wasStaticVoidCallbackIntValueCalled = false; + staticIntValue = 0; + signal.Emit( 11 ); + DALI_TEST_EQUALS( wasStaticVoidCallbackIntValueCalled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( staticIntValue, 0, TEST_LOCATION ); + } + + // float Func( float, float ) + + { + TestSignals::FloatRet2ValueParamSignal signal; + DALI_TEST_CHECK( signal.Empty() ); + + signal.Connect( StaticFloatCallbackFloatValueFloatValue ); + DALI_TEST_CHECK( ! signal.Empty() ); + + wasStaticFloatCallbackFloatValueFloatValueCalled = false; + staticFloatValue1 = 0.0f; + staticFloatValue2 = 0.0f; + float result = signal.Emit( 5.0f, 6.0f ); + DALI_TEST_EQUALS( wasStaticFloatCallbackFloatValueFloatValueCalled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( staticFloatValue1, 5.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( staticFloatValue2, 6.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( result, 5.0f+6.0f, TEST_LOCATION ); + + signal.Disconnect( StaticFloatCallbackFloatValueFloatValue ); + DALI_TEST_CHECK( signal.Empty() ); + + wasStaticFloatCallbackFloatValueFloatValueCalled = false; + staticFloatValue1 = 0.0f; + staticFloatValue2 = 0.0f; + result = signal.Emit( 7.0f, 8.0f ); + DALI_TEST_EQUALS( wasStaticFloatCallbackFloatValueFloatValueCalled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( staticFloatValue1, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( staticFloatValue2, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( result, 0.0f, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliSignalDisconnectDuringCallback(void) +{ + // Test disconnection during each callback + + TestSignals::VoidRetNoParamSignal signal; + DALI_TEST_CHECK( signal.Empty() ); + + TestSlotDisconnector handler1; + handler1.VoidConnectVoid( signal ); + DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION ); + DALI_TEST_CHECK( ! signal.Empty() ); + + signal.Emit(); + DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION ); + DALI_TEST_CHECK( signal.Empty() ); + + // Repeat with 2 callbacks + + handler1.mHandled = false; + + TestSlotDisconnector handler2; + handler1.VoidConnectVoid( signal ); + handler2.VoidConnectVoid( signal ); + DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION ); + DALI_TEST_CHECK( ! signal.Empty() ); + + signal.Emit(); + DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mHandled, true, TEST_LOCATION ); + DALI_TEST_CHECK( signal.Empty() ); + + // Repeat with no callbacks + + handler1.mHandled = false; + handler2.mHandled = false; + + signal.Emit(); + DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION ); + + // Repeat with 3 callbacks + + TestSlotDisconnector handler3; + handler1.VoidConnectVoid( signal ); + handler2.VoidConnectVoid( signal ); + handler3.VoidConnectVoid( signal ); + DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler3.mHandled, false, TEST_LOCATION ); + DALI_TEST_CHECK( ! signal.Empty() ); + + signal.Emit(); + DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler3.mHandled, true, TEST_LOCATION ); + DALI_TEST_CHECK( signal.Empty() ); + + // Repeat with no callbacks + + handler1.mHandled = false; + handler2.mHandled = false; + handler3.mHandled = false; + + signal.Emit(); + DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler3.mHandled, false, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSignalDisconnectDuringCallback2(void) +{ + // Test disconnection of some (but not all) callbacks during sigmal emission + + TestSignals::VoidRetNoParamSignal signal; + DALI_TEST_CHECK( signal.Empty() ); + + TestSlotMultiDisconnector handler; + handler.ConnectAll( signal ); + DALI_TEST_EQUALS( handler.mSlotHandled[0], false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[1], false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[2], false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[3], false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[4], false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[5], false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[6], false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[7], false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[8], false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[9], false, TEST_LOCATION ); + DALI_TEST_CHECK( ! signal.Empty() ); + + signal.Emit(); + + // Slots 5, 7, & 9 should be disconnected before being called + DALI_TEST_EQUALS( handler.mSlotHandled[0], true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[1], true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[2], true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[3], true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[4], true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[5], false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[6], true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[7], false, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[8], true, TEST_LOCATION ); + DALI_TEST_EQUALS( handler.mSlotHandled[9], false, TEST_LOCATION ); + DALI_TEST_CHECK( ! signal.Empty() ); + + // Odd slots are disconnected + DALI_TEST_EQUALS( handler.GetConnectionCount(), 5u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSignalEmitDuringCallback(void) +{ + TestApplication app; // Create core for debug logging + + // for coverage purposes we test the emit guard for each signal type (0,1,2,3 params) void / return value + { + TestSignals::VoidRetNoParamSignal signal; + DALI_TEST_CHECK( signal.Empty() ); + + TestEmitDuringCallback handler1; + handler1.VoidConnectVoid( signal ); + + // Test that this does not result in an infinite loop! + signal.Emit(); + } + { + TestSignals::FloatRet0ParamSignal signal; + + DALI_TEST_CHECK( signal.Empty() ); + + TestEmitDuringCallback handler1; + handler1.FloatRet0ParamConnect( signal ); + + // Test that this does not result in an infinite loop! + signal.Emit(); + } + { + TestSignals::FloatRet1ParamSignal signal; + + DALI_TEST_CHECK( signal.Empty() ); + + TestEmitDuringCallback handler1; + handler1.FloatRet1ParamConnect( signal ); + + // Test that this does not result in an infinite loop! + signal.Emit( 1.f ); + } + { + TestSignals::FloatRet2ValueParamSignal signal; + + DALI_TEST_CHECK( signal.Empty() ); + + TestEmitDuringCallback handler1; + handler1.FloatRet2ParamConnect( signal ); + + // Test that this does not result in an infinite loop! + signal.Emit( 1.f, 1.f ); + } + { + TestSignals::FloatRet3ValueParamSignal signal; + + DALI_TEST_CHECK( signal.Empty() ); + + TestEmitDuringCallback handler1; + handler1.FloatRet3ParamConnect( signal ); + + // Test that this does not result in an infinite loop! + signal.Emit( 1.f,1.f,1.f ); + } + END_TEST; +} + +int UtcDaliSignalDeleteDuringEmit(void) +{ + // testing a signal deletion during an emit + // need to dynamically allocate the signal for this to work + + TestApplication app; // Create core for debug logging + + TestSignals::VoidRetNoParamSignal* signal = new TestSignals::VoidRetNoParamSignal; + + TestEmitDuringCallback handler1; + handler1.DeleteDuringEmitConnect( *signal ); + + // should just log an error + signal->Emit(); + + tet_result( TET_PASS ); + + END_TEST; +} + +int UtcDaliSignalTestApp01(void) +{ + // Test 1 signal connected to 1 Slot. + // Signal dies first. + + TestButton* button = new TestButton(1); + TestApp app; + button->DownSignal().Connect(&app,&TestApp::OnButtonPress); + + // check we have both the button, and the app have 1 connection + DALI_TEST_EQUALS( app.GetConnectionCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( button->DownSignal().GetConnectionCount(), 1u, TEST_LOCATION ); + + delete button; // should automatically destroy the connection + + // check we have a 0 connections + DALI_TEST_EQUALS( app.GetConnectionCount(), 0u, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliSignalTestApp02(void) +{ + // Test 1 signal connected to 1 Slot. + // Slot owning object dies first. + + TestButton button(1); + TestApp *app = new TestApp; + button.DownSignal().Connect( app, &TestApp::OnButtonPress); + + // check we have a 1 connection + DALI_TEST_EQUALS( app->GetConnectionCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( button.DownSignal().GetConnectionCount(), 1u, TEST_LOCATION ); + + delete app; // should automatically destroy the connection + + // check we have a 0 connections + DALI_TEST_EQUALS( button.DownSignal().GetConnectionCount(), 0u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSignalTestApp03(void) +{ + // Test 1 Signal connect to 2 slots + // 1 of the slot owners dies. Then the second slot owner dies + + TestButton button(1); + TestApp *app1 = new TestApp; + TestApp *app2 = new TestApp; + + button.DownSignal().Connect( app1, &TestApp::OnButtonPress); + button.DownSignal().Connect( app2, &TestApp::OnButtonPress); + + // check we have a 2 connections to the signal + DALI_TEST_EQUALS( button.DownSignal().GetConnectionCount(), 2u, TEST_LOCATION ); + + // kill the first slot + delete app1; // should automatically destroy the connection + + // check we have 1 connection left + DALI_TEST_EQUALS( button.DownSignal().GetConnectionCount(), 1u, TEST_LOCATION ); + + button.Press(); // emit the signal (to ensure it doesn't seg fault) + + // kill the second slot + delete app2; // should automatically destroy the connection + + // check we have 1 connection left + DALI_TEST_EQUALS( button.DownSignal().GetConnectionCount(), 0u, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliSignalTestApp04(void) +{ + // Test 1 Signal connected to 2 slots (with different owners) + // The Signal dies, check the 2 slots disconnect automatically + + TestButton* button = new TestButton(1); + TestApp app1; + TestApp app2; + + button->DownSignal().Connect(&app1,&TestApp::OnButtonPress); + button->DownSignal().Connect(&app2,&TestApp::OnButtonPress); + + // check the connection counts + DALI_TEST_EQUALS( app1.GetConnectionCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( app2.GetConnectionCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( button->DownSignal().GetConnectionCount(), 2u, TEST_LOCATION ); + + delete button; // should automatically destroy the connection + + // check both slot owners have zero connections + DALI_TEST_EQUALS( app1.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( app2.GetConnectionCount(), 0u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSignalTestApp05(void) +{ + // Test 2 Signals (with different owners) connected to 1 slots + // 1 Signal dies, check that the remaining connection is valid + + TestButton* button1 = new TestButton(1); // use for signal 1 + TestButton* button2 = new TestButton(2); // use for signal 2 + + TestApp app; + + button1->DownSignal().Connect(&app,&TestApp::OnButtonPress); + button2->DownSignal().Connect(&app,&TestApp::OnButtonPress); + + // check the connection counts + DALI_TEST_EQUALS( app.GetConnectionCount(), 2u, TEST_LOCATION ); + DALI_TEST_EQUALS( button1->DownSignal().GetConnectionCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( button2->DownSignal().GetConnectionCount(), 1u, TEST_LOCATION ); + + // make sure both signals emit ok + button2->Press(); + DALI_TEST_EQUALS( app.GetButtonPressedId() , 2 , TEST_LOCATION ); + + button1->Press(); + DALI_TEST_EQUALS( app.GetButtonPressedId() , 1 , TEST_LOCATION ); + + delete button1; // should automatically destroy 1 connection + + // check both slot owners have zero connections + DALI_TEST_EQUALS( app.GetConnectionCount(), 1u, TEST_LOCATION ); + + // check remaining connection still works + button2->Press(); + DALI_TEST_EQUALS( app.GetButtonPressedId() , 2 , TEST_LOCATION ); + + // kill the last signal + delete button2; + DALI_TEST_EQUALS( app.GetConnectionCount(), 0u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSignalTestApp06(void) +{ + Signal< bool () > boolSignal; + TestApp app; + bool result(false); + + // connect a slot which will return false + boolSignal.Connect( &app, &TestApp::BoolReturnTestFalse); + result = boolSignal.Emit(); + DALI_TEST_EQUALS( result, false, TEST_LOCATION ); + + // disconnect last slot, and connect a slot which returns true + boolSignal.Disconnect( &app, &TestApp::BoolReturnTestFalse); + boolSignal.Connect( &app, &TestApp::BoolReturnTestTrue); + result = boolSignal.Emit(); + DALI_TEST_EQUALS( result, true, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSlotDelegateConnection(void) +{ + TestSignals signals; + + { + TestSlotDelegateHandler handlers; + signals.SignalVoidNone().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.EmitVoidSignalVoid(); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + + // Test double emission + handlers.mHandled = false; + signals.EmitVoidSignalVoid(); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotDelegateHandler handlers; + signals.SignalVoid1Ref().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntRef ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + int x = 7; + signals.EmitVoidSignalIntRef(x); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 7, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotDelegateHandler handlers; + signals.SignalVoid1Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValue ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.EmitVoidSignal1IntValue(5); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 5, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotDelegateHandler handlers; + signals.SignalVoid2Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValueIntValue ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.EmitVoidSignal2IntValue(6, 7); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 6, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam2, 7, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotDelegateHandler handlers; + signals.SignalBool1Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValue ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + + handlers.mBoolReturn = true; + DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(5.0f), true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION ); + + // repeat with opposite return value + handlers.mBoolReturn = false; + handlers.mHandled = false; + DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(6.0f), false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 6.0f, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotDelegateHandler handlers; + signals.SignalBool2Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValueIntValue ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mBoolReturn = true; + DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValueIntValue(5.0f, 10), true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam2, 10, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotDelegateHandler handlers; + signals.SignalInt2Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::IntSlotFloatValueIntValue ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mIntReturn = 27; + int x = signals.EmitIntSignalFloatValueIntValue(33.5f, 5); + DALI_TEST_EQUALS( x, 27, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 33.5f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam2, 5, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotDelegateHandler handlers; + signals.SignalFloat0().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotVoid ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mFloatReturn = 27.0f; + float f = signals.EmitFloat0Signal(); + DALI_TEST_EQUALS( f, 27.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotDelegateHandler handlers; + signals.SignalFloat2Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotFloatValueFloatValue ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mFloatReturn = 27.0f; + float f = signals.EmitFloat2VSignal(5, 33.0f); + DALI_TEST_EQUALS( f, 27.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 33.0f, 0.001f, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotDelegateHandler handlers; + signals.VoidSignalFloatValue3().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotFloatValue3 ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.EmitVoidSignalFloatValue3(5, 33.0f, 100.0f); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 33.0f, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam3, 100.0f, 0.001f, TEST_LOCATION ); + } + signals.CheckNoConnections(); + + { + TestSlotDelegateHandler handlers; + signals.SignalFloat3Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotFloatValue3 ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mFloatReturn = 27.0f; + float returnValue = signals.EmitFloat3VSignal(5, 33.0f, 100.0f); + DALI_TEST_EQUALS( returnValue, 27.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 33.0f, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam3, 100.0f, 0.001f, TEST_LOCATION ); + } + signals.CheckNoConnections(); + END_TEST; +} + +int UtcDaliSignalSlotDelegateDestruction(void) +{ + // Test that signal disconnect works when slot-delegate is destroyed (goes out of scope) + + { + TestSignals::VoidRetNoParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotDelegateHandler handler; + signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + signal.Emit(); + } + + { + TestSignals::VoidRet1ValueParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotDelegateHandler handler; + signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValue ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + signal.Emit( 10 ); + } + + { + TestSignals::VoidRet1RefParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotDelegateHandler handler; + signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntRef ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + int temp( 5 ); + signal.Emit( temp ); + } + + { + TestSignals::VoidRet2ValueParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotDelegateHandler handler; + signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValueIntValue ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + signal.Emit( 1, 2 ); + } + + { + TestSignals::BoolRet1ValueParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotDelegateHandler handler; + signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValue ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + bool blah = signal.Emit( 1.0f ); + DALI_TEST_CHECK( ! blah ); + } + + { + TestSignals::BoolRet2ValueParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotDelegateHandler handler; + signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValueIntValue ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + bool blah = signal.Emit( 1.0f, 2 ); + DALI_TEST_CHECK( ! blah ); + } + + { + TestSignals::IntRet2ValueParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotDelegateHandler handler; + signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::IntSlotFloatValueIntValue ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + int blah = signal.Emit( 10.0f, 100 ); + DALI_TEST_CHECK( 0 == blah ); + } + + { + TestSignals::FloatRet0ParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotDelegateHandler handler; + signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotVoid ); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + float blah = signal.Emit(); + DALI_TEST_CHECK( 0.0f == blah ); + } + + { + TestSignals::FloatRet2ValueParamSignal signal; + { + DALI_TEST_CHECK( signal.Empty() ); + TestSlotDelegateHandler handler; + signal.Connect(handler.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotFloatValueFloatValue); + DALI_TEST_CHECK( ! signal.Empty() ); + } + // End of slot lifetime + DALI_TEST_CHECK( signal.Empty() ); + + // Signal emission should be a NOOP + float blah = signal.Emit( 3.0f, 4.0f ); + DALI_TEST_CHECK( 0.0f == blah ); + } + END_TEST; +} + +int UtcDaliSlotHandlerDisconnect(void) +{ + // Test that callbacks don't occur if a signal is disconnected before emission + + TestSignals signals; + + { + TestSlotDelegateHandler handlers; + signals.SignalVoidNone().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.SignalVoidNone().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid); + signals.EmitVoidSignalVoid(); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + } + + { + TestSlotDelegateHandler handlers; + signals.SignalVoid1Ref().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntRef); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + int r = 7; + handlers.mIntReturn = 5; + signals.SignalVoid1Ref().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntRef); + signals.EmitVoidSignalIntRef(r); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( r, 7, TEST_LOCATION ); + } + + { + TestSlotDelegateHandler handlers; + signals.SignalVoid1Value().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.SignalVoid1Value().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValue); + signals.EmitVoidSignal1IntValue(5); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + } + + { + TestSlotDelegateHandler handlers; + signals.SignalVoid2Value().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValueIntValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + signals.SignalVoid2Value().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValueIntValue); + signals.EmitVoidSignal2IntValue(5, 10); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam2, 0, TEST_LOCATION ); + } + + { + TestSlotDelegateHandler handlers; + signals.SignalBool1Value().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mBoolReturn = true; + signals.SignalBool1Value().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValue); + DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(5.0f), false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION ); + } + + { + TestSlotDelegateHandler handlers; + signals.SignalBool2Value().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValueIntValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mBoolReturn = true; + signals.SignalBool2Value().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValueIntValue); + DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValueIntValue(5.0f, 10), false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam2, 0, TEST_LOCATION ); + } + + { + TestSlotDelegateHandler handlers; + signals.SignalInt2Value().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::IntSlotFloatValueIntValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mIntReturn = 27; + signals.SignalInt2Value().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::IntSlotFloatValueIntValue); + signals.EmitIntSignalFloatValueIntValue(5, 33.0f); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION ); + } + + { + TestSlotDelegateHandler handlers; + signals.SignalFloat0().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotVoid); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mFloatReturn = 27.0f; + signals.SignalFloat0().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotVoid); + signals.EmitFloat0Signal(); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION ); + } + + { + TestSlotDelegateHandler handlers; + signals.SignalFloat2Value().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotFloatValueFloatValue); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + handlers.mFloatReturn = 27.0f; + signals.SignalFloat2Value().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotFloatValueFloatValue); + signals.EmitFloat2VSignal(5, 33.0f); + DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, 0.001f, TEST_LOCATION ); + DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION ); + } + END_TEST; +} + + +int UtcDaliCallbackBase(void) +{ + // simple constructor for coverage + CallbackBase base; + tet_result( TET_PASS ); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-SignalTemplatesFunctors.cpp b/automated-tests/src/dali/utc-Dali-SignalTemplatesFunctors.cpp new file mode 100644 index 0000000..d66aa29 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-SignalTemplatesFunctors.cpp @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include + +using namespace Dali; + +void utc_dali_signal_templates_functors_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_signal_templates_functors_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +class TestSignals +{ +public: + + typedef Signal VoidSignalVoid; + typedef Signal VoidSignalFloat; + + typedef Signal FloatSignalVoid; + typedef Signal FloatSignalFloat; + + TestSignals() + { + } + + void CheckNoConnections() + { + DALI_TEST_EQUALS( mVoidSignalVoid.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mVoidSignalFloat.GetConnectionCount(), 0u, TEST_LOCATION ); + + DALI_TEST_EQUALS( mFloatSignalVoid.GetConnectionCount(), 0u, TEST_LOCATION ); + DALI_TEST_EQUALS( mFloatSignalFloat.GetConnectionCount(), 0u, TEST_LOCATION ); + } + + VoidSignalVoid mVoidSignalVoid; + VoidSignalFloat mVoidSignalFloat; + + FloatSignalVoid mFloatSignalVoid; + FloatSignalFloat mFloatSignalFloat; +}; + +class TestConnectionTracker : public ConnectionTracker +{ +public: + + TestConnectionTracker() + { + } +}; + +struct VoidFunctorVoid +{ + VoidFunctorVoid() + { + ++mTotalInstanceCount; + ++mCurrentInstanceCount; + } + + VoidFunctorVoid( const VoidFunctorVoid& copyMe ) + { + ++mTotalInstanceCount; + ++mCurrentInstanceCount; + } + + ~VoidFunctorVoid() + { + --mCurrentInstanceCount; + } + + void operator()() + { + ++mCallbackCount; + } + + static int mTotalInstanceCount; + static int mCurrentInstanceCount; + static int mCallbackCount; +}; + +struct VoidFunctorFloat +{ + VoidFunctorFloat( float* lastReceivedValue ) + : mLastReceivedValue( lastReceivedValue ) + { + ++mTotalInstanceCount; + ++mCurrentInstanceCount; + } + + VoidFunctorFloat( const VoidFunctorFloat& copyMe ) + : mLastReceivedValue( copyMe.mLastReceivedValue ) + { + ++mTotalInstanceCount; + ++mCurrentInstanceCount; + } + + ~VoidFunctorFloat() + { + --mCurrentInstanceCount; + } + + void operator()(float value) + { + ++mCallbackCount; + + if( mLastReceivedValue ) + { + *mLastReceivedValue = value; + } + } + + float* mLastReceivedValue; + + static int mTotalInstanceCount; + static int mCurrentInstanceCount; + static int mCallbackCount; +}; + +struct FloatFunctorVoid +{ + static float DEFAULT_RETURN_VALUE; + + FloatFunctorVoid() + { + ++mTotalInstanceCount; + ++mCurrentInstanceCount; + } + + FloatFunctorVoid( const FloatFunctorVoid& copyMe ) + { + ++mTotalInstanceCount; + ++mCurrentInstanceCount; + } + + ~FloatFunctorVoid() + { + --mCurrentInstanceCount; + } + + float operator()() + { + ++mCallbackCount; + + return DEFAULT_RETURN_VALUE; + } + + static int mTotalInstanceCount; + static int mCurrentInstanceCount; + static int mCallbackCount; +}; + +float FloatFunctorVoid::DEFAULT_RETURN_VALUE = 5.0f; + +struct FloatFunctorFloat +{ + FloatFunctorFloat() + : mLastReceivedValue() + { + ++mTotalInstanceCount; + ++mCurrentInstanceCount; + } + + FloatFunctorFloat( const FloatFunctorFloat& copyMe ) + { + ++mTotalInstanceCount; + ++mCurrentInstanceCount; + } + + ~FloatFunctorFloat() + { + --mCurrentInstanceCount; + } + + float operator()(float value) + { + ++mCallbackCount; + + return value + 1.0f; + } + + float* mLastReceivedValue; + + static int mTotalInstanceCount; + static int mCurrentInstanceCount; + static int mCallbackCount; +}; + +static void ResetFunctorCounts() +{ + VoidFunctorVoid::mTotalInstanceCount = 0; + VoidFunctorVoid::mCurrentInstanceCount = 0; + VoidFunctorVoid::mCallbackCount = 0; + + VoidFunctorFloat::mTotalInstanceCount = 0; + VoidFunctorFloat::mCurrentInstanceCount = 0; + VoidFunctorFloat::mCallbackCount = 0; + + FloatFunctorVoid::mTotalInstanceCount = 0; + FloatFunctorVoid::mCurrentInstanceCount = 0; + FloatFunctorVoid::mCallbackCount = 0; + + FloatFunctorFloat::mTotalInstanceCount = 0; + FloatFunctorFloat::mCurrentInstanceCount = 0; + FloatFunctorFloat::mCallbackCount = 0; +} + +int VoidFunctorVoid::mTotalInstanceCount = 0; +int VoidFunctorVoid::mCurrentInstanceCount = 0; +int VoidFunctorVoid::mCallbackCount = 0; + +int VoidFunctorFloat::mTotalInstanceCount = 0; +int VoidFunctorFloat::mCurrentInstanceCount = 0; +int VoidFunctorFloat::mCallbackCount = 0; + +int FloatFunctorVoid::mTotalInstanceCount = 0; +int FloatFunctorVoid::mCurrentInstanceCount = 0; +int FloatFunctorVoid::mCallbackCount = 0; + +int FloatFunctorFloat::mTotalInstanceCount = 0; +int FloatFunctorFloat::mCurrentInstanceCount = 0; +int FloatFunctorFloat::mCallbackCount = 0; + +} // anon namespace + + +int UtcDaliSignalFunctorsEmptyCheck(void) +{ + // Test that Empty() check works before & after signal connection + + ResetFunctorCounts(); + + { + TestSignals::VoidSignalVoid signal; + DALI_TEST_CHECK( signal.Empty() ); + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION ); + TestConnectionTracker tracker; + signal.Connect( &tracker, VoidFunctorVoid() ); + DALI_TEST_CHECK( ! signal.Empty() ); + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 1, TEST_LOCATION ); + } + // TestConnectionTracker should auto-disconnect + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION ); + + { + TestSignals::VoidSignalFloat signal; + DALI_TEST_CHECK( signal.Empty() ); + DALI_TEST_EQUALS( VoidFunctorFloat::mTotalInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorFloat::mCurrentInstanceCount, 0, TEST_LOCATION ); + TestConnectionTracker tracker; + signal.Connect( &tracker, VoidFunctorFloat(NULL) ); + DALI_TEST_CHECK( ! signal.Empty() ); + DALI_TEST_EQUALS( VoidFunctorFloat::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorFloat::mCurrentInstanceCount, 1, TEST_LOCATION ); + } + // TestConnectionTracker should auto-disconnect + DALI_TEST_EQUALS( VoidFunctorFloat::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorFloat::mCurrentInstanceCount, 0, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSignalFunctorsEmit(void) +{ + // Test basic signal emission for each functor type + + ResetFunctorCounts(); + + TestSignals signals; + + { + TestConnectionTracker tracker; + + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION ); + + signals.mVoidSignalVoid.Connect( &tracker, VoidFunctorVoid() ); + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 0, TEST_LOCATION ); + + signals.mVoidSignalVoid.Emit(); + DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 1, TEST_LOCATION ); + + // Test double emission + signals.mVoidSignalVoid.Emit(); + DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 2, TEST_LOCATION ); + } + // TestConnectionTracker should auto-disconnect + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 2, TEST_LOCATION ); + signals.CheckNoConnections(); + + { + TestConnectionTracker tracker; + float lastReceivedValue( 0.0f ); + + DALI_TEST_EQUALS( VoidFunctorFloat::mTotalInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorFloat::mCurrentInstanceCount, 0, TEST_LOCATION ); + + signals.mVoidSignalFloat.Connect( &tracker, VoidFunctorFloat(&lastReceivedValue) ); + DALI_TEST_EQUALS( VoidFunctorFloat::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorFloat::mCurrentInstanceCount, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorFloat::mCallbackCount, 0, TEST_LOCATION ); + + signals.mVoidSignalFloat.Emit( 3.5f ); + DALI_TEST_EQUALS( VoidFunctorFloat::mCallbackCount, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( lastReceivedValue, 3.5f, TEST_LOCATION ); + + // Test double emission + signals.mVoidSignalFloat.Emit( 7.0f ); + DALI_TEST_EQUALS( VoidFunctorFloat::mCallbackCount, 2, TEST_LOCATION ); + DALI_TEST_EQUALS( lastReceivedValue, 7.0f, TEST_LOCATION ); + } + // TestConnectionTracker should auto-disconnect + DALI_TEST_EQUALS( VoidFunctorFloat::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorFloat::mCurrentInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorFloat::mCallbackCount, 2, TEST_LOCATION ); + signals.CheckNoConnections(); + END_TEST; +} + +int UtcDaliSignalFunctorsEmitReturn(void) +{ + // Test signals with return values + + ResetFunctorCounts(); + + TestSignals signals; + + { + TestConnectionTracker tracker; + + DALI_TEST_EQUALS( FloatFunctorVoid::mTotalInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( FloatFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION ); + + signals.mFloatSignalVoid.Connect( &tracker, FloatFunctorVoid() ); + DALI_TEST_EQUALS( FloatFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( FloatFunctorVoid::mCurrentInstanceCount, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( FloatFunctorVoid::mCallbackCount, 0, TEST_LOCATION ); + + float returnValue = signals.mFloatSignalVoid.Emit(); + DALI_TEST_EQUALS( FloatFunctorVoid::mCallbackCount, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( returnValue, FloatFunctorVoid::DEFAULT_RETURN_VALUE, TEST_LOCATION ); + + // Test double emission + returnValue = 0.0f; + returnValue = signals.mFloatSignalVoid.Emit(); + DALI_TEST_EQUALS( FloatFunctorVoid::mCallbackCount, 2, TEST_LOCATION ); + DALI_TEST_EQUALS( returnValue, FloatFunctorVoid::DEFAULT_RETURN_VALUE, TEST_LOCATION ); + } + // TestConnectionTracker should auto-disconnect + DALI_TEST_EQUALS( FloatFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( FloatFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( FloatFunctorVoid::mCallbackCount, 2, TEST_LOCATION ); + signals.CheckNoConnections(); + + { + TestConnectionTracker tracker; + + DALI_TEST_EQUALS( FloatFunctorFloat::mTotalInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( FloatFunctorFloat::mCurrentInstanceCount, 0, TEST_LOCATION ); + + signals.mFloatSignalFloat.Connect( &tracker, FloatFunctorFloat() ); + DALI_TEST_EQUALS( FloatFunctorFloat::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( FloatFunctorFloat::mCurrentInstanceCount, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( FloatFunctorFloat::mCallbackCount, 0, TEST_LOCATION ); + + float returnValue = signals.mFloatSignalFloat.Emit( 0.1f ); + DALI_TEST_EQUALS( FloatFunctorFloat::mCallbackCount, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( returnValue, 1.0f + 0.1f, TEST_LOCATION ); + + // Test double emission + returnValue = signals.mFloatSignalFloat.Emit( 0.2f ); + DALI_TEST_EQUALS( FloatFunctorFloat::mCallbackCount, 2, TEST_LOCATION ); + DALI_TEST_EQUALS( returnValue, 1.0f + 0.2f, TEST_LOCATION ); + } + // TestConnectionTracker should auto-disconnect + DALI_TEST_EQUALS( FloatFunctorFloat::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( FloatFunctorFloat::mCurrentInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( FloatFunctorFloat::mCallbackCount, 2, TEST_LOCATION ); + signals.CheckNoConnections(); + END_TEST; +} + +int UtcDaliSignalFunctorsDisconnectBeforeEmit(void) +{ + // Test explicit disconnect using ConnectionTracker + + ResetFunctorCounts(); + + TestSignals signals; + + { + TestConnectionTracker tracker; + + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION ); + + signals.mVoidSignalVoid.Connect( &tracker, VoidFunctorVoid() ); + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 1, TEST_LOCATION ); + + tracker.DisconnectAll(); + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION ); + + signals.mVoidSignalVoid.Emit(); + DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 0, TEST_LOCATION ); + + // Test double emission + signals.mVoidSignalVoid.Emit(); + DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 0, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliSignalFunctorsDestroySignal(void) +{ + // Test destruction of signal before slot + + ResetFunctorCounts(); + + TestConnectionTracker tracker; + + { + TestSignals signals; + + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION ); + + signals.mVoidSignalVoid.Connect( &tracker, VoidFunctorVoid() ); + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 1, TEST_LOCATION ); + + signals.mVoidSignalVoid.Emit(); + DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount,1, TEST_LOCATION ); + + DALI_TEST_EQUALS( tracker.GetConnectionCount(), 1u, TEST_LOCATION ); + } + + // Functor should have been deleted with signal + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 1, TEST_LOCATION ); + + DALI_TEST_EQUALS( tracker.GetConnectionCount(), 0u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliSignalConnectVoidFunctor(void) +{ + // Test connecting a functor using the VoidFunctor wrapper + + ResetFunctorCounts(); + + TestSignals signals; + + { + TestConnectionTracker tracker; + + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION ); + + signals.mVoidSignalVoid.Connect( &tracker, FunctorDelegate::New( VoidFunctorVoid() ) ); + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 0, TEST_LOCATION ); + + signals.mVoidSignalVoid.Emit(); + DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 1, TEST_LOCATION ); + + // Test double emission + signals.mVoidSignalVoid.Emit(); + DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 2, TEST_LOCATION ); + } + // TestConnectionTracker should auto-disconnect + DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION ); + DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 2, TEST_LOCATION ); + signals.CheckNoConnections(); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Stage.cpp b/automated-tests/src/dali/utc-Dali-Stage.cpp new file mode 100644 index 0000000..3c5ef7b --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Stage.cpp @@ -0,0 +1,1323 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +using namespace Dali; + +void stage_test_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void stage_test_cleanup(void) +{ + test_return_value = TET_PASS; +} + +namespace +{ + +// Functor for EventProcessingFinished signal +struct EventProcessingFinishedFunctor +{ + /** + * @param[in] eventProcessingFinished reference to a boolean variable used to check if signal has been called. + */ + EventProcessingFinishedFunctor( bool& eventProcessingFinished ) + : mEventProcessingFinished( eventProcessingFinished ) + {} + + void operator()() + { + mEventProcessingFinished = true; + } + + bool& mEventProcessingFinished; +}; + +// Stores data that is populated in the key-event callback and will be read by the TET cases +struct KeyEventSignalData +{ + KeyEventSignalData() + : functorCalled(false) + {} + + void Reset() + { + functorCalled = false; + + receivedKeyEvent.keyModifier = 0; + receivedKeyEvent.keyPressedName.clear(); + receivedKeyEvent.keyPressed.clear(); + } + + bool functorCalled; + KeyEvent receivedKeyEvent; +}; + +// Functor that sets the data when called +struct KeyEventReceivedFunctor +{ + KeyEventReceivedFunctor( KeyEventSignalData& data ) : signalData( data ) { } + + bool operator()( const KeyEvent& keyEvent ) + { + signalData.functorCalled = true; + signalData.receivedKeyEvent = keyEvent; + + return true; + } + + KeyEventSignalData& signalData; +}; + +// Stores data that is populated in the touched signal callback and will be read by the TET cases +struct TouchedSignalData +{ + TouchedSignalData() + : functorCalled(false) + {} + + void Reset() + { + functorCalled = false; + + receivedTouchEvent.points.clear(); + receivedTouchEvent.time = 0; + } + + bool functorCalled; + TouchEvent receivedTouchEvent; +}; + +// Functor that sets the data when touched signal is received +struct TouchedFunctor +{ + TouchedFunctor( TouchedSignalData& data ) : signalData( data ) { } + + void operator()( const TouchEvent& touch ) + { + signalData.functorCalled = true; + signalData.receivedTouchEvent = touch; + } + + TouchedSignalData& signalData; +}; + +// Stores data that is populated in the wheel-event callback and will be read by the TET cases +struct WheelEventSignalData +{ + WheelEventSignalData() + : functorCalled(false) + {} + + void Reset() + { + functorCalled = false; + } + + bool functorCalled; + WheelEvent receivedWheelEvent; +}; + +// Functor that sets the data when wheel-event signal is received +struct WheelEventReceivedFunctor +{ + WheelEventReceivedFunctor( WheelEventSignalData& data ) : signalData( data ) { } + + bool operator()( const WheelEvent& wheelEvent ) + { + signalData.functorCalled = true; + signalData.receivedWheelEvent = wheelEvent; + + return true; + } + + WheelEventSignalData& signalData; +}; + +bool DummyTouchCallback( Actor actor, const TouchEvent& touch ) +{ + return true; +} + +struct ContextStatusFunctor +{ + ContextStatusFunctor(bool& calledFlag) : mCalledFlag( calledFlag ) + { + mCalledFlag = false; + } + + void operator()() + { + mCalledFlag = true; + } + void Reset() + { + mCalledFlag = false; + } + + bool& mCalledFlag; +}; + +struct SceneCreatedStatusFunctor +{ + SceneCreatedStatusFunctor(bool& calledFlag) : mCalledFlag( calledFlag ) + { + mCalledFlag = false; + } + + void operator()() + { + mCalledFlag = true; + } + void Reset() + { + mCalledFlag = false; + } + + bool& mCalledFlag; +}; + +struct ActorCreatedFunctor +{ + ActorCreatedFunctor( bool& signalReceived ) + : mSignalVerified( signalReceived ) + { + } + + void operator()( BaseHandle object ) + { + tet_infoline( "Verifying TestActorCallback()" ); + Actor actor = Actor::DownCast( object ); + if( actor ) + { + mSignalVerified = true; + } + } + + bool& mSignalVerified; +}; + +} // unnamed namespace + + +int UtcDaliStageDefaultConstructorP(void) +{ + TestApplication application; + Stage stage; + + DALI_TEST_CHECK( !stage ); + END_TEST; +} + +// Note: No negative test for default constructor. + +int UtcDaliStageDestructorP(void) +{ + TestApplication application; + Stage* stage = new Stage(); + delete stage; + stage = NULL; + + DALI_TEST_CHECK( true ); + END_TEST; +} + +// Note: No negative test for default destructor. + +int UtcDaliStageGetCurrentP(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + DALI_TEST_CHECK( stage ); + END_TEST; +} + +int UtcDaliStageGetCurrentN(void) +{ + bool asserted = false; + try + { + Stage stage = Stage::GetCurrent(); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "stage && \"Stage doesn't exist\"", TEST_LOCATION ); + asserted = true; + } + + DALI_TEST_CHECK( asserted ); + END_TEST; +} + +int UtcDaliStageIsInstalledP(void) +{ + TestApplication application; + + Stage::GetCurrent(); + + DALI_TEST_CHECK( Stage::IsInstalled() ); + END_TEST; +} + +int UtcDaliStageIsInstalledN(void) +{ + DALI_TEST_CHECK( !Stage::IsInstalled() ); + + END_TEST; +} + +int UtcDaliStageCopyConstructorP(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + Stage copyStage( stage ); + + DALI_TEST_CHECK( copyStage ); + DALI_TEST_CHECK( copyStage.GetRootLayer() == stage.GetRootLayer() ); + + END_TEST; +} + +// Note: no negative test for UtcDaliStageCopyConstructor. + +int UtcDaliStageAssignmentOperatorP(void) +{ + TestApplication application; + const Stage stage = Stage::GetCurrent(); + + Stage copyStage = stage; + + DALI_TEST_CHECK( copyStage ); + DALI_TEST_CHECK( copyStage.GetRootLayer() == stage.GetRootLayer() ); + + END_TEST; +} + +// Note: No negative test for UtcDaliStageAssignmentOperator. + +int UtcDaliStageAddP(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + Actor actor = Actor::New(); + DALI_TEST_CHECK( !actor.OnStage() ); + + stage.Add( actor ); + DALI_TEST_CHECK( actor.OnStage() ); + END_TEST; +} + +int UtcDaliStageAddN(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + Actor actor; + + bool asserted = false; + try + { + stage.Add( actor ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "actor && \"Actor handle is empty\"", TEST_LOCATION ); + asserted = true; + } + + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliStageRemoveP(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + Actor actor = Actor::New(); + DALI_TEST_CHECK( !actor.OnStage() ); + + stage.Add( actor ); + DALI_TEST_CHECK( actor.OnStage() ); + + stage.Remove(actor); + DALI_TEST_CHECK( !actor.OnStage() ); + END_TEST; +} + +int UtcDaliStageRemoveN1(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + Actor actor; + + bool asserted = false; + try + { + // Actor is not valid, confirm a removal attempt does assert. + stage.Remove( actor ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "actor && \"Actor handle is empty\"", TEST_LOCATION ); + asserted = true; + } + + DALI_TEST_CHECK( asserted ); + END_TEST; +} + +int UtcDaliStageRemoveN2(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + Actor actor = Actor::New(); + DALI_TEST_CHECK( !actor.OnStage() ); + + bool asserted = false; + try + { + // Actor is not on stage, confirm a removal attempt does not assert / segfault. + stage.Remove( actor ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + asserted = true; + } + + DALI_TEST_CHECK( !asserted ); + END_TEST; +} + +int UtcDaliStageRemoveN3(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + // Initially we have a default layer + DALI_TEST_EQUALS( stage.GetLayerCount(), 1u, TEST_LOCATION ); + + // Check we cannot remove the root layer from the stage. + Layer layer = stage.GetRootLayer(); + bool asserted = true; + try + { + stage.Remove( layer ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "this != &child && \"Cannot remove actor from itself\"", TEST_LOCATION ); + asserted = true; + } + + DALI_TEST_CHECK( asserted ); + DALI_TEST_EQUALS( stage.GetLayerCount(), 1u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliStageGetSizeP(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + Vector2 size = stage.GetSize(); + + DALI_TEST_EQUALS( size.width, static_cast( TestApplication::DEFAULT_SURFACE_WIDTH ), TEST_LOCATION ); + DALI_TEST_EQUALS( size.height, static_cast( TestApplication::DEFAULT_SURFACE_HEIGHT ), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliStageGetSizeN(void) +{ + TestApplication application; + + Stage stage; + + bool asserted = false; + Vector2 size; + try + { + size = stage.GetSize(); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "stage && \"Stage handle is empty\"", TEST_LOCATION ); + asserted = true; + } + + DALI_TEST_CHECK( asserted ); + END_TEST; +} + +int UtcDaliStageGetDpiP1(void) +{ + TestApplication application; // Initializes core DPI to default values + + Stage stage = Stage::GetCurrent(); + + // Test the default DPI. + Vector2 dpi = stage.GetDpi(); + DALI_TEST_EQUALS( dpi.x, static_cast( TestApplication::DEFAULT_HORIZONTAL_DPI ), TEST_LOCATION ); + DALI_TEST_EQUALS( dpi.y, static_cast( TestApplication::DEFAULT_VERTICAL_DPI ), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliStageGetDpiP2(void) +{ + TestApplication application; // Initializes core DPI to default values + + // Test that setting core DPI explicitly also sets up the Stage's DPI. + application.GetCore().SetDpi( 200, 180 ); + + Stage stage = Stage::GetCurrent(); + Vector2 dpi = stage.GetDpi(); + DALI_TEST_EQUALS( dpi.x, 200.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( dpi.y, 180.0f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliStageGetDpiP3(void) +{ + TestApplication application( 480, 800, 72.0f, 120.0f ); // Initializes core DPI with specific values + + Stage stage = Stage::GetCurrent(); + + // Test that setting core DPI explicitly also sets up the Stage's DPI. + Vector2 dpi = stage.GetDpi(); + DALI_TEST_EQUALS( dpi.x, 72.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( dpi.y, 120.0f, TEST_LOCATION) ; + END_TEST; +} + +/* + * This is not a true negative test, we are checking the DPI if it has not been set. + * A test for setting negative DPI values would be part of the application core utc tests. + */ +int UtcDaliStageGetDpiN(void) +{ + TestApplication application; // Initializes core DPI to default values + + Stage stage = Stage::GetCurrent(); + Vector2 dpi = stage.GetDpi(); + + DALI_TEST_EQUALS( dpi.x, 220.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( dpi.y, 217.0f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliStageGetLayerCountP(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + // Initially we have a default layer + DALI_TEST_EQUALS( stage.GetLayerCount(), 1u, TEST_LOCATION ); + + Layer layer = Layer::New(); + stage.Add( layer ); + + DALI_TEST_EQUALS( stage.GetLayerCount(), 2u, TEST_LOCATION ); + END_TEST; +} + +/* + * Not a true negative test, but confirms layer count is not affected by an invalid removal. + */ +int UtcDaliStageGetLayerCountN(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + // Initially we have a default layer + DALI_TEST_EQUALS( stage.GetLayerCount(), 1u, TEST_LOCATION ); + + Layer layer = Layer::New(); + stage.Remove( layer ); + + // Still have 1 layer. + DALI_TEST_EQUALS( stage.GetLayerCount(), 1u, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliStageGetLayerP(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + Layer rootLayer = stage.GetLayer( 0 ); + DALI_TEST_CHECK( rootLayer ); + + Layer layer = Layer::New(); + stage.Add( layer ); + + Layer sameLayer = stage.GetLayer( 1 ); + DALI_TEST_CHECK( layer == sameLayer ); + END_TEST; +} + +int UtcDaliStageGetLayerN(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + bool asserted = false; + try + { + // Try to get a layer that doesn't exist (note: 0 is the root layer). + Layer layer = stage.GetLayer( 1 ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "depth < mLayers.size()", TEST_LOCATION ); + asserted = true; + } + + DALI_TEST_CHECK( asserted ); + END_TEST; +} + +int UtcDaliStageGetRootLayerP(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + Layer layer = stage.GetLayer( 0 ); + DALI_TEST_CHECK( layer ); + + // Check that GetRootLayer() correctly retreived layer 0. + DALI_TEST_CHECK( stage.GetRootLayer() == layer ); + + END_TEST; +} + +int UtcDaliStageGetRootLayerN(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + Layer rootLayer = stage.GetLayer( 0 ); + DALI_TEST_CHECK( rootLayer ); + DALI_TEST_CHECK( stage.GetRootLayer() == rootLayer ); + + // Create a new layer and attempt to lower it below the root layer. + Layer layer = Layer::New(); + stage.Add( layer ); + layer.LowerToBottom(); + + // Check that GetRootLayer still retrieves the same original layer. + DALI_TEST_CHECK( stage.GetRootLayer() == rootLayer ); + + // Check modifying the root layer is also blocked. + rootLayer.RaiseToTop(); + DALI_TEST_CHECK( stage.GetRootLayer() == rootLayer ); + + END_TEST; +} + +int UtcDaliStageSetBackgroundColorP(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + Vector4 testColor( 0.1f, 0.2f, 0.3f, 1.0f ); + stage.SetBackgroundColor( testColor ); + + DALI_TEST_EQUALS( testColor, stage.GetBackgroundColor(), TEST_LOCATION ); + END_TEST; +} + +// Note: No negative test for UtcDaliStageSetBackgroundColor as we do not wish to implement +// range checking for colors due to speed. Colors are clamped with glclampf within GL anyway. + +int UtcDaliStageGetBackgroundColorP(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + DALI_TEST_EQUALS( Stage::DEFAULT_BACKGROUND_COLOR, stage.GetBackgroundColor(), TEST_LOCATION ); + END_TEST; +} + +// Note: No negative test for UtcDaliStageGetBackgroundColor as this is covered by UtcDaliStageSetBackgroundColorN. + +int UtcDaliStageKeepRenderingP(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + // Run core until it wants to sleep + bool keepUpdating( true ); + while ( keepUpdating ) + { + application.SendNotification(); + keepUpdating = application.Render( 1000.0f /*1 second*/ ); + } + + // Force rendering for the next 5 seconds + stage.KeepRendering( 5.0f ); + + application.SendNotification(); + + // Test that core wants to sleep after 10 seconds + keepUpdating = application.Render( 1000.0f /*1 second*/ ); + DALI_TEST_CHECK( keepUpdating ); + keepUpdating = application.Render( 1000.0f /*2 seconds*/ ); + DALI_TEST_CHECK( keepUpdating ); + keepUpdating = application.Render( 1000.0f /*3 seconds*/ ); + DALI_TEST_CHECK( keepUpdating ); + keepUpdating = application.Render( 1000.0f /*4 seconds*/ ); + DALI_TEST_CHECK( keepUpdating ); + keepUpdating = application.Render( 1000.0f /*5 seconds*/ ); + DALI_TEST_CHECK( !keepUpdating ); + END_TEST; +} + +int UtcDaliStageKeepRenderingN(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + + // Run core until it wants to sleep + bool keepUpdating( true ); + while ( keepUpdating ) + { + application.SendNotification(); + keepUpdating = application.Render( 1000.0f /*1 second*/ ); + } + + // Force rendering for the next 5 seconds + stage.KeepRendering( -1.0f ); + + application.SendNotification(); + + // Test that core wants to sleep after 10 seconds + keepUpdating = application.Render( 1000.0f /*1 second*/ ); + DALI_TEST_CHECK( !keepUpdating ); + + END_TEST; +} + +int UtcDaliStageEventProcessingFinishedP(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + bool eventProcessingFinished = false; + EventProcessingFinishedFunctor functor( eventProcessingFinished ); + stage.EventProcessingFinishedSignal().Connect( &application, functor ); + + Actor actor( Actor::New() ); + stage.Add( actor ); + + application.SendNotification(); + application.Render(); + + DALI_TEST_CHECK( eventProcessingFinished ); + + END_TEST; +} + +int UtcDaliStageEventProcessingFinishedN(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + bool eventProcessingFinished = false; + EventProcessingFinishedFunctor functor( eventProcessingFinished ); + stage.EventProcessingFinishedSignal().Connect( &application, functor ); + + Actor actor( Actor::New() ); + stage.Add( actor ); + + // Do not complete event processing and confirm the signal has not been emitted. + DALI_TEST_CHECK( !eventProcessingFinished ); + + END_TEST; +} + +int UtcDaliStageSignalKeyEventP(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + KeyEventSignalData data; + KeyEventReceivedFunctor functor( data ); + stage.KeyEventSignal().Connect( &application, functor ); + + Integration::KeyEvent event( "i", "i", 0, 0, 0, Integration::KeyEvent::Down ); + application.ProcessEvent( event ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( event.keyModifier == data.receivedKeyEvent.keyModifier ); + DALI_TEST_CHECK( event.keyName == data.receivedKeyEvent.keyPressedName ); + DALI_TEST_CHECK( event.keyString == data.receivedKeyEvent.keyPressed ); + DALI_TEST_CHECK( event.state == static_cast( data.receivedKeyEvent.state ) ); + + data.Reset(); + + Integration::KeyEvent event2( "i", "i", 0, 0, 0, Integration::KeyEvent::Up ); + application.ProcessEvent( event2 ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( event2.keyModifier == data.receivedKeyEvent.keyModifier ); + DALI_TEST_CHECK( event2.keyName == data.receivedKeyEvent.keyPressedName ); + DALI_TEST_CHECK( event2.keyString == data.receivedKeyEvent.keyPressed ); + DALI_TEST_CHECK( event2.state == static_cast( data.receivedKeyEvent.state ) ); + + data.Reset(); + + Integration::KeyEvent event3( "a", "a", 0, 0, 0, Integration::KeyEvent::Down ); + application.ProcessEvent( event3 ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( event3.keyModifier == data.receivedKeyEvent.keyModifier ); + DALI_TEST_CHECK( event3.keyName == data.receivedKeyEvent.keyPressedName ); + DALI_TEST_CHECK( event3.keyString == data.receivedKeyEvent.keyPressed ); + DALI_TEST_CHECK( event3.state == static_cast( data.receivedKeyEvent.state ) ); + + data.Reset(); + + Integration::KeyEvent event4( "a", "a", 0, 0, 0, Integration::KeyEvent::Up ); + application.ProcessEvent( event4 ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( event4.keyModifier == data.receivedKeyEvent.keyModifier ); + DALI_TEST_CHECK( event4.keyName == data.receivedKeyEvent.keyPressedName ); + DALI_TEST_CHECK( event4.keyString == data.receivedKeyEvent.keyPressed ); + DALI_TEST_CHECK( event4.state == static_cast( data.receivedKeyEvent.state ) ); + END_TEST; +} + +int UtcDaliStageSignalKeyEventN(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + KeyEventSignalData data; + KeyEventReceivedFunctor functor( data ); + stage.KeyEventSignal().Connect( &application, functor ); + + // Check that a non-pressed key events data is not modified. + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliStageTouchedSignalP(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + TouchedSignalData data; + TouchedFunctor functor( data ); + stage.TouchedSignal().Connect( &application, functor ); + + // Render and notify. + application.SendNotification(); + application.Render(); + + // Basic test: No actors, single touch (down then up). + { + Integration::TouchEvent touchEvent; + touchEvent.points.push_back( TouchPoint( 0, TouchPoint::Down, 10.0f, 10.0f ) ); + application.ProcessEvent( touchEvent ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u ); + DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor ); + data.Reset(); + + touchEvent.points[0].state = TouchPoint::Up; + application.ProcessEvent( touchEvent ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u ); + DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor ); + data.Reset(); + } + + // Add an actor to the scene. + Actor actor = Actor::New(); + actor.SetSize( 100.0f, 100.0f ); + actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + actor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + actor.TouchedSignal().Connect( &DummyTouchCallback ); + stage.Add( actor ); + + // Render and notify. + application.SendNotification(); + application.Render(); + + // Actor on scene, single touch, down in actor, motion, then up outside actor. + { + Integration::TouchEvent touchEvent; + touchEvent.points.push_back( TouchPoint( 0, TouchPoint::Down, 10.0f, 10.0f ) ); + application.ProcessEvent( touchEvent ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u ); + DALI_TEST_CHECK( data.receivedTouchEvent.points[0].hitActor == actor ); + data.Reset(); + + touchEvent.points[0].state = TouchPoint::Motion; + touchEvent.points[0].screen.x = 150.0f; // Some motion + application.ProcessEvent( touchEvent ); + + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + touchEvent.points[0].state = TouchPoint::Up; + application.ProcessEvent( touchEvent ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u ); + DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor ); + data.Reset(); + } + + // Multiple touch. Should only receive a touch on first down and last up. + { + Integration::TouchEvent touchEvent; + + // 1st point + touchEvent.points.push_back( TouchPoint( 0, TouchPoint::Down, 10.0f, 10.0f ) ); + application.ProcessEvent( touchEvent ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( data.receivedTouchEvent.GetPointCount(), 1u, TEST_LOCATION ); + data.Reset(); + + // 2nd point + touchEvent.points[0].state = TouchPoint::Stationary; + touchEvent.points.push_back( TouchPoint( 1, TouchPoint::Down, 50.0f, 50.0f ) ); + application.ProcessEvent( touchEvent ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( data.receivedTouchEvent.GetPointCount(), 0u, TEST_LOCATION ); + data.Reset(); + + // Primary point is up + touchEvent.points[0].state = TouchPoint::Up; + touchEvent.points[1].state = TouchPoint::Stationary; + application.ProcessEvent( touchEvent ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( data.receivedTouchEvent.GetPointCount(), 0u, TEST_LOCATION ); + data.Reset(); + + // Remove 1st point now, 2nd point is now in motion + touchEvent.points.erase( touchEvent.points.begin() ); + touchEvent.points[0].state = TouchPoint::Motion; + touchEvent.points[0].screen.x = 150.0f; + application.ProcessEvent( touchEvent ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( data.receivedTouchEvent.GetPointCount(), 0u, TEST_LOCATION ); + data.Reset(); + + // Final point Up + touchEvent.points[0].state = TouchPoint::Up; + application.ProcessEvent( touchEvent ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( data.receivedTouchEvent.GetPointCount(), 1u, TEST_LOCATION ); + data.Reset(); + } + END_TEST; +} + +int UtcDaliStageTouchedSignalN(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + TouchedSignalData data; + TouchedFunctor functor( data ); + stage.TouchedSignal().Connect( &application, functor ); + + // Render and notify. + application.SendNotification(); + application.Render(); + + // Confirm functor not called before there has been any touch event. + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + + // No actors, single touch, down, motion then up. + { + Integration::TouchEvent touchEvent; + touchEvent.points.push_back( TouchPoint( 0, TouchPoint::Down, 10.0f, 10.0f ) ); + application.ProcessEvent( touchEvent ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u ); + DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor ); + data.Reset(); + + // Confirm there is no signal when the touchpoint is only moved. + touchEvent.points[0].state = TouchPoint::Motion; + touchEvent.points[0].screen.x = 1200.0f; // Some motion + application.ProcessEvent( touchEvent ); + + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Confirm a following up event generates a signal. + touchEvent.points[0].state = TouchPoint::Up; + application.ProcessEvent( touchEvent ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u ); + DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor ); + data.Reset(); + } + + // Add an actor to the scene. + Actor actor = Actor::New(); + actor.SetSize( 100.0f, 100.0f ); + actor.SetAnchorPoint( AnchorPoint::TOP_LEFT ); + actor.SetParentOrigin( ParentOrigin::TOP_LEFT ); + actor.TouchedSignal().Connect( &DummyTouchCallback ); + stage.Add( actor ); + + // Render and notify. + application.SendNotification(); + application.Render(); + + // Actor on scene. Interrupted before down and interrupted after down. + { + Integration::TouchEvent touchEvent; + touchEvent.points.push_back( TouchPoint( 0, TouchPoint::Interrupted, 10.0f, 10.0f ) ); + application.ProcessEvent( touchEvent ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u ); + DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor ); + DALI_TEST_CHECK( data.receivedTouchEvent.points[0].state == TouchPoint::Interrupted ); + data.Reset(); + + touchEvent.points[0].state = TouchPoint::Down; + application.ProcessEvent( touchEvent ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u ); + DALI_TEST_CHECK( data.receivedTouchEvent.points[0].hitActor == actor ); + DALI_TEST_CHECK( data.receivedTouchEvent.points[0].state == TouchPoint::Down ); + data.Reset(); + + touchEvent.points[0].state = TouchPoint::Interrupted; + application.ProcessEvent( touchEvent ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u ); + DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor ); + DALI_TEST_CHECK( data.receivedTouchEvent.points[0].state == TouchPoint::Interrupted ); + + DALI_TEST_EQUALS( data.receivedTouchEvent.GetPointCount(), 1u, TEST_LOCATION ); + + // Check that getting info about a non-existent point causes an assert. + bool asserted = false; + try + { + data.receivedTouchEvent.GetPoint( 1 ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "point < points.size() && \"No point at index\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + + data.Reset(); + } + + END_TEST; +} + +int UtcDaliStageSignalWheelEventP(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + WheelEventSignalData data; + WheelEventReceivedFunctor functor( data ); + stage.WheelEventSignal().Connect( &application, functor ); + + Integration::WheelEvent event( Integration::WheelEvent::CUSTOM_WHEEL, 0, 0u, Vector2( 0.0f, 0.0f ), 1, 1000u ); + application.ProcessEvent( event ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( static_cast< WheelEvent::Type >(event.type) == data.receivedWheelEvent.type ); + DALI_TEST_CHECK( event.direction == data.receivedWheelEvent.direction ); + DALI_TEST_CHECK( event.modifiers == data.receivedWheelEvent.modifiers ); + DALI_TEST_CHECK( event.point == data.receivedWheelEvent.point ); + DALI_TEST_CHECK( event.z == data.receivedWheelEvent.z ); + DALI_TEST_CHECK( event.timeStamp == data.receivedWheelEvent.timeStamp ); + + data.Reset(); + + Integration::WheelEvent event2( Integration::WheelEvent::CUSTOM_WHEEL, 0, 0u, Vector2( 0.0f, 0.0f ), -1, 1000u ); + application.ProcessEvent( event2 ); + + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( static_cast< WheelEvent::Type >(event2.type) == data.receivedWheelEvent.type ); + DALI_TEST_CHECK( event2.direction == data.receivedWheelEvent.direction ); + DALI_TEST_CHECK( event2.modifiers == data.receivedWheelEvent.modifiers ); + DALI_TEST_CHECK( event2.point == data.receivedWheelEvent.point ); + DALI_TEST_CHECK( event2.z == data.receivedWheelEvent.z ); + DALI_TEST_CHECK( event2.timeStamp == data.receivedWheelEvent.timeStamp ); + END_TEST; +} + +int UtcDaliStageContextLostSignalP(void) +{ + TestApplication app; + Stage stage = Stage::GetCurrent(); + + bool contextLost = false; + ContextStatusFunctor contextLostFunctor( contextLost ); + stage.ContextLostSignal().Connect( &app, contextLostFunctor ); + + Integration::ContextNotifierInterface* notifier = app.GetCore().GetContextNotifier(); + notifier->NotifyContextLost(); + DALI_TEST_EQUALS( contextLost, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliStageContextLostSignalN(void) +{ + TestApplication app; + Stage stage; + + // Check that connecting to the signal with a bad stage instance causes an assert. + bool asserted = false; + bool contextLost = false; + ContextStatusFunctor contextLostFunctor( contextLost ); + try + { + stage.ContextLostSignal().Connect( &app, contextLostFunctor ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "stage && \"Stage handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliStageContextRegainedSignalP(void) +{ + TestApplication app; + Stage stage = Stage::GetCurrent(); + + bool contextRegained = false; + ContextStatusFunctor contextRegainedFunctor( contextRegained ); + stage.ContextRegainedSignal().Connect( &app, contextRegainedFunctor ); + + Integration::ContextNotifierInterface* notifier = app.GetCore().GetContextNotifier(); + notifier->NotifyContextLost(); + notifier->NotifyContextRegained(); + DALI_TEST_EQUALS( contextRegained, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliStageContextRegainedSignalN(void) +{ + TestApplication app; + Stage stage; + + // Check that connecting to the signal with a bad stage instance causes an assert. + bool asserted = false; + bool contextRegained = false; + ContextStatusFunctor contextRegainedFunctor( contextRegained ); + try + { + stage.ContextRegainedSignal().Connect( &app, contextRegainedFunctor ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "stage && \"Stage handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliStageSceneCreatedSignalP(void) +{ + TestApplication app; + Stage stage = Stage::GetCurrent(); + + bool signalCalled = false; + SceneCreatedStatusFunctor sceneCreatedFunctor( signalCalled ); + stage.SceneCreatedSignal().Connect( &app, sceneCreatedFunctor ); + + Integration::Core& core = app.GetCore(); + core.SceneCreated(); + DALI_TEST_EQUALS( signalCalled, true, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliStageSceneCreatedSignalN(void) +{ + TestApplication app; + Stage stage; + + // Check that connecting to the signal with a bad stage instance causes an assert. + bool asserted = false; + bool signalCalled = false; + SceneCreatedStatusFunctor sceneCreatedFunctor( signalCalled ); + try + { + stage.SceneCreatedSignal().Connect( &app, sceneCreatedFunctor ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "stage && \"Stage handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliStageGetRenderTaskListP(void) +{ + TestApplication app; + Stage stage = Stage::GetCurrent(); + + // Check we get a valid instance. + const RenderTaskList& tasks = stage.GetRenderTaskList(); + + // There should be 1 task by default. + DALI_TEST_EQUALS( tasks.GetTaskCount(), 1u, TEST_LOCATION ); + + // RenderTaskList has it's own UTC tests. + // But we can confirm that GetRenderTaskList in Stage retrieves the same RenderTaskList each time. + RenderTask newTask = stage.GetRenderTaskList().CreateTask(); + + DALI_TEST_EQUALS( stage.GetRenderTaskList().GetTask( 1 ), newTask, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliStageGetRenderTaskListN(void) +{ + TestApplication app; + Stage stage; + + // Check that getting the render task list with a bad stage instance causes an assert. + bool asserted = false; + try + { + stage.GetRenderTaskList(); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "stage && \"Stage handle is empty\"", TEST_LOCATION ); + asserted = true; + } + DALI_TEST_CHECK( asserted ); + + END_TEST; +} + +int UtcDaliStageGetObjectRegistryP(void) +{ + TestApplication app; + Stage stage = Stage::GetCurrent(); + + ObjectRegistry objectRegistry = stage.GetObjectRegistry(); + + // Object registry tests are covered in their own module. + // However we want a basic test to confirm the returned registry is valid and works. + bool verified = false; + ActorCreatedFunctor test( verified ); + objectRegistry.ObjectCreatedSignal().Connect( &app, test ); + + Actor actor = Actor::New(); + DALI_TEST_CHECK( test.mSignalVerified ); + + END_TEST; +} + +int UtcDaliStageGetObjectRegistryN(void) +{ + TestApplication app; + Stage stage; + + // Check that getting the object registry with a bad stage instance DOES NOT cause an assert. + // This is because GetCurrent() is used, always creating a stage if one does not exist. + bool asserted = false; + try + { + stage.GetObjectRegistry(); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + asserted = true; + } + DALI_TEST_CHECK( !asserted ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-TapGesture.cpp b/automated-tests/src/dali/utc-Dali-TapGesture.cpp new file mode 100644 index 0000000..e53dcbb --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-TapGesture.cpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_tap_gesture_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_tap_gesture_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +// Positive test case for a method +int UtcDaliTapGestureConstructor(void) +{ + TestApplication application; // Reset all test adapter return codes + + TapGesture gesture; + DALI_TEST_EQUALS(1u, gesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(1u, gesture.numberOfTaps, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Tap, gesture.type, TEST_LOCATION); + + // Test Copy constructor + gesture.numberOfTouches = 5u; + gesture.numberOfTaps = 2u; + + TapGesture gesture2(gesture); + DALI_TEST_EQUALS(5u, gesture2.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(2u, gesture2.numberOfTaps, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Tap, gesture2.type, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureAssignment(void) +{ + // Test Assignment operator + TapGesture gesture; + DALI_TEST_EQUALS(1u, gesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(1u, gesture.numberOfTaps, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Tap, gesture.type, TEST_LOCATION); + + gesture.numberOfTouches = 5u; + gesture.numberOfTaps = 2u; + + TapGesture gesture2; + gesture2 = gesture; + DALI_TEST_EQUALS(5u, gesture2.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(2u, gesture2.numberOfTaps, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Tap, gesture2.type, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureDynamicAllocation(void) +{ + TapGesture* gesture = new TapGesture; + DALI_TEST_EQUALS(1u, gesture->numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS(1u, gesture->numberOfTaps, TEST_LOCATION); + DALI_TEST_EQUALS(Gesture::Tap, gesture->type, TEST_LOCATION); + delete gesture; + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp new file mode 100644 index 0000000..eed11ca --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp @@ -0,0 +1,1387 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; + +void utc_dali_tap_gesture_detector_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_tap_gesture_detector_cleanup(void) +{ + test_return_value = TET_PASS; +} + +/////////////////////////////////////////////////////////////////////////////// +namespace +{ + +// Stores data that is populated in the callback and will be read by the TET cases +struct SignalData +{ + SignalData() + : functorCalled(false), + voidFunctorCalled(false) + {} + + void Reset() + { + functorCalled = false; + voidFunctorCalled = false; + + receivedGesture.numberOfTaps = 0u; + receivedGesture.numberOfTouches = 0u; + receivedGesture.screenPoint = Vector2(0.0f, 0.0f); + receivedGesture.localPoint = Vector2(0.0f, 0.0f); + + tappedActor.Reset(); + } + + bool functorCalled; + bool voidFunctorCalled; + TapGesture receivedGesture; + Actor tappedActor; +}; + +// Functor that sets the data when called +struct GestureReceivedFunctor +{ + GestureReceivedFunctor(SignalData& data) : signalData(data) { } + + void operator()(Actor actor, const TapGesture& tap) + { + signalData.functorCalled = true; + signalData.receivedGesture = tap; + signalData.tappedActor = actor; + } + + void operator()() + { + signalData.voidFunctorCalled = true; + } + + SignalData& signalData; +}; + +// Functor that removes the gestured actor from stage +struct UnstageActorFunctor : public GestureReceivedFunctor +{ + UnstageActorFunctor( SignalData& data ) : GestureReceivedFunctor( data ) { } + + void operator()(Actor actor, const TapGesture& tap) + { + GestureReceivedFunctor::operator()( actor, tap ); + Stage::GetCurrent().Remove( actor ); + } +}; + +// Functor for receiving a touch event +struct TouchEventFunctor +{ + bool operator()(Actor actor, const TouchEvent& touch) + { + //For line coverage + unsigned int points = touch.GetPointCount(); + if( points > 0) + { + const TouchPoint& touchPoint = touch.GetPoint(0); + tet_printf("Touch Point state = %d\n", touchPoint.state); + } + return false; + } +}; + +// Generate a TapGestureEvent to send to Core +Integration::TapGestureEvent GenerateTap( + Gesture::State state, + unsigned int numberOfTaps, + unsigned int numberOfTouches, + Vector2 point) +{ + Integration::TapGestureEvent tap( state ); + + tap.numberOfTaps = numberOfTaps; + tap.numberOfTouches = numberOfTouches; + tap.point = point; + + return tap; +} + +} // anon namespace + +/////////////////////////////////////////////////////////////////////////////// + + +// Positive test case for a method +int UtcDaliTapGestureDetectorConstructor(void) +{ + TestApplication application; + + TapGestureDetector detector; + DALI_TEST_CHECK(!detector); + END_TEST; +} + +int UtcDaliTapGestureDetectorCopyConstructorP(void) +{ + TestApplication application; + + TapGestureDetector detector = TapGestureDetector::New(); + + TapGestureDetector copy( detector ); + DALI_TEST_CHECK( detector ); + END_TEST; +} + +int UtcDaliTapGestureDetectorAssignmentOperatorP(void) +{ + TestApplication application; + + TapGestureDetector detector = TapGestureDetector::New();; + + TapGestureDetector assign; + assign = detector; + DALI_TEST_CHECK( detector ); + + DALI_TEST_CHECK( detector == assign ); + END_TEST; +} + +int UtcDaliTapGestureDetectorNew(void) +{ + TestApplication application; + + TapGestureDetector detector = TapGestureDetector::New(); + DALI_TEST_CHECK(detector); + DALI_TEST_EQUALS(1u, detector.GetMinimumTapsRequired(), TEST_LOCATION); + DALI_TEST_EQUALS(1u, detector.GetMaximumTapsRequired(), TEST_LOCATION); + + TapGestureDetector detector2 = TapGestureDetector::New( 5u ); + DALI_TEST_CHECK(detector2); + DALI_TEST_EQUALS(5u, detector2.GetMinimumTapsRequired(), TEST_LOCATION); + DALI_TEST_EQUALS(5u, detector2.GetMaximumTapsRequired(), TEST_LOCATION); + + //Scoped test to test destructor + { + TapGestureDetector detector3 = TapGestureDetector::New(); + DALI_TEST_CHECK(detector3); + } + + // Attach an actor and emit a touch event on the actor to ensure complete line coverage + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + detector.Attach(actor); + + TouchEventFunctor touchFunctor; + actor.TouchedSignal().Connect( &application, touchFunctor ); + + Integration::TouchEvent touchEvent(1); + TouchPoint point(1, TouchPoint::Down, 20.0f, 20.0f); + touchEvent.AddPoint(point); + application.ProcessEvent(touchEvent); + + // Render and notify + application.SendNotification(); + application.Render(); + + // For line coverage, Initialise default constructor + TouchEvent touchEvent2; + END_TEST; +} + +int UtcDaliTapGestureDetectorDownCast(void) +{ + TestApplication application; + tet_infoline("Testing Dali::TapGestureDetector::DownCast()"); + + TapGestureDetector detector = TapGestureDetector::New(); + + BaseHandle object(detector); + + TapGestureDetector detector2 = TapGestureDetector::DownCast(object); + DALI_TEST_CHECK(detector2); + + TapGestureDetector detector3 = DownCast< TapGestureDetector >(object); + DALI_TEST_CHECK(detector3); + + BaseHandle unInitializedObject; + TapGestureDetector detector4 = TapGestureDetector::DownCast(unInitializedObject); + DALI_TEST_CHECK(!detector4); + + TapGestureDetector detector5 = DownCast< TapGestureDetector >(unInitializedObject); + DALI_TEST_CHECK(!detector5); + + GestureDetector detector6 = TapGestureDetector::New(); + TapGestureDetector detector7 = TapGestureDetector::DownCast(detector6); + DALI_TEST_CHECK(detector7); + END_TEST; +} + +int UtcDaliTapGestureSetTapsRequired(void) +{ + TestApplication application; + + TapGestureDetector detector = TapGestureDetector::New(); + + const unsigned int minTaps = 3; + const unsigned int maxTaps = 7; + + DALI_TEST_CHECK( minTaps != detector.GetMinimumTapsRequired() ); + DALI_TEST_CHECK( maxTaps != detector.GetMaximumTapsRequired() ); + + detector.SetMinimumTapsRequired( minTaps ); + detector.SetMaximumTapsRequired( maxTaps ); + + DALI_TEST_EQUALS( minTaps, detector.GetMinimumTapsRequired(), TEST_LOCATION ); + DALI_TEST_EQUALS( maxTaps, detector.GetMaximumTapsRequired(), TEST_LOCATION ); + + // Attach an actor and change the required touches + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Ensure signal is emitted if minimum taps received + application.ProcessEvent(GenerateTap(Gesture::Possible, minTaps, 1u, Vector2(50.0f, 50.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, minTaps, 1u, Vector2(50.0f, 50.0f))); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( minTaps, data.receivedGesture.numberOfTaps, TEST_LOCATION ); + data.Reset(); + + // Ensure signal is emitted if maximum taps received + application.ProcessEvent(GenerateTap(Gesture::Possible, maxTaps, 1u, Vector2(50.0f, 50.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, maxTaps, 1u, Vector2(50.0f, 50.0f))); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( maxTaps, data.receivedGesture.numberOfTaps, TEST_LOCATION ); + data.Reset(); + + // Ensure signal is NOT emitted if outside the range + application.ProcessEvent(GenerateTap(Gesture::Possible, minTaps - 1, 1u, Vector2(50.0f, 50.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, minTaps - 1, 1u, Vector2(50.0f, 50.0f))); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, maxTaps + 1, 1u, Vector2(50.0f, 50.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, maxTaps + 1, 1u, Vector2(50.0f, 50.0f))); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + TestGestureManager& gestureManager = application.GetGestureManager(); + gestureManager.Initialize(); + + detector.SetMinimumTapsRequired(4); + + // Gesture detection should have been updated only + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + // Reset values + gestureManager.Initialize(); + + detector.SetMaximumTapsRequired(maxTaps); + + // Gesture detection should NOT have been updated + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + // Reset values + gestureManager.Initialize(); + + // Create a second gesture detector that requires even less maximum touches + TapGestureDetector secondDetector = TapGestureDetector::New(); + secondDetector.Attach(actor); + + // Gesture detection should have been updated + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + // Reset values + gestureManager.Initialize(); + + // Delete the second detector so that our detection is updated again + secondDetector.Reset(); + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + // Set the minimum to be greater than the maximum, should Assert + try + { + detector.SetMinimumTapsRequired( maxTaps ); + detector.SetMaximumTapsRequired( minTaps ); + DALI_TEST_CHECK( false ); // Should not get here + } + catch ( DaliException& e ) + { + DALI_TEST_CHECK( true ); + } + + END_TEST; +} + +int UtcDaliTapGestureSetTapsRequiredMinMaxCheck(void) +{ + TestApplication application; + + // Attach an actor and change the required touches + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set the minimum to be greater than the maximum, should Assert + + try + { + TapGestureDetector detector = TapGestureDetector::New(); + detector.SetMinimumTapsRequired( 7u ); + detector.SetMaximumTapsRequired( 3u ); + detector.Attach(actor); + DALI_TEST_CHECK( false ); // Should not get here + } + catch ( DaliException& e ) + { + DALI_TEST_CHECK( true ); + } + + END_TEST; +} + +int UtcDaliTapGestureGetTapsRequired(void) +{ + TestApplication application; + + TapGestureDetector detector = TapGestureDetector::New(); + DALI_TEST_EQUALS(1u, detector.GetMinimumTapsRequired(), TEST_LOCATION); + DALI_TEST_EQUALS(1u, detector.GetMaximumTapsRequired(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureSignalReceptionNegative(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Do a tap outside actor's area + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(112.0f, 112.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(112.0f, 112.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureSignalReceptionPositive(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Do a tap inside actor's area + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 50.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 50.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTaps, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(50.0f, 50.0f), data.receivedGesture.localPoint, 0.1, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureSignalReceptionDetach(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Start tap within the actor's area + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(20.0f, 20.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTaps, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(20.0f, 20.0f), data.receivedGesture.localPoint, 0.1, TEST_LOCATION); + + // repeat the tap within the actor's area - we should still receive the signal + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 50.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 50.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTaps, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(50.0f, 50.0f), data.receivedGesture.localPoint, 0.1, TEST_LOCATION); + + // Detach actor + detector.DetachAll(); + + // Ensure we are no longer signalled + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(20.0f, 20.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 50.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 50.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureSignalReceptionActorDestroyedWhileTapping(void) +{ + TestApplication application; + + SignalData data; + GestureReceivedFunctor functor(data); + + TapGestureDetector detector = TapGestureDetector::New(); + detector.DetectedSignal().Connect(&application, functor); + + // Actor lifetime is scoped + { + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + detector.Attach(actor); + + // Start tap within the actor's area + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(20.0f, 20.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Remove the actor from stage and reset the data + Stage::GetCurrent().Remove(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + } + + // Actor should now have been destroyed + + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(20.0f, 20.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(20.0f, 20.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureSignalReceptionRotatedActor(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Do tap, only check finished value + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(5.0f, 5.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(5.0f, 5.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTaps, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(5.0f, 5.0f), data.receivedGesture.screenPoint, 0.1, TEST_LOCATION); + + // Rotate actor again and render + actor.SetOrientation(Dali::Degree(180.0f), Vector3::ZAXIS); + application.SendNotification(); + application.Render(); + + // Do tap, should still receive event + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(5.0f, 5.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(5.0f, 5.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTaps, TEST_LOCATION); + DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION); + DALI_TEST_EQUALS( Vector2(5.0f, 5.0f), data.receivedGesture.screenPoint, 0.1, TEST_LOCATION); + + // Rotate actor again and render + actor.SetOrientation(Dali::Degree(90.0f), Vector3::YAXIS); + application.SendNotification(); + application.Render(); + + // Do tap, inside the actor's area (area if it is not rotated), Should not receive the event + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(70.0f, 70.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(70.0f, 70.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureSignalReceptionChildHit(void) +{ + TestApplication application; + + Actor parent = Actor::New(); + parent.SetSize(100.0f, 100.0f); + parent.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(parent); + + // Set child to completely cover parent. + // Change rotation of child to be different from parent so that we can check if our local coordinate + // conversion of the parent actor is correct. + Actor child = Actor::New(); + child.SetSize(100.0f, 100.0f); + child.SetAnchorPoint(AnchorPoint::CENTER); + child.SetParentOrigin(ParentOrigin::CENTER); + child.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS); + parent.Add(child); + + TouchEventFunctor touchFunctor; + child.TouchedSignal().Connect(&application, touchFunctor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(parent); + detector.DetectedSignal().Connect(&application, functor); + + // Do tap - hits child area but parent should still receive it + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 50.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 50.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, parent == data.tappedActor, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(50.0f, 50.0f), data.receivedGesture.screenPoint, 0.01f, TEST_LOCATION); + + // Attach child and generate same touch points + // (Also proves that you can detach and then re-attach another actor) + detector.Attach(child); + detector.Detach(parent); + + // Do an entire tap, only check finished value + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(51.0f, 51.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(51.0f, 51.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, child == data.tappedActor, TEST_LOCATION); + DALI_TEST_EQUALS(Vector2(51.0f, 51.0f), data.receivedGesture.screenPoint, 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureSignalReceptionAttachDetachMany(void) +{ + TestApplication application; + + Actor first = Actor::New(); + first.SetSize(100.0f, 100.0f); + first.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(first); + + Actor second = Actor::New(); + second.SetSize(100.0f, 100.0f); + second.SetX(100.0f); + second.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(second); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(first); + detector.Attach(second); + detector.DetectedSignal().Connect(&application, functor); + + // Tap within second actor's area + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(120.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(120.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, second == data.tappedActor, TEST_LOCATION); + + // Tap within first actor's area + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(20.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, first == data.tappedActor, TEST_LOCATION); + + // Detach the second actor + detector.Detach(second); + + // second actor shouldn't receive event + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(120.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(120.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // first actor should continue receiving event + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(20.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureSignalReceptionActorBecomesUntouchable(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + // Tap in actor's area + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + + // Actor become invisible - actor should not receive the next pan + actor.SetVisible(false); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Tap in the same area, shouldn't receive event + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureSignalReceptionMultipleGestureDetectors(void) +{ + TestApplication application; + Dali::TestGestureManager& gestureManager = application.GetGestureManager(); + + Actor first = Actor::New(); + first.SetSize(100.0f, 100.0f); + first.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(first); + + Actor second = Actor::New(); + second.SetSize(100.0f, 100.0f); + second.SetAnchorPoint(AnchorPoint::TOP_LEFT); + second.SetX(100.0f); + first.Add(second); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + TapGestureDetector firstDetector = TapGestureDetector::New(); + firstDetector.Attach(first); + firstDetector.DetectedSignal().Connect(&application, functor); + + // secondDetector is scoped + { + // Reset gestureManager statistics + gestureManager.Initialize(); + + TapGestureDetector secondDetector = TapGestureDetector::New( 2 ); + secondDetector.Attach(second); + secondDetector.DetectedSignal().Connect(&application, functor); + + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + + // Tap within second actor's area + application.ProcessEvent(GenerateTap(Gesture::Possible, 2u, 1u, Vector2(150.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 2u, 1u, Vector2(150.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, second == data.tappedActor, TEST_LOCATION); + + // Tap continues as single touch gesture - we should not receive any gesture + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(150.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(150.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Single touch tap starts - first actor should be panned + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, first == data.tappedActor, TEST_LOCATION); + + // Pan changes to double-touch - we shouldn't receive event + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Possible, 2u, 2u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 2u, 2u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Reset gesture manager statistics + gestureManager.Initialize(); + } + + // secondDetector has now been deleted. Gesture detection should have been updated only + DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION); + DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureSignalReceptionMultipleDetectorsOnActor(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to one detector + SignalData firstData; + GestureReceivedFunctor firstFunctor(firstData); + TapGestureDetector firstDetector = TapGestureDetector::New(); + firstDetector.Attach(actor); + firstDetector.DetectedSignal().Connect(&application, firstFunctor); + + // Attach actor to another detector + SignalData secondData; + GestureReceivedFunctor secondFunctor(secondData); + TapGestureDetector secondDetector = TapGestureDetector::New(); + secondDetector.Attach(actor); + secondDetector.DetectedSignal().Connect(&application, secondFunctor); + + // Tap in actor's area - both detector's functors should be called + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION); + DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureSignalReceptionDifferentPossible(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Gesture possible in actor's area. + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Move actor somewhere else + actor.SetPosition( 100.0f, 100.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit Started event, we should not receive the tap. + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Tap possible in empty area. + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Move actor in to the tap position. + actor.SetPosition( 0.0f, 0.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit Started event, we should not receive the tap. + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Normal tap in actor's area for completeness. + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureEmitIncorrectStateClear(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Try a Clear state + try + { + application.ProcessEvent(GenerateTap(Gesture::Clear, 1u, 1u, Vector2(50.0f, 10.0f))); + tet_result(TET_FAIL); + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_ASSERT( e, "false", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTapGestureEmitIncorrectStateContinuing(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Try a Continuing state + try + { + application.ProcessEvent(GenerateTap(Gesture::Continuing, 1u, 1u, Vector2(50.0f, 10.0f))); + tet_result(TET_FAIL); + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_ASSERT( e, "false", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTapGestureEmitIncorrectStateFinished(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Try a Finished state + try + { + application.ProcessEvent(GenerateTap(Gesture::Finished, 1u, 1u, Vector2(50.0f, 10.0f))); + tet_result(TET_FAIL); + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_ASSERT( e, "false", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTapGestureActorUnstaged(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + UnstageActorFunctor functor( data ); + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Tap in Actor's area, actor removed in signal handler, should be handled gracefully. + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + tet_result( TET_PASS ); // If we get here, then the actor removal on signal handler was handled gracefully. + END_TEST; +} + +int UtcDaliTapGestureRepeatedState(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Emit two possibles + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Send a couple of Started states, only first one should be received. + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + + // Send a couple of cancelled states, no reception + application.ProcessEvent(GenerateTap(Gesture::Cancelled, 1u, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Cancelled, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGesturePossibleCancelled(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Emit a possible and then a cancelled, no reception + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Cancelled, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureDetectorRemovedWhilePossible(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Emit a possible + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + + // Detach actor and send a Started state, no signal. + detector.DetachAll(); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureActorRemovedWhilePossible(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Emit a possible + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + + // Remove, render and delete actor + Stage::GetCurrent().Remove(actor); + application.SendNotification(); + application.Render(); + actor.Reset(); + + // Send a Started state, no signal. + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureSystemOverlay(void) +{ + TestApplication application; + Dali::Integration::Core& core = application.GetCore(); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + SignalData data; + GestureReceivedFunctor functor(data); + + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect(&application, functor); + + Vector2 screenCoords( 50.0f, 50.0f ); + + // Do a tap inside actor's area + application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, screenCoords ) ); + application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, screenCoords ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliTapGestureBehindTouchableSystemOverlay(void) +{ + TestApplication application; + Dali::Integration::Core& core = application.GetCore(); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + // SystemOverlay actor + Actor systemOverlayActor = Actor::New(); + systemOverlayActor.SetSize(100.0f, 100.0f); + systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add(systemOverlayActor); + + // Stage actor + Actor stageActor = Actor::New(); + stageActor.SetSize(100.0f, 100.0f); + stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(stageActor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set system-overlay actor to touchable + TouchEventData touchData; + TouchEventDataFunctor touchFunctor( touchData ); + systemOverlayActor.TouchedSignal().Connect(&application, touchFunctor); + + // Set stage actor to receive the gesture + SignalData data; + GestureReceivedFunctor functor(data); + + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(stageActor); + detector.DetectedSignal().Connect(&application, functor); + + Vector2 screenCoords( 50.0f, 50.0f ); + + // Do a tap inside both actors' area + application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, screenCoords ) ); + application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, screenCoords ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION ); + + data.Reset(); + touchData.Reset(); + + // Do touch in the same area + application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoords ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliTapGestureTouchBehindGesturedSystemOverlay(void) +{ + TestApplication application; + Dali::Integration::Core& core = application.GetCore(); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + // SystemOverlay actor + Actor systemOverlayActor = Actor::New(); + systemOverlayActor.SetSize(100.0f, 100.0f); + systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add(systemOverlayActor); + + // Stage actor + Actor stageActor = Actor::New(); + stageActor.SetSize(100.0f, 100.0f); + stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(stageActor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Set stage actor to touchable + TouchEventData touchData; + TouchEventDataFunctor touchFunctor( touchData ); + stageActor.TouchedSignal().Connect(&application, touchFunctor); + + // Set system-overlay actor to have the gesture + SignalData data; + GestureReceivedFunctor functor(data); + + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(systemOverlayActor); + detector.DetectedSignal().Connect(&application, functor); + + Vector2 screenCoords( 50.0f, 50.0f ); + + // Do a tap inside both actors' area + application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, screenCoords ) ); + application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, screenCoords ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION ); + + data.Reset(); + touchData.Reset(); + + // Do touch in the same area + application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoords ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliTapGestureLayerConsumesTouch(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Add a detector + SignalData data; + GestureReceivedFunctor functor(data); + TapGestureDetector detector = TapGestureDetector::New(); + detector.Attach(actor); + detector.DetectedSignal().Connect( &application, functor ); + + // Add a layer to overlap the actor + Layer layer = Layer::New(); + layer.SetSize(100.0f, 100.0f); + layer.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add( layer ); + layer.RaiseToTop(); + + // Render and notify + application.SendNotification(); + application.Render(); + + Vector2 screenCoords( 50.0f, 50.0f ); + + // Emit signals, should receive + application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, screenCoords ) ); + application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, screenCoords ) ); + DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION); + data.Reset(); + + // Set layer to consume all touch + layer.SetTouchConsumed( true ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit the same signals again, should not receive + application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, screenCoords ) ); + application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, screenCoords ) ); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-TouchEventCombiner.cpp b/automated-tests/src/dali/utc-Dali-TouchEventCombiner.cpp new file mode 100644 index 0000000..fb1eafa --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-TouchEventCombiner.cpp @@ -0,0 +1,902 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include +#include + +using namespace Dali; +using namespace Dali::Integration; + +void utc_dali_touch_event_combiner_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_touch_event_combiner_cleanup(void) +{ + test_return_value = TET_PASS; +} + + +int UtcDaliTouchEventCombinerConstructors(void) +{ + TouchEventCombiner combiner1; + DALI_TEST_EQUALS( combiner1.GetMinimumMotionTimeThreshold(), static_cast(1), TEST_LOCATION ); + DALI_TEST_EQUALS( combiner1.GetMinimumMotionDistanceThreshold(), Vector2( 1.0f, 1.0f ), TEST_LOCATION ); + + TouchEventCombiner combiner2( 10, 20.0f, 31.0f ); + DALI_TEST_EQUALS( combiner2.GetMinimumMotionTimeThreshold(), static_cast(10), TEST_LOCATION ); + DALI_TEST_EQUALS( combiner2.GetMinimumMotionDistanceThreshold(), Vector2( 20.0f, 31.0f ), TEST_LOCATION ); + + TouchEventCombiner combiner3( 10, Vector2( 20.0f, 31.0f ) ); + DALI_TEST_EQUALS( combiner3.GetMinimumMotionTimeThreshold(), static_cast(10), TEST_LOCATION ); + DALI_TEST_EQUALS( combiner3.GetMinimumMotionDistanceThreshold(), Vector2( 20.0f, 31.0f ), TEST_LOCATION ); + + // Boundary Checks + + TouchEventCombiner combiner4( 10, 0.0f, 0.0f ); + DALI_TEST_EQUALS( combiner4.GetMinimumMotionDistanceThreshold(), Vector2( 0.0f, 0.0f ), TEST_LOCATION ); + + TouchEventCombiner combiner5( 10, Vector2( 0.0f, 0.0f ) ); + DALI_TEST_EQUALS( combiner5.GetMinimumMotionDistanceThreshold(), Vector2( 0.0f, 0.0f ), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliTouchEventCombinerConstructorsNegative(void) +{ + try + { + TouchEventCombiner combiner( 10, -20.0f, 31.0f ); + tet_printf( "%s: Should have asserted\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + catch ( Dali::DaliException& e ) + { + tet_result( TET_PASS ); + } + + try + { + TouchEventCombiner combiner( 10, 20.0f, -31.0f ); + tet_printf( "%s: Should have asserted\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + catch ( Dali::DaliException& e ) + { + tet_result( TET_PASS ); + } + + try + { + TouchEventCombiner combiner( 10, Vector2( -20.0f, 31.0f ) ); + tet_printf( "%s: Should have asserted\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + catch ( Dali::DaliException& e ) + { + tet_result( TET_PASS ); + } + + try + { + TouchEventCombiner combiner( 10, Vector2( 20.0f, -31.0f ) ); + tet_printf( "%s: Should have asserted\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + catch ( Dali::DaliException& e ) + { + tet_result( TET_PASS ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerSettersAndGetters(void) +{ + TouchEventCombiner combiner; + unsigned long time( 10u ); + Vector2 distance( 40.0f, 30.0f ); + + DALI_TEST_CHECK( combiner.GetMinimumMotionTimeThreshold() != time ); + DALI_TEST_CHECK( combiner.GetMinimumMotionDistanceThreshold() != distance ); + + combiner.SetMinimumMotionTimeThreshold( time ); + DALI_TEST_EQUALS( combiner.GetMinimumMotionTimeThreshold(), time, TEST_LOCATION ); + + combiner.SetMinimumMotionDistanceThreshold( distance.x ); + DALI_TEST_EQUALS( combiner.GetMinimumMotionDistanceThreshold(), Vector2( distance.x, distance.x ), TEST_LOCATION ); + + distance.x = 20.0f; + distance.y = 50.0f; + combiner.SetMinimumMotionDistanceThreshold( distance.x, distance.y ); + DALI_TEST_EQUALS( combiner.GetMinimumMotionDistanceThreshold(), distance, TEST_LOCATION ); + + distance.x = 100.0f; + distance.y = 20.0f; + combiner.SetMinimumMotionDistanceThreshold( distance ); + DALI_TEST_EQUALS( combiner.GetMinimumMotionDistanceThreshold(), distance, TEST_LOCATION ); + + // Boundary Checks + + combiner.SetMinimumMotionDistanceThreshold( 0.0f ); + DALI_TEST_EQUALS( combiner.GetMinimumMotionDistanceThreshold(), Vector2::ZERO, TEST_LOCATION ); + + combiner.SetMinimumMotionDistanceThreshold( 0.0f, 0.0f ); + DALI_TEST_EQUALS( combiner.GetMinimumMotionDistanceThreshold(), Vector2::ZERO, TEST_LOCATION ); + + combiner.SetMinimumMotionDistanceThreshold( Vector2::ZERO ); + DALI_TEST_EQUALS( combiner.GetMinimumMotionDistanceThreshold(), Vector2::ZERO, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliTouchEventCombinerSettersNegative(void) +{ + TouchEventCombiner combiner; + + try + { + combiner.SetMinimumMotionDistanceThreshold( -100.0f ); + tet_printf( "%s: Should have asserted\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + catch ( Dali::DaliException& e ) + { + tet_result( TET_PASS ); + } + + try + { + combiner.SetMinimumMotionDistanceThreshold( -100.0f, 20.0f ); + tet_printf( "%s: Should have asserted\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + catch ( Dali::DaliException& e ) + { + tet_result( TET_PASS ); + } + + try + { + combiner.SetMinimumMotionDistanceThreshold( 100.0f, -20.0f ); + tet_printf( "%s: Should have asserted\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + catch ( Dali::DaliException& e ) + { + tet_result( TET_PASS ); + } + + try + { + combiner.SetMinimumMotionDistanceThreshold( Vector2( -100.0f, 20.0f ) ); + tet_printf( "%s: Should have asserted\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + catch ( Dali::DaliException& e ) + { + tet_result( TET_PASS ); + } + + try + { + combiner.SetMinimumMotionDistanceThreshold( Vector2( 100.0f, -20.0f ) ); + tet_printf( "%s: Should have asserted\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + catch ( Dali::DaliException& e ) + { + tet_result( TET_PASS ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerSingleTouchNormal(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + + // Down event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Motion in X direction + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Motion, 101.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Motion in Y direction + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Motion, 101.0f, 101.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + // Motion event, but same time + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + } + + time++; + + // Motion event, both X and Y movement + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Motion event, no movement + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + } + + // Up event, no time diff, no movement + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Up, 102.0f, 102.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerSingleTouchMotionWithoutDown(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + + // Motion event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Motion, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].state, TouchPoint::Started, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Motion event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerSingleTouchMotionFollowedByDown(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + + // Motion event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Motion, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].state, TouchPoint::Started, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Motion event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Motion event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Motion, 103.0f, 103.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Down event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Down, 103.0f, 103.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchBoth, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].state, TouchPoint::Finished, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerSingleTouchTwoDowns(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + + // Down event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Another down with the same ID + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerSingleTouchUpWithoutDown(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + + // Up event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + } + + time++; + + // Up event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Up, 102.0f, 102.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerSingleTouchTwoUps(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + + // Down event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Up event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Another up event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerSingleTouchUpWithDifferentId(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + + // Down event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Up event with different ID + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 2, TouchPoint::Up, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + } + + time++; + + // Up event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerSingleTouchMotionWithDifferentId(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + + // Down event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Motion event with different ID + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 2, TouchPoint::Motion, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].state, TouchPoint::Started, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Motion event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerMultiTouchNormal(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + + // 1st point down + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // 2nd point down + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 2, TouchPoint::Down, 200.0f, 200.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 2u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[1].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, TouchPoint::Stationary, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[1].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[1].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // 1st point motion + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Motion, 101.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 2u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[1].state, TouchPoint::Stationary, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + // 2nd point motion, no time diff + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 2, TouchPoint::Motion, 200.0f, 200.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + } + + time++; + + // 2nd point motion + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 2, TouchPoint::Motion, 201.0f, 201.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 2u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[1].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, TouchPoint::Stationary, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[1].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[1].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // 1st point up + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Up, 101.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 2u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[1].state, TouchPoint::Stationary, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // 2nd point motion + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 2, TouchPoint::Motion, 202.0f, 202.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // 2nd point up + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 2, TouchPoint::Up, 202.0f, 202.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerSeveralPoints(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + unsigned int const maximum( 200u ); + + // Several downs + for ( unsigned int pointCount = 1u; pointCount < maximum; ++pointCount ) + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( pointCount, TouchPoint::Down, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time++, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), pointCount, TEST_LOCATION ); + } + + // Several Ups + for ( unsigned int pointCount = maximum - 1; pointCount > 0; --pointCount ) + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( pointCount, TouchPoint::Up, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time++, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), pointCount, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerReset(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + + // Down event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Reset combiner, no more events should be sent to core. + combiner.Reset(); + + // Up event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerSingleTouchInterrupted(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + + // Down event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION ); + } + + time++; + + // Interrupted event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Interrupted, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchBoth, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION ); + } + + // Send up, should not be able to send as combiner has been reset. + // Up event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerMultiTouchInterrupted(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + unsigned int const maximum( 200u ); + + // Several downs + for ( unsigned int pointCount = 1u; pointCount < maximum; ++pointCount ) + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( pointCount, TouchPoint::Down, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), pointCount, TEST_LOCATION ); + } + + // Interrupted event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Interrupted, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchBoth, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION ); + DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION ); + } + + // Send up, should not be able to send as combiner has been reset. + // Up event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchEventCombinerInvalidState(void) +{ + TouchEventCombiner combiner; + unsigned long time( 0u ); + + // Stationary event + { + Integration::TouchEvent touchEvent; + Integration::HoverEvent hoverEvent; + TouchPoint point( 1, TouchPoint::Stationary, 100.0f, 100.0f ); + + DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION ); + } + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp b/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp new file mode 100644 index 0000000..f38084b --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp @@ -0,0 +1,1368 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include +#include +#include + +using namespace Dali; + +void utc_dali_touch_processing_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_touch_processing_cleanup(void) +{ + test_return_value = TET_PASS; +} + +/////////////////////////////////////////////////////////////////////////////// + +namespace +{ + +// Stores data that is populated in the callback and will be read by the TET cases +struct SignalData +{ + SignalData() + : functorCalled( false ), + touchEvent(), + touchedActor() + { + } + + void Reset() + { + functorCalled = false; + + touchEvent.time = 0u; + touchEvent.points.clear(); + + touchedActor.Reset(); + } + + bool functorCalled; + TouchEvent touchEvent; + Actor touchedActor; +}; + +// Functor that sets the data when called +struct TouchEventFunctor +{ + /** + * Constructor. + * @param[in] data Reference to the data to store callback information. + * @param[in] returnValue What the functor should return. + */ + TouchEventFunctor( SignalData& data, bool returnValue = true ) + : signalData( data ), + returnValue( returnValue ) + { + } + + bool operator()( Actor actor, const TouchEvent& touchEvent ) + { + signalData.functorCalled = true; + signalData.touchedActor = actor; + signalData.touchEvent = touchEvent; + + return returnValue; + } + + SignalData& signalData; + bool returnValue; +}; + +// Functor that removes the actor when called. +struct RemoveActorFunctor : public TouchEventFunctor +{ + /** + * Constructor. + * @param[in] data Reference to the data to store callback information. + * @param[in] returnValue What the functor should return. + */ + RemoveActorFunctor( SignalData& data, bool returnValue = true ) + : TouchEventFunctor( data, returnValue ) + { + } + + bool operator()( Actor actor, const TouchEvent& touchEvent ) + { + Actor parent( actor.GetParent() ); + if ( parent ) + { + parent.Remove( actor ); + } + + return TouchEventFunctor::operator()( actor, touchEvent ); + } +}; + +Integration::TouchEvent GenerateSingleTouch( TouchPoint::State state, Vector2 screenPosition ) +{ + Integration::TouchEvent touchEvent; + touchEvent.points.push_back( TouchPoint ( 0, state, screenPosition.x, screenPosition.y ) ); + return touchEvent; +} + +} // anon namespace + +/////////////////////////////////////////////////////////////////////////////// + +int UtcDaliTouchNormalProcessing(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data ); + actor.TouchedSignal().Connect( &application, functor ); + + Vector2 screenCoordinates( 10.0f, 10.0f ); + Vector2 localCoordinates; + actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) ); + const TouchPoint *point1 = &data.touchEvent.GetPoint(0); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, data.touchEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, point1->state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, point1->screen, TEST_LOCATION ); + DALI_TEST_EQUALS( localCoordinates, point1->local, 0.1f, TEST_LOCATION ); + data.Reset(); + + // Emit a motion signal + screenCoordinates.x = screenCoordinates.y = 11.0f; + actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, screenCoordinates ) ); + const TouchPoint *point2 = &data.touchEvent.GetPoint(0); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, data.touchEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, point2->state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, point2->screen, TEST_LOCATION ); + DALI_TEST_EQUALS( localCoordinates, point2->local, 0.1f, TEST_LOCATION ); + data.Reset(); + + // Emit an up signal + screenCoordinates.x = screenCoordinates.y = 12.0f; + actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Up, screenCoordinates ) ); + const TouchPoint *point3 = &data.touchEvent.GetPoint(0); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, data.touchEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Up, point3->state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, point3->screen, TEST_LOCATION ); + DALI_TEST_EQUALS( localCoordinates, point3->local, 0.1f, TEST_LOCATION ); + data.Reset(); + + // Emit a down signal where the actor is not present + screenCoordinates.x = screenCoordinates.y = 200.0f; + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliTouchOutsideCameraNearFarPlanes(void) +{ + TestApplication application; + + Stage stage = Stage::GetCurrent(); + Vector2 stageSize = stage.GetSize(); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::CENTER); + actor.SetParentOrigin(ParentOrigin::CENTER); + stage.Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Get the camera's near and far planes + RenderTaskList taskList = stage.GetRenderTaskList(); + Dali::RenderTask task = taskList.GetTask(0); + CameraActor camera = task.GetCameraActor(); + float nearPlane = camera.GetNearClippingPlane(); + float farPlane = camera.GetFarClippingPlane(); + + // Calculate the current distance of the actor from the camera + float tanHalfFov = tanf(camera.GetFieldOfView() * 0.5f); + float distance = (stageSize.y * 0.5f) / tanHalfFov; + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data ); + actor.TouchedSignal().Connect( &application, functor ); + + Vector2 screenCoordinates( stageSize.x * 0.5f, stageSize.y * 0.5f ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit a down signal where actor is just at the camera's near plane + actor.SetZ(distance - nearPlane); + + // Render and notify + application.SendNotification(); + application.Render(); + + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit a down signal where actor is closer than the camera's near plane + actor.SetZ((distance - nearPlane) + 1.0f); + + // Render and notify + application.SendNotification(); + application.Render(); + + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit a down signal where actor is just at the camera's far plane + actor.SetZ(distance - farPlane); + + // Render and notify + application.SendNotification(); + application.Render(); + + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit a down signal where actor is further than the camera's far plane + actor.SetZ((distance - farPlane) - 1.0f); + + // Render and notify + application.SendNotification(); + application.Render(); + + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliTouchEmitEmpty(void) +{ + TestApplication application; + + try + { + // Emit an empty TouchEvent + Integration::TouchEvent event; + application.ProcessEvent( event ); + tet_result( TET_FAIL ); + } + catch ( Dali::DaliException& e ) + { + DALI_TEST_ASSERT( e, "!event.points.empty()", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliTouchInterrupted(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data ); + actor.TouchedSignal().Connect( &application, functor ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + // Emit an interrupted signal, we should be signalled regardless of whether there is a hit or not. + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f /* Outside actor */ ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + // Emit another interrupted signal, our signal handler should not be called. + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliTouchParentConsumer(void) +{ + TestApplication application; + Actor rootActor( Stage::GetCurrent().GetRootLayer() ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data, false ); + actor.TouchedSignal().Connect( &application, functor ); + + // Connect to root actor's touched signal + SignalData rootData; + TouchEventFunctor rootFunctor( rootData ); // Consumes signal + rootActor.TouchedSignal().Connect( &application, rootFunctor ); + + Vector2 screenCoordinates( 10.0f, 10.0f ); + Vector2 actorCoordinates, rootCoordinates; + actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, data.touchEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, rootData.touchEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, data.touchEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, rootData.touchEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( actorCoordinates, data.touchEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_EQUALS( rootCoordinates, rootData.touchEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit a motion signal + screenCoordinates.x = screenCoordinates.y = 11.0f; + actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, data.touchEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, rootData.touchEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, data.touchEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, rootData.touchEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( actorCoordinates, data.touchEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_EQUALS( rootCoordinates, rootData.touchEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit an up signal + screenCoordinates.x = screenCoordinates.y = 12.0f; + actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Up, screenCoordinates ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, data.touchEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, rootData.touchEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Up, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Up, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, data.touchEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, rootData.touchEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( actorCoordinates, data.touchEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_EQUALS( rootCoordinates, rootData.touchEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit a down signal where the actor is not present, will hit the root actor though + screenCoordinates.x = screenCoordinates.y = 200.0f; + rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, rootData.touchEvent.GetPointCount(), TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( screenCoordinates, rootData.touchEvent.points[0].screen, TEST_LOCATION ); + DALI_TEST_EQUALS( rootCoordinates, rootData.touchEvent.points[0].local, 0.1f, TEST_LOCATION ); + DALI_TEST_CHECK( rootActor == rootData.touchEvent.points[0].hitActor ); + END_TEST; +} + +int UtcDaliTouchInterruptedParentConsumer(void) +{ + TestApplication application; + Actor rootActor( Stage::GetCurrent().GetRootLayer() ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data, false ); + actor.TouchedSignal().Connect( &application, functor ); + + // Connect to root actor's touched signal + SignalData rootData; + TouchEventFunctor rootFunctor( rootData ); // Consumes signal + rootActor.TouchedSignal().Connect( &application, rootFunctor ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit an interrupted signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit another down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + rootData.Reset(); + + // Remove actor from Stage + Stage::GetCurrent().Remove( actor ); + data.Reset(); + rootData.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit an interrupted signal, only root actor's signal should be called. + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f /* Outside actor */ ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( rootActor == rootData.touchEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit another interrupted state, none of the signal's should be called. + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, rootData.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliTouchLeave(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data ); + actor.TouchedSignal().Connect( &application, functor ); + + // Set actor to require leave events + actor.SetLeaveRequired( true ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + // Emit a motion signal outside of actor, should be signalled with a Leave + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Leave, data.touchEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + // Another motion outside of actor, no signalling + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 201.0f, 201.0f )) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Another motion event inside actor, signalled with motion + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 10.0f, 10.0f )) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, data.touchEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + // We do not want to listen to leave events anymore + actor.SetLeaveRequired( false ); + + // Another motion event outside of actor, no signalling + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliTouchLeaveParentConsumer(void) +{ + TestApplication application; + Actor rootActor( Stage::GetCurrent().GetRootLayer() ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data, false ); + actor.TouchedSignal().Connect( &application, functor ); + + // Connect to root actor's touched signal + SignalData rootData; + TouchEventFunctor rootFunctor( rootData ); // Consumes signal + rootActor.TouchedSignal().Connect( &application, rootFunctor ); + + // Set actor to require leave events + actor.SetLeaveRequired( true ); + rootActor.SetLeaveRequired( true ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Emit a motion signal outside of actor, should be signalled with a Leave + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Leave, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Leave, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Another motion outside of actor, only rootActor signalled + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 201.0f, 201.0f )) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( rootActor == rootData.touchEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Another motion event inside actor, signalled with motion + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 10.0f, 10.0f )) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Motion, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // We do not want to listen to leave events of actor anymore + actor.SetLeaveRequired( false ); + + // Another motion event outside of root actor, only root signalled + Vector2 stageSize( Stage::GetCurrent().GetSize() ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( stageSize.width + 10.0f, stageSize.height + 10.0f )) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Leave, rootData.touchEvent.points[0].state, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliTouchActorBecomesInsensitive(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data ); + actor.TouchedSignal().Connect( &application, functor ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + // Change actor to insensitive + actor.SetSensitive( false ); + + // Emit a motion signal, signalled with an interrupted + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliTouchActorBecomesInsensitiveParentConsumer(void) +{ + TestApplication application; + Actor rootActor( Stage::GetCurrent().GetRootLayer() ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data, false ); + actor.TouchedSignal().Connect( &application, functor ); + + // Connect to root actor's touched signal + SignalData rootData; + TouchEventFunctor rootFunctor( rootData ); // Consumes signal + rootActor.TouchedSignal().Connect( &application, rootFunctor ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor ); + data.Reset(); + rootData.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Make root actor insensitive + rootActor.SetSensitive( false ); + + // Emit a motion signal, signalled with an interrupted (should get interrupted even if within root actor) + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.touchEvent.points[0].state, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliTouchMultipleLayers(void) +{ + TestApplication application; + Actor rootActor( Stage::GetCurrent().GetRootLayer() ); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data ); + + Layer layer1 ( Layer::New() ); + layer1.SetSize(100.0f, 100.0f); + layer1.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add( layer1 ); + + Actor actor1 ( Actor::New() ); + actor1.SetSize( 100.0f, 100.0f ); + actor1.SetAnchorPoint(AnchorPoint::TOP_LEFT); + actor1.SetZ( 1.0f ); // Should hit actor1 in this layer + layer1.Add( actor1 ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to layer1 and actor1 + layer1.TouchedSignal().Connect( &application, functor ); + actor1.TouchedSignal().Connect( &application, functor ); + + // Hit in hittable area, actor1 should be hit + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.touchedActor == actor1 ); + data.Reset(); + + // Make layer1 insensitive, nothing should be hit + layer1.SetSensitive( false ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Make layer1 sensitive again, again actor1 will be hit + layer1.SetSensitive( true ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.touchedActor == actor1 ); + data.Reset(); + + // Make rootActor insensitive, nothing should be hit + rootActor.SetSensitive( false ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Make rootActor sensitive + rootActor.SetSensitive( true ); + + // Add another layer + Layer layer2 ( Layer::New() ); + layer2.SetSize(100.0f, 100.0f ); + layer2.SetAnchorPoint(AnchorPoint::TOP_LEFT); + layer2.SetZ( 10.0f ); // Should hit layer2 in this layer rather than actor2 + Stage::GetCurrent().Add( layer2 ); + + Actor actor2 ( Actor::New() ); + actor2.SetSize(100.0f, 100.0f); + actor2.SetAnchorPoint(AnchorPoint::TOP_LEFT); + layer2.Add( actor2 ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to layer2 and actor2 + layer2.TouchedSignal().Connect( &application, functor ); + actor2.TouchedSignal().Connect( &application, functor ); + + // Emit an event, should hit layer2 + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + //DALI_TEST_CHECK( data.touchedActor == layer2 ); // TODO: Uncomment this after removing renderable hack! + data.Reset(); + + // Make layer2 insensitive, should hit actor1 + layer2.SetSensitive( false ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.touchedActor == actor1 ); + data.Reset(); + + // Make layer2 sensitive again, should hit layer2 + layer2.SetSensitive( true ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + //DALI_TEST_CHECK( data.touchedActor == layer2 ); // TODO: Uncomment this after removing renderable hack! + data.Reset(); + + // Make layer2 invisible, render and notify + layer2.SetVisible( false ); + application.SendNotification(); + application.Render(); + + // Should hit actor1 + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( data.touchedActor == actor1 ); + data.Reset(); + + // Make rootActor invisible, render and notify + rootActor.SetVisible( false ); + application.SendNotification(); + application.Render(); + + // Should not hit anything + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliTouchMultipleRenderTasks(void) +{ + TestApplication application; + Stage stage ( Stage::GetCurrent() ); + Vector2 stageSize ( stage.GetSize() ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stage.Add(actor); + + // Create render task + Viewport viewport( stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f ); + RenderTask renderTask ( Stage::GetCurrent().GetRenderTaskList().CreateTask() ); + renderTask.SetViewport( viewport ); + renderTask.SetInputEnabled( true ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data ); + actor.TouchedSignal().Connect( &application, functor ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Ensure renderTask actor can be hit too. + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Disable input on renderTask, should not be hittable + renderTask.SetInputEnabled( false ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliTouchMultipleRenderTasksWithChildLayer(void) +{ + TestApplication application; + Stage stage ( Stage::GetCurrent() ); + Vector2 stageSize ( stage.GetSize() ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stage.Add(actor); + + Layer layer = Layer::New(); + layer.SetSize(100.0f, 100.0f); + layer.SetAnchorPoint(AnchorPoint::TOP_LEFT); + actor.Add(layer); + + // Create render task + Viewport viewport( stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f ); + RenderTask renderTask ( Stage::GetCurrent().GetRenderTaskList().CreateTask() ); + renderTask.SetViewport( viewport ); + renderTask.SetInputEnabled( true ); + renderTask.SetSourceActor( actor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to layer's touched signal + SignalData data; + TouchEventFunctor functor( data ); + actor.TouchedSignal().Connect( &application, functor ); + layer.TouchedSignal().Connect( &application, functor ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Ensure renderTask actor can be hit too. + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Disable input on renderTask, should not be hittable + renderTask.SetInputEnabled( false ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliTouchOffscreenRenderTasks(void) +{ + TestApplication application; + Stage stage ( Stage::GetCurrent() ); + Vector2 stageSize ( stage.GetSize() ); + + // FrameBufferImage for offscreen RenderTask + FrameBufferImage frameBufferImage( FrameBufferImage::New( stageSize.width, stageSize.height, Pixel::RGBA8888 ) ); + + // Create an image actor to display the FrameBufferImage + ImageActor imageActor ( ImageActor::New( frameBufferImage ) ); + imageActor.SetParentOrigin(ParentOrigin::CENTER); + imageActor.SetSize( stageSize.x, stageSize.y ); + imageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME + stage.Add( imageActor ); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stage.Add( actor ); + application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); // Ensure framebuffer connects + + stage.GetRenderTaskList().GetTask( 0u ).SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION ); + + // Create a RenderTask + RenderTask renderTask = stage.GetRenderTaskList().CreateTask(); + renderTask.SetSourceActor( actor ); + renderTask.SetTargetFrameBuffer( frameBufferImage ); + renderTask.SetInputEnabled( true ); + + // Create another RenderTask + RenderTask renderTask2( stage.GetRenderTaskList().CreateTask() ); + renderTask2.SetInputEnabled( true ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data ); + actor.TouchedSignal().Connect( &application, functor ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} + +int UtcDaliTouchMultipleRenderableActors(void) +{ + TestApplication application; + Stage stage ( Stage::GetCurrent() ); + Vector2 stageSize ( stage.GetSize() ); + + ImageActor parent = ImageActor::New(); + parent.SetSize(100.0f, 100.0f); + parent.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stage.Add(parent); + + ImageActor actor = ImageActor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + actor.SetSortModifier( 1.0f ); + parent.Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to layer's touched signal + SignalData data; + TouchEventFunctor functor( data ); + parent.TouchedSignal().Connect( &application, functor ); + actor.TouchedSignal().Connect( &application, functor ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.touchedActor ); + END_TEST; +} + +int UtcDaliTouchActorRemovedInSignal(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + RemoveActorFunctor functor( data ); + actor.TouchedSignal().Connect( &application, functor ); + + // Register for leave events + actor.SetLeaveRequired( true ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Re-add, render and notify + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(); + + // Emit another signal outside of actor's area, should not get anything as the scene has changed. + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit another signal outside of actor's area, should not get anything as the scene has changed. + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Re-add actor back to stage, render and notify + Stage::GetCurrent().Add(actor); + application.SendNotification(); + application.Render(); + + // Emit another down event + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Completely delete the actor + actor.Reset(); + + // Emit event, should not crash and should not receive an event. + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliTouchActorSignalNotConsumed(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data, false ); + actor.TouchedSignal().Connect( &application, functor ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliTouchSystemOverlayActor(void) +{ + TestApplication application; + Dali::Integration::Core& core( application.GetCore() ); + Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() ); + systemOverlay.GetOverlayRenderTasks().CreateTask(); + + // Create an actor and add it to the system overlay. + Actor systemActor = Actor::New(); + systemActor.SetSize(100.0f, 100.0f); + systemActor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + systemOverlay.Add( systemActor ); + + // Create an actor and add it to the stage as per normal, same position and size as systemActor + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Connect to the touch signals. + SignalData data; + TouchEventFunctor functor( data ); + systemActor.TouchedSignal().Connect( &application, functor ); + actor.TouchedSignal().Connect( &application, functor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit a down signal, the system overlay is drawn last so is at the top, should hit the systemActor. + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( systemActor == data.touchedActor ); + END_TEST; +} + +int UtcDaliTouchLayerConsumesTouch(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data ); + actor.TouchedSignal().Connect( &application, functor ); + + // Add a layer to overlap the actor + Layer layer = Layer::New(); + layer.SetSize(100.0f, 100.0f); + layer.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add( layer ); + layer.RaiseToTop(); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit a few touch signals + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Up, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Set layer to consume all touch + layer.SetTouchConsumed( true ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit the same signals again, should not receive + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Up, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION); + data.Reset(); + + END_TEST; +} + +int UtcDaliTouchLeaveActorReadded(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stage.Add(actor); + + // Set actor to receive touch-events + actor.SetLeaveRequired( true ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data ); + actor.TouchedSignal().Connect( &application, functor ); + + // Emit a down and motion + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 11.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Remove actor from stage and add again + stage.Remove( actor ); + stage.Add( actor ); + + // Emit a motion within the actor's bounds + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 12.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit a motion outside the actor's bounds + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 200.0f, 200.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Leave, data.touchEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + + END_TEST; +} + +int UtcDaliTouchStencilNonRenderableActor(void) +{ + TestApplication application; + Stage stage = Stage::GetCurrent(); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stage.Add(actor); + + Actor stencil = Actor::New(); + stencil.SetSize(50.0f, 50.0f); + stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT); + stencil.SetDrawMode( DrawMode::STENCIL ); + stage.Add(stencil); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data ); + actor.TouchedSignal().Connect( &application, functor ); + + // Emit an event within stencil area + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + // Emit an event outside the stencil area but within the actor area, we should have a hit! + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 60.0f, 60.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + data.Reset(); + + END_TEST; +} + +int UtcDaliTouchInterruptedDifferentConsumer(void) +{ + TestApplication application; + Actor rootActor( Stage::GetCurrent().GetRootLayer() ); + + Actor parent = Actor::New(); + parent.SetSize(100.0f, 100.0f); + parent.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(parent); + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + parent.Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's touched signal + SignalData data; + TouchEventFunctor functor( data, false /* Do not consume */ ); + actor.TouchedSignal().Connect( &application, functor ); + + // Connect to parent's touched signal + SignalData parentData; + TouchEventFunctor parentFunctor( parentData, false /* Do not consume */ ); + parent.TouchedSignal().Connect( &application, parentFunctor ); + + // Connect to root's touched signal and consume + SignalData rootData; + TouchEventFunctor rootFunctor( rootData ); + rootActor.TouchedSignal().Connect( &application, rootFunctor ); + + // Emit a down signal + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor ); + DALI_TEST_CHECK( actor == data.touchedActor ); + DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, parentData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == parentData.touchEvent.points[0].hitActor ); + DALI_TEST_CHECK( parent == parentData.touchedActor ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor ); + DALI_TEST_CHECK( rootActor == rootData.touchedActor ); + data.Reset(); + parentData.Reset(); + rootData.Reset(); + + // Root is now consumer, connect to the touched signal of the parent so that it becomes the consumer + SignalData secondData; + TouchEventFunctor secondFunctor( secondData /* Consume */ ); + parent.TouchedSignal().Connect( &application, secondFunctor ); + + // Emit an interrupted signal, all three should STILL be called + application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 10.0f, 10.0f ) ) ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, parentData.touchEvent.points[0].state, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.touchEvent.points[0].state, TEST_LOCATION ); + data.Reset(); + parentData.Reset(); + rootData.Reset(); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-TypeRegistry.cpp b/automated-tests/src/dali/utc-Dali-TypeRegistry.cpp new file mode 100644 index 0000000..8280e4a --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-TypeRegistry.cpp @@ -0,0 +1,1749 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace Dali; + + +namespace +{ + +// Stores data that is populated in the callback and will be read by the Test cases +struct SignalData +{ + SignalData() + : functorCalled( false ), + voidFunctorCalled( false ), + receivedGesture( Gesture::Clear ), + pressedActor() + {} + + void Reset() + { + functorCalled = false; + voidFunctorCalled = false; + + receivedGesture.numberOfTouches = 0u; + receivedGesture.screenPoint = Vector2(0.0f, 0.0f); + receivedGesture.localPoint = Vector2(0.0f, 0.0f); + + pressedActor.Reset(); + } + + bool functorCalled; + bool voidFunctorCalled; + LongPressGesture receivedGesture; + Actor pressedActor; +}; + +// Functor that sets the data when called +struct GestureReceivedFunctor +{ + GestureReceivedFunctor(SignalData& data) : signalData(data) { } + + void operator()(Actor actor, LongPressGesture longPress) + { + signalData.functorCalled = true; + signalData.receivedGesture = longPress; + signalData.pressedActor = actor; + } + + void operator()() + { + signalData.voidFunctorCalled = true; + } + + SignalData& signalData; +}; + +// Generate a LongPressGestureEvent to send to Core +Integration::LongPressGestureEvent GenerateLongPress( + Gesture::State state, + unsigned int numberOfTouches, + Vector2 point) +{ + Integration::LongPressGestureEvent longPress( state ); + + longPress.numberOfTouches = numberOfTouches; + longPress.point = point; + + return longPress; +} + +// Generate a PanGestureEvent to send to Core +Integration::PanGestureEvent GeneratePan( + Gesture::State state, + Vector2 previousPosition, + Vector2 currentPosition, + unsigned long timeDelta, + unsigned int numberOfTouches = 1, + unsigned int time = 1u) +{ + Integration::PanGestureEvent pan(state); + + pan.previousPosition = previousPosition; + pan.currentPosition = currentPosition; + pan.timeDelta = timeDelta; + pan.numberOfTouches = numberOfTouches; + pan.time = time; + + return pan; +} +// Generate a PinchGestureEvent to send to Core +Integration::PinchGestureEvent GeneratePinch( + Gesture::State state, + float scale, + float speed, + Vector2 centerpoint) +{ + Integration::PinchGestureEvent pinch(state); + + pinch.scale = scale; + pinch.speed = speed; + pinch.centerPoint = centerpoint; + + return pinch; +} +// Generate a TapGestureEvent to send to Core +Integration::TapGestureEvent GenerateTap( + Gesture::State state, + unsigned int numberOfTaps, + unsigned int numberOfTouches, + Vector2 point) +{ + Integration::TapGestureEvent tap( state ); + + tap.numberOfTaps = numberOfTaps; + tap.numberOfTouches = numberOfTouches; + tap.point = point; + + return tap; +} + +// +// Create function as Init function called +// +static bool CreateCustomInitCalled = false; +BaseHandle CreateCustomInit(void) +{ + CreateCustomInitCalled = true; + return BaseHandle(); +} + +static bool CreateCustomNamedInitCalled = false; +BaseHandle CreateCustomNamedInit(void) +{ + CreateCustomNamedInitCalled = true; + return BaseHandle(); +} + +const std::string scriptedName("PopupStyle"); +static TypeRegistration scriptedType( scriptedName, typeid(Dali::CustomActor), CreateCustomNamedInit ); + +// Property Registration +bool setPropertyCalled = false; +bool getPropertyCalled = false; +void SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value ) +{ + setPropertyCalled = true; +} +Property::Value GetProperty( BaseObject* object, Property::Index propertyIndex ) +{ + getPropertyCalled = true; + return Property::Value( true ); +} + + + +/******************************************************************************* + * + * Custom Actor + * + ******************************************************************************/ +namespace Impl +{ +struct MyTestCustomActor : public CustomActorImpl +{ + typedef Signal< void ()> SignalType; + typedef Signal< void (float)> SignalTypeFloat; + + MyTestCustomActor() : CustomActorImpl( ActorFlags( REQUIRES_TOUCH_EVENTS ) ) + { } + + virtual ~MyTestCustomActor() + { } + + void ResetCallStack() + { + } + + // From CustomActorImpl + virtual void OnStageConnection( int depth ) + { + } + virtual void OnStageDisconnection() + { + } + virtual void OnChildAdd(Actor& child) + { + } + virtual void OnChildRemove(Actor& child) + { + } + virtual void OnSizeSet(const Vector3& targetSize) + { + } + virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize) + { + } + virtual bool OnTouchEvent(const TouchEvent& event) + { + return true; + } + virtual bool OnHoverEvent(const HoverEvent& event) + { + return true; + } + virtual bool OnWheelEvent(const WheelEvent& event) + { + return true; + } + virtual bool OnKeyEvent(const KeyEvent& event) + { + return true; + } + virtual void OnKeyInputFocusGained() + { + } + virtual void OnKeyInputFocusLost() + { + } + virtual Vector3 GetNaturalSize() + { + return Vector3( 0.0f, 0.0f, 0.0f ); + } + + virtual float GetHeightForWidth( float width ) + { + return 0.0f; + } + + virtual float GetWidthForHeight( float height ) + { + return 0.0f; + } + + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ) + { + } + + virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) + { + } + + virtual void OnCalculateRelayoutSize( Dimension::Type dimension ) + { + } + + virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension ) + { + return 0.0f; + } + + virtual void OnLayoutNegotiated( float size, Dimension::Type dimension ) + { + } + + virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) + { + return false; + } + +public: + + SignalType mSignal; +}; + +}; // namespace Impl + +class MyTestCustomActor : public CustomActor +{ +public: + + typedef Signal< void ()> SignalType; + typedef Signal< void (float)> SignalTypeFloat; + + MyTestCustomActor() + { + } + + static MyTestCustomActor New() + { + Impl::MyTestCustomActor* p = new Impl::MyTestCustomActor; + return MyTestCustomActor( *p ); // takes ownership + } + + virtual ~MyTestCustomActor() + { + } + + static MyTestCustomActor DownCast( BaseHandle handle ) + { + MyTestCustomActor result; + + CustomActor custom = Dali::CustomActor::DownCast( handle ); + if ( custom ) + { + CustomActorImpl& customImpl = custom.GetImplementation(); + + Impl::MyTestCustomActor* impl = dynamic_cast(&customImpl); + + if (impl) + { + result = MyTestCustomActor(customImpl.GetOwner()); + } + } + + return result; + } + + SignalType& GetCustomSignal() + { + Dali::RefObject& obj = GetImplementation(); + return static_cast( obj ).mSignal; + } + +private: + + MyTestCustomActor(Internal::CustomActor* internal) + : CustomActor(internal) + { + } + + MyTestCustomActor( Impl::MyTestCustomActor& impl ) + : CustomActor( impl ) + { + } +}; + + +class MyTestCustomActor2 : public CustomActor +{ +public: + + MyTestCustomActor2() + { + } + + static MyTestCustomActor2 New() + { + return MyTestCustomActor2(); // takes ownership + } + + virtual ~MyTestCustomActor2() + { + } + + static MyTestCustomActor2 DownCast( BaseHandle handle ) + { + MyTestCustomActor2 result; + + CustomActor custom = Dali::CustomActor::DownCast( handle ); + if ( custom ) + { + CustomActorImpl& customImpl = custom.GetImplementation(); + + Impl::MyTestCustomActor* impl = dynamic_cast(&customImpl); + + if (impl) + { + result = MyTestCustomActor2(customImpl.GetOwner()); + } + } + + return result; + } + +private: + + MyTestCustomActor2(Internal::CustomActor* internal) + : CustomActor(internal) + { + } + + MyTestCustomActor2( Impl::MyTestCustomActor& impl ) + : CustomActor( impl ) + { + } +}; + +static TypeRegistration customTypeInit( typeid(MyTestCustomActor2), typeid(Dali::CustomActor), CreateCustomInit, true ); + + +BaseHandle CreateCustom(void) +{ + return MyTestCustomActor::New(); +} + +static std::string lastSignalConnectionCustom; + +bool DoConnectSignalCustom( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) +{ + lastSignalConnectionCustom = signalName; + + bool connected( true ); + + Dali::BaseHandle handle(object); + MyTestCustomActor customActor = MyTestCustomActor::DownCast(handle); + + if( "sig1" == signalName ) + { + customActor.GetCustomSignal().Connect( tracker, functor ); + } + else + { + // signalName does not match any signal + connected = false; + } + + return connected; +} + +bool DoConnectSignalCustomFailure( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) +{ + lastSignalConnectionCustom = "failed"; + + return false; // This is supposed to fail +} + +struct CustomTestFunctor +{ + CustomTestFunctor() + { + ++mTotalInstanceCount; + ++mCurrentInstanceCount; + } + + CustomTestFunctor( const CustomTestFunctor& copyMe ) + { + ++mTotalInstanceCount; + ++mCurrentInstanceCount; + } + + ~CustomTestFunctor() + { + --mCurrentInstanceCount; + } + + void operator()() + { + ++mCallbackCount; + } + + static int mTotalInstanceCount; + static int mCurrentInstanceCount; + static int mCallbackCount; +}; + +int CustomTestFunctor::mTotalInstanceCount = 0; +int CustomTestFunctor::mCurrentInstanceCount = 0; +int CustomTestFunctor::mCallbackCount = 0; + +static void ResetFunctorCounts() +{ + CustomTestFunctor::mTotalInstanceCount = 0; + CustomTestFunctor::mCurrentInstanceCount = 0; + CustomTestFunctor::mCallbackCount = 0; +} + +static std::string lastActionCustom; +bool DoActionCustom(BaseObject* object, const std::string& actionName, const Property::Map& /*attributes*/) +{ + lastActionCustom = actionName; + return true; +} + +// Custom type registration +static TypeRegistration customType1( typeid(MyTestCustomActor), typeid(Dali::CustomActor), CreateCustom ); + +// Custom signals +static SignalConnectorType customSignalConnector1( customType1, "sig1", DoConnectSignalCustom ); +static SignalConnectorType customSignalConnector2( customType1, "sig2", DoConnectSignalCustomFailure ); +static const int TEST_SIGNAL_COUNT = 2; + +// Custom actions +static TypeAction customAction1( customType1, "act1", DoActionCustom); +static const int TEST_ACTION_COUNT = 1; + +class TestConnectionTracker : public ConnectionTracker +{ +public: + + TestConnectionTracker() + { + } +}; + +BaseHandle CreateNamedActorType() +{ + Actor actor = Actor::New(); + actor.SetName( "NamedActor" ); + return actor; +} + +TypeRegistration namedActorType( "MyNamedActor", typeid(Dali::Actor), CreateNamedActorType ); +PropertyRegistration namedActorPropertyOne( namedActorType, "prop-name", PROPERTY_REGISTRATION_START_INDEX, Property::BOOLEAN, &SetProperty, &GetProperty ); + +} // Anonymous namespace + +// Note: No negative test case for UtcDaliTypeRegistryGet can be implemented. +int UtcDaliTypeRegistryGetP(void) +{ + TestApplication application; + + TypeRegistry registry = TypeRegistry::Get(); + DALI_TEST_CHECK( registry ); + + END_TEST; +} + +// Note: No negative test case for UtcDaliTypeRegistryConstructor can be implemented. +int UtcDaliTypeRegistryConstructorP(void) +{ + TestApplication application; + + TypeRegistry registry; + DALI_TEST_CHECK( !registry ); + END_TEST; +} + +// Note: No negative test case for UtcDaliTypeRegistryCopyConstructor can be implemented. +int UtcDaliTypeRegistryCopyConstructorP(void) +{ + TestApplication application; + + TypeRegistry registry = TypeRegistry::Get(); + DALI_TEST_CHECK( registry ); + + TypeRegistry copy( registry ); + DALI_TEST_CHECK( copy ); + + DALI_TEST_CHECK( registry.GetTypeInfo( "Actor" ).GetName() == copy.GetTypeInfo( "Actor" ).GetName() ); + + END_TEST; +} + +// Note: No negative test case for UtcDaliTypeRegistryAssignmentOperator can be implemented. +int UtcDaliTypeRegistryAssignmentOperatorP(void) +{ + TestApplication application; + + TypeRegistry registry = TypeRegistry::Get(); + DALI_TEST_CHECK( registry ); + + TypeRegistry copy = registry; + DALI_TEST_CHECK( copy ); + DALI_TEST_CHECK( registry == copy ); + + DALI_TEST_CHECK( registry.GetTypeInfo( "Actor" ).GetName() == copy.GetTypeInfo( "Actor" ).GetName() ); + + END_TEST; +} + +int UtcDaliTypeRegistryAssignP(void) +{ + TestApplication application; + + TypeRegistry registry = TypeRegistry::Get(); + TypeRegistry registry2; + registry2 = registry; + DALI_TEST_CHECK( registry2 ); + + DALI_TEST_CHECK( registry2.GetTypeInfo( "Actor" ).GetName() == registry2.GetTypeInfo( "Actor" ).GetName() ); + + END_TEST; +} + +int UtcDaliTypeRegistryGetTypeInfoFromTypeNameP(void) +{ + TestApplication application; + + TypeRegistry registry = TypeRegistry::Get(); + + TypeInfo type; + + // image actor + type = registry.GetTypeInfo( "ImageActor" ); + DALI_TEST_CHECK( type ); + DALI_TEST_CHECK( type.GetCreator() ); + DALI_TEST_CHECK( ImageActor::DownCast( type.GetCreator()() ) ); + ImageActor ia = ImageActor::DownCast(type.CreateInstance()); + DALI_TEST_CHECK( ia ); + Stage::GetCurrent().Add( ia ); + application.Render(); + + // camera actor + type = registry.GetTypeInfo( "CameraActor" ); + DALI_TEST_CHECK( type ); + CameraActor ca = CameraActor::DownCast(type.CreateInstance()); + DALI_TEST_CHECK( ca ); + Stage::GetCurrent().Add( ca ); + application.Render(); + + // animations + type = registry.GetTypeInfo( "Animation" ); + DALI_TEST_CHECK( type ); + Animation an = Animation::DownCast(type.CreateInstance()); + DALI_TEST_CHECK( an ); + an.Play(); + application.Render(); + + // shader effect + type = registry.GetTypeInfo( "ShaderEffect" ); + DALI_TEST_CHECK( type ); + ShaderEffect ef = ShaderEffect::DownCast(type.CreateInstance()); + DALI_TEST_CHECK( ef ); + application.Render(); + + END_TEST; +} + +int UtcDaliTypeRegistryGetTypeInfoFromTypeNameN(void) +{ + TestApplication application; + + TypeRegistry registry = TypeRegistry::Get(); + + TypeInfo type; + + type = registry.GetTypeInfo( "MyDummyActor" ); + DALI_TEST_CHECK( !type ); + + END_TEST; +} + +int UtcDaliTypeRegistryGetTypeInfoFromTypeIdP(void) +{ + TypeInfo named_type = TypeRegistry::Get().GetTypeInfo( "ImageActor" ); + TypeInfo typeinfo_type = TypeRegistry::Get().GetTypeInfo( typeid(Dali::ImageActor) ); + + DALI_TEST_CHECK( named_type ); + DALI_TEST_CHECK( typeinfo_type ); + + // Check named and typeid are equivalent + DALI_TEST_CHECK( named_type == typeinfo_type ); + + DALI_TEST_CHECK( named_type.GetName() == typeinfo_type.GetName() ); + DALI_TEST_CHECK( named_type.GetBaseName() == typeinfo_type.GetBaseName() ); + + END_TEST; +} + +int UtcDaliTypeRegistryGetTypeInfoFromTypeIdN(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + + TypeInfo typeInfo = typeRegistry.GetTypeInfo( typeid(Vector2) ); + DALI_TEST_CHECK( !typeInfo ); + + END_TEST; +} + +int UtcDaliTypeRegistryGetTypeNameCountP(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + TypeInfo type; + + for(size_t i = 0; i < typeRegistry.GetTypeNameCount(); i++) + { + type = typeRegistry.GetTypeInfo( typeRegistry.GetTypeName(i) ); + DALI_TEST_CHECK( type ); + } + + END_TEST; +} + + +int UtcDaliTypeRegistryGetTypeNamesP(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + TypeInfo type; + + for(size_t i = 0; i < typeRegistry.GetTypeNameCount(); i++) + { + type = typeRegistry.GetTypeInfo( typeRegistry.GetTypeName(i) ); + DALI_TEST_CHECK( type ); + } + + END_TEST; +} + + +// Note: No negative test case for UtcDaliTypeRegistryTypeRegistration can be implemented. +int UtcDaliTypeRegistryTypeRegistrationNotCallingCreateOnInitP(void) +{ + ResetFunctorCounts(); + + TestApplication application; + + TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyTestCustomActor" ); + DALI_TEST_CHECK( type ); + + TypeInfo baseType = TypeRegistry::Get().GetTypeInfo( "CustomActor" ); + DALI_TEST_CHECK( baseType ); + + BaseHandle handle = type.CreateInstance(); + DALI_TEST_CHECK( handle ); + + MyTestCustomActor customHandle = MyTestCustomActor::DownCast( handle ); + DALI_TEST_CHECK( customHandle ); + + DALI_TEST_EQUALS( type.GetActionCount(), TEST_ACTION_COUNT + baseType.GetActionCount(), TEST_LOCATION ); + + DALI_TEST_EQUALS( type.GetSignalCount(), TEST_SIGNAL_COUNT + baseType.GetSignalCount(), TEST_LOCATION ); + + { + TestConnectionTracker tracker; + + bool connected = handle.ConnectSignal( &tracker, "sig1", CustomTestFunctor() ); + DALI_TEST_EQUALS( connected, true, TEST_LOCATION ); + DALI_TEST_CHECK( lastSignalConnectionCustom == "sig1" ); + DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 1, TEST_LOCATION ); + + DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 0, TEST_LOCATION ); + customHandle.GetCustomSignal().Emit(); + DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 1, TEST_LOCATION ); + } + // tracker should automatically disconnect here + DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 0, TEST_LOCATION ); + + // Test that functor is disconnected + DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 1, TEST_LOCATION ); + customHandle.GetCustomSignal().Emit(); + DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 1/*not incremented*/, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 0, TEST_LOCATION ); + + Property::Map attributes; + handle.DoAction("act1", attributes); + DALI_TEST_CHECK( lastActionCustom == "act1" ); + END_TEST; +} + +// Note: No negative test case for UtcDaliTypeRegistryTypeRegistration can be implemented. +int UtcDaliTypeRegistryTypeRegistrationCallingCreateOnInitP(void) +{ + TestApplication application; + + DALI_TEST_CHECK( "MyTestCustomActor2" == customTypeInit.RegisteredName() ); + + DALI_TEST_CHECK( true == CreateCustomInitCalled ); + TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyTestCustomActor2" ); + DALI_TEST_CHECK( type ); + END_TEST; +} + +// Note: No negative test case for UtcDaliTypeRegistryTypeRegistration can be implemented. +int UtcDaliTypeRegistryTypeRegistrationForNamedTypeP(void) +{ + TestApplication application; + + // Create Named Actor Type + TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyNamedActor" ); + DALI_TEST_CHECK( type ); + + BaseHandle namedHandle = type.CreateInstance(); + DALI_TEST_CHECK( namedHandle ); + Actor namedActor( Actor::DownCast( namedHandle ) ); + DALI_TEST_CHECK( namedActor ); + + DALI_TEST_CHECK( namedActor.GetName() == "NamedActor" ); + DALI_TEST_CHECK( type.GetName() == "MyNamedActor" ); + DALI_TEST_CHECK( type.GetBaseName() == "Actor" ); + + END_TEST; +} + +// Note: No negative test case for UtcDaliTypeRegistryRegisteredName can be implemented. +int UtcDaliTypeRegistryRegisteredNameP(void) +{ + TestApplication application; + + DALI_TEST_CHECK( scriptedName == scriptedType.RegisteredName() ); + + TypeInfo baseType = TypeRegistry::Get().GetTypeInfo( scriptedName ); + DALI_TEST_CHECK( baseType ); + + BaseHandle handle = baseType.CreateInstance(); + + DALI_TEST_CHECK( true == CreateCustomNamedInitCalled ); + TypeInfo type = TypeRegistry::Get().GetTypeInfo( scriptedName ); + DALI_TEST_CHECK( type ); + END_TEST; +} + +int UtcDaliTypeRegistrySignalConnectorTypeP(void) +{ + ResetFunctorCounts(); + + TestApplication application; + + TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyTestCustomActor" ); + DALI_TEST_CHECK( type ); + + BaseHandle handle = type.CreateInstance(); + DALI_TEST_CHECK( handle ); + + MyTestCustomActor customHandle = MyTestCustomActor::DownCast( handle ); + DALI_TEST_CHECK( customHandle ); + + { + TestConnectionTracker tracker; + + bool connected = handle.ConnectSignal( &tracker, "sig1", CustomTestFunctor() ); + DALI_TEST_EQUALS( connected, true, TEST_LOCATION ); + DALI_TEST_CHECK( lastSignalConnectionCustom == "sig1" ); + DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 1, TEST_LOCATION ); + + DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 0, TEST_LOCATION ); + customHandle.GetCustomSignal().Emit(); + DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 1, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 1, TEST_LOCATION ); + } + // tracker should automatically disconnect here + DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 0, TEST_LOCATION ); + + // Test that functor is disconnected + DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 1, TEST_LOCATION ); + customHandle.GetCustomSignal().Emit(); + DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 1/*not incremented*/, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 0, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliTypeRegistrySignalConnectorTypeN(void) +{ + // Test what happens when signal connnector (DoConnectSignalFailure method) returns false + + ResetFunctorCounts(); + + TestApplication application; + + TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyTestCustomActor" ); + DALI_TEST_CHECK( type ); + + TypeInfo baseType = TypeRegistry::Get().GetTypeInfo( "CustomActor" ); + DALI_TEST_CHECK( baseType ); + + BaseHandle handle = type.CreateInstance(); + DALI_TEST_CHECK( handle ); + + MyTestCustomActor customHandle = MyTestCustomActor::DownCast( handle ); + DALI_TEST_CHECK( customHandle ); + + DALI_TEST_EQUALS( type.GetActionCount(), TEST_ACTION_COUNT + baseType.GetActionCount(), TEST_LOCATION ); + + DALI_TEST_EQUALS( type.GetSignalCount(), TEST_SIGNAL_COUNT + baseType.GetSignalCount(), TEST_LOCATION ); + + { + TestConnectionTracker tracker; + + bool connected = handle.ConnectSignal( &tracker, "sig2", CustomTestFunctor() ); + DALI_TEST_EQUALS( connected, false/*This is supposed to fail*/, TEST_LOCATION ); + DALI_TEST_CHECK( lastSignalConnectionCustom == "failed" ); + DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION ); + DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 0/*deleted along with FunctorDelegate*/, TEST_LOCATION ); + + // Should be a NOOP + DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 0, TEST_LOCATION ); + customHandle.GetCustomSignal().Emit(); + DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 0/*never called*/, TEST_LOCATION ); + } + // tracker should have nothing to disconnect here + + // Should be a NOOP + DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 0, TEST_LOCATION ); + customHandle.GetCustomSignal().Emit(); + DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 0/*never called*/, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliTypeRegistryTypeActionP(void) +{ + ResetFunctorCounts(); + + TestApplication application; + + TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyTestCustomActor" ); + DALI_TEST_CHECK( type ); + + BaseHandle handle = type.CreateInstance(); + DALI_TEST_CHECK( handle ); + + Property::Map attributes; + DALI_TEST_CHECK( handle.DoAction("act1", attributes) ); + DALI_TEST_CHECK( lastActionCustom == "act1" ); + + END_TEST; +} + +int UtcDaliTypeRegistryTypeActionN(void) +{ + ResetFunctorCounts(); + + TestApplication application; + + TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyTestCustomActor" ); + DALI_TEST_CHECK( type ); + + BaseHandle handle = type.CreateInstance(); + DALI_TEST_CHECK( handle ); + + Property::Map attributes; + DALI_TEST_CHECK( !handle.DoAction( "unknown-action", attributes ) ); + + END_TEST; +} + +int UtcDaliTypeRegistryPropertyRegistrationP(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + + // Check property count before property registration + TypeInfo typeInfo = typeRegistry.GetTypeInfo( typeid(MyTestCustomActor) ); + DALI_TEST_CHECK( typeInfo ); + BaseHandle handle = typeInfo.CreateInstance(); + DALI_TEST_CHECK( handle ); + Actor customActor = Actor::DownCast( handle ); + DALI_TEST_CHECK( customActor ); + unsigned int initialPropertyCount( customActor.GetPropertyCount() ); + + std::string propertyName( "prop-1" ); + int propertyIndex( PROPERTY_REGISTRATION_START_INDEX ); + Property::Type propertyType( Property::BOOLEAN ); + PropertyRegistration property1( customType1, propertyName, propertyIndex, propertyType, &SetProperty, &GetProperty ); + + // Check property count after registration + unsigned int postRegistrationPropertyCount( customActor.GetPropertyCount() ); + DALI_TEST_EQUALS( initialPropertyCount + 1u, postRegistrationPropertyCount, TEST_LOCATION ); + + // Add custom property and check property count + customActor.RegisterProperty( "custom-prop-1", true ); + unsigned int customPropertyCount( customActor.GetPropertyCount() ); + DALI_TEST_EQUALS( postRegistrationPropertyCount + 1u, customPropertyCount, TEST_LOCATION ); + + // Set the property, ensure SetProperty called + DALI_TEST_CHECK( !setPropertyCalled ); + customActor.SetProperty( propertyIndex, false ); + DALI_TEST_CHECK( setPropertyCalled ); + + // Get the property, ensure GetProperty called + DALI_TEST_CHECK( !getPropertyCalled ); + (void)customActor.GetProperty< bool >( propertyIndex ); + DALI_TEST_CHECK( getPropertyCalled ); + + // Check the property name + DALI_TEST_EQUALS( customActor.GetPropertyName( propertyIndex ), propertyName, TEST_LOCATION ); + DALI_TEST_EQUALS( typeInfo.GetPropertyName( propertyIndex ), propertyName, TEST_LOCATION ); + + // Check the property index + DALI_TEST_EQUALS( customActor.GetPropertyIndex( propertyName ), propertyIndex, TEST_LOCATION ); + + // Check the property type + DALI_TEST_EQUALS( customActor.GetPropertyType( propertyIndex ), propertyType, TEST_LOCATION ); + + // Check property count of type-info is 1 + Property::IndexContainer indices; + typeInfo.GetPropertyIndices( indices ); + DALI_TEST_EQUALS( indices.Size(), 1u, TEST_LOCATION ); + + // Ensure indices returned from actor and customActor differ by two + Actor actor = Actor::New(); + actor.GetPropertyIndices( indices ); + unsigned int actorIndices = indices.Size(); + customActor.GetPropertyIndices( indices ); + unsigned int customActorIndices = indices.Size(); + DALI_TEST_EQUALS( actorIndices + 2u, customActorIndices, TEST_LOCATION ); // Custom property + registered property + END_TEST; +} + +int UtcDaliTypeRegistryPropertyRegistrationN(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + + // Attempt to register a property type out-of-bounds index (less than) + try + { + PropertyRegistration property1( customType1, "prop-name", PROPERTY_REGISTRATION_START_INDEX - 1, Property::BOOLEAN, &SetProperty, &GetProperty ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX )", TEST_LOCATION ); + } + + // Attempt to register a property type out-of-bounds index (greater than) + try + { + PropertyRegistration property1( customType1, "prop-name", PROPERTY_REGISTRATION_MAX_INDEX + 1, Property::BOOLEAN, &SetProperty, &GetProperty ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX )", TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliTypeRegistryAnimatablePropertyRegistrationP(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + + // Check property count before property registration + TypeInfo typeInfo = typeRegistry.GetTypeInfo( typeid(MyTestCustomActor) ); + DALI_TEST_CHECK( typeInfo ); + BaseHandle handle = typeInfo.CreateInstance(); + DALI_TEST_CHECK( handle ); + Actor customActor = Actor::DownCast( handle ); + DALI_TEST_CHECK( customActor ); + + unsigned int customPropertyCount( customActor.GetPropertyCount() ); + + // Register animatable property + std::string animatablePropertyName( "animatable-prop-1" ); + int animatablePropertyIndex( ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ); + Property::Type animatablePropertyType( Property::FLOAT ); + AnimatablePropertyRegistration animatableProperty1( customType1, animatablePropertyName, animatablePropertyIndex, animatablePropertyType ); + + // Check property count after registration + DALI_TEST_EQUALS( customPropertyCount + 1u, customActor.GetPropertyCount(), TEST_LOCATION ); + + // Set the animatable property value + customActor.SetProperty( animatablePropertyIndex, 25.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Check the animatable property value + DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyIndex ), 25.0f, TEST_LOCATION ); + + // Check the animatable property name + DALI_TEST_EQUALS( customActor.GetPropertyName( animatablePropertyIndex ), animatablePropertyName, TEST_LOCATION ); + + // Check the animatable property index + DALI_TEST_EQUALS( customActor.GetPropertyIndex( animatablePropertyName ), animatablePropertyIndex, TEST_LOCATION ); + + // Check the animatable property type + DALI_TEST_EQUALS( customActor.GetPropertyType( animatablePropertyIndex ), animatablePropertyType, TEST_LOCATION ); + + // Check property count of type-info is 1 + Property::IndexContainer indices; + typeInfo.GetPropertyIndices( indices ); + DALI_TEST_EQUALS( indices.Size(), 1u, TEST_LOCATION ); + + // Ensure indices returned from actor and customActor differ by one + Actor actor = Actor::New(); + actor.GetPropertyIndices( indices ); + unsigned int actorIndices = indices.Size(); + customActor.GetPropertyIndices( indices ); + unsigned int customActorIndices = indices.Size(); + DALI_TEST_EQUALS( actorIndices + 1u, customActorIndices, TEST_LOCATION ); // Custom property + registered property + + END_TEST; +} + +int UtcDaliTypeRegistryAnimatablePropertyRegistrationN(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + + // Attempt to register an animatable property type out-of-bounds index (less than) + try + { + AnimatablePropertyRegistration property1( customType1, "anim-prop-name", ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX - 1, Property::BOOLEAN ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )", TEST_LOCATION ); + } + + // Attempt to register an animatable property type out-of-bounds index (greater than) + try + { + AnimatablePropertyRegistration property1( customType1, "anim-prop-name", ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX + 1, Property::BOOLEAN ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )", TEST_LOCATION ); + } + + END_TEST; +} + +int UtcDaliTypeRegistryAnimatablePropertyComponentRegistrationP(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + + // Check property count before property registration + TypeInfo typeInfo = typeRegistry.GetTypeInfo( typeid(MyTestCustomActor) ); + DALI_TEST_CHECK( typeInfo ); + BaseHandle handle = typeInfo.CreateInstance(); + DALI_TEST_CHECK( handle ); + Actor customActor = Actor::DownCast( handle ); + DALI_TEST_CHECK( customActor ); + + unsigned int customPropertyCount( customActor.GetPropertyCount() ); + + // Register animatable property + std::string animatablePropertyName( "animatable-prop-1" ); + int animatablePropertyIndex( ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ); + Property::Type animatablePropertyType( Property::VECTOR2 ); + AnimatablePropertyRegistration animatableProperty1( customType1, animatablePropertyName, animatablePropertyIndex, animatablePropertyType ); + + // Check property count after registration + DALI_TEST_EQUALS( customPropertyCount + 1u, customActor.GetPropertyCount(), TEST_LOCATION ); + + // Set the animatable property value + customActor.SetProperty( animatablePropertyIndex, Vector2(25.0f, 50.0f) ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Check the animatable property value + DALI_TEST_EQUALS( customActor.GetProperty< Vector2 >( animatablePropertyIndex ), Vector2(25.0f, 50.0f), TEST_LOCATION ); + + // Check the animatable property name + DALI_TEST_EQUALS( customActor.GetPropertyName( animatablePropertyIndex ), animatablePropertyName, TEST_LOCATION ); + + // Check the animatable property index + DALI_TEST_EQUALS( customActor.GetPropertyIndex( animatablePropertyName ), animatablePropertyIndex, TEST_LOCATION ); + + // Check the animatable property type + DALI_TEST_EQUALS( customActor.GetPropertyType( animatablePropertyIndex ), animatablePropertyType, TEST_LOCATION ); + + // Check property count of type-info is 1 + Property::IndexContainer indices; + typeInfo.GetPropertyIndices( indices ); + DALI_TEST_EQUALS( indices.Size(), 1u, TEST_LOCATION ); + + // Register animatable property components + std::string animatablePropertyComponentName1( "animatable-prop-1-x" ); + int animatablePropertyComponentIndex1( ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 1 ); + AnimatablePropertyComponentRegistration animatablePropertyComponent1( customType1, animatablePropertyComponentName1, animatablePropertyComponentIndex1, animatablePropertyIndex, 0 ); + + std::string animatablePropertyComponentName2( "animatable-prop-1-y" ); + int animatablePropertyComponentIndex2( ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 2 ); + AnimatablePropertyComponentRegistration animatablePropertyComponent2( customType1, animatablePropertyComponentName2, animatablePropertyComponentIndex2, animatablePropertyIndex, 1 ); + + // Check property count after registration + DALI_TEST_EQUALS( customPropertyCount + 3u, customActor.GetPropertyCount(), TEST_LOCATION ); + + // Check the animatable property component value + DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyComponentIndex1 ), 25.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyComponentIndex2 ), 50.0f, TEST_LOCATION ); + + // Set the animatable property component value + customActor.SetProperty( animatablePropertyComponentIndex1, 150.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Check the animatable property value + DALI_TEST_EQUALS( customActor.GetProperty< Vector2 >( animatablePropertyIndex ), Vector2(150.0f, 50.0f), TEST_LOCATION ); + DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyComponentIndex1 ), 150.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyComponentIndex2 ), 50.0f, TEST_LOCATION ); + + // Set the animatable property component value + customActor.SetProperty( animatablePropertyComponentIndex2, 225.0f ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Check the animatable property value + DALI_TEST_EQUALS( customActor.GetProperty< Vector2 >( animatablePropertyIndex ), Vector2(150.0f, 225.0f), TEST_LOCATION ); + DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyComponentIndex1 ), 150.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyComponentIndex2 ), 225.0f, TEST_LOCATION ); + + // Ensure indices returned from actor and customActor differ by three + Actor actor = Actor::New(); + actor.GetPropertyIndices( indices ); + unsigned int actorIndices = indices.Size(); + customActor.GetPropertyIndices( indices ); + unsigned int customActorIndices = indices.Size(); + DALI_TEST_EQUALS( actorIndices + 3u, customActorIndices, TEST_LOCATION ); // Custom property + registered property + + END_TEST; +} + +int UtcDaliTypeRegistryAnimatablePropertyComponentRegistrationN(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + + // Register animatable property with the type of Vector2 + int animatablePropertyIndex1( ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ); + AnimatablePropertyRegistration animatableProperty1( customType1, "animatable-prop-1", animatablePropertyIndex1, Property::VECTOR2 ); + + // Attempt to register an animatable property component out-of-bounds index (less than) + try + { + AnimatablePropertyComponentRegistration propertyComponent1( customType1, "animatable-prop-1-x", ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX - 1, animatablePropertyIndex1, 0 ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )", TEST_LOCATION ); + } + + // Attempt to register an animatable property component out-of-bounds index (greater than) + try + { + AnimatablePropertyComponentRegistration propertyComponent1( customType1, "animatable-prop-1-x", ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX + 1, animatablePropertyIndex1, 0 ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )", TEST_LOCATION ); + } + + // Register an animatable property component + AnimatablePropertyComponentRegistration propertyComponent1( customType1, "animatable-prop-1-x", ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 1, animatablePropertyIndex1, 0 ); + + // Attempt to register another animatable property component with the same component index + try + { + AnimatablePropertyComponentRegistration propertyComponent2( customType1, "animatable-prop-1-y", ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 2, animatablePropertyIndex1, 0 ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "Property component already registered", TEST_LOCATION ); + } + + // Register animatable property with the type of boolean + int animatablePropertyIndex2( ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 2 ); + AnimatablePropertyRegistration animatableProperty2( customType1, "animatable-prop-2", animatablePropertyIndex2, Property::BOOLEAN ); + + // Attempt to register an animatable property component for the above property with boolean type + try + { + AnimatablePropertyComponentRegistration propertyComponent1( customType1, "animatable-prop-2-x", animatablePropertyIndex2 + 1, animatablePropertyIndex2, 0 ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "Base property does not support component", TEST_LOCATION ); + } + + END_TEST; +} + + +/******************************************************************************* + * + * Action through the base handle + * + ******************************************************************************/ +int UtcDaliTypeRegistryActionViaBaseHandle(void) +{ + TestApplication application; + + TypeInfo type; + + type = TypeRegistry::Get().GetTypeInfo( "Actor" ); + DALI_TEST_CHECK( type ); + + BaseHandle hdl = type.CreateInstance(); + DALI_TEST_CHECK( hdl ); + + Actor a = Actor::DownCast(hdl); + DALI_TEST_CHECK( a ); + + a.SetVisible(false); + + application.SendNotification(); + application.Render(0); + DALI_TEST_CHECK(!a.IsVisible()); + + Property::Map attributes; + + DALI_TEST_CHECK(hdl.DoAction("show", attributes)); + + application.SendNotification(); + application.Render(0); + DALI_TEST_CHECK(a.IsVisible()); + + DALI_TEST_CHECK(!hdl.DoAction("unknown-action", attributes)); + END_TEST; +} + +int UtcDaliPropertyRegistrationFunctions(void) +{ + TestApplication application; + int propertyIndex = PROPERTY_REGISTRATION_START_INDEX + 10; + + // Attempt to register a property without a setter + try + { + PropertyRegistration property1( customType1, "prop-name", propertyIndex++, Property::BOOLEAN, NULL, &GetProperty ); + tet_result( TET_PASS ); + } + catch ( DaliException& e ) + { + tet_result( TET_FAIL ); + } + + // Attempt to register a property without a getter + try + { + PropertyRegistration property1( customType1, "prop-name", propertyIndex++, Property::BOOLEAN, NULL, NULL ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "! \"GetProperty", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliPropertyRegistrationAddSameIndex(void) +{ + TestApplication application; + int propertyIndex = PROPERTY_REGISTRATION_START_INDEX + 100; + + // Add one property with a valid property index + PropertyRegistration property1( customType1, "prop-name", propertyIndex, Property::BOOLEAN, &SetProperty, &GetProperty ); + + // Attempt to add another property with the same index + try + { + PropertyRegistration property2( customType1, "prop-name-2", propertyIndex, Property::BOOLEAN, &SetProperty, &GetProperty ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "! \"Property index already added", TEST_LOCATION ); + } + + int animatablePropertyIndex = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 100; + + // Add one property with a valid property index + AnimatablePropertyRegistration property3( customType1, "anim-prop-name", animatablePropertyIndex, Property::BOOLEAN ); + + // Attempt to add another property with the same index + try + { + AnimatablePropertyRegistration property4( customType1, "anim-prop-name-2", animatablePropertyIndex, Property::BOOLEAN ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "! \"Property index already added", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliPropertyRegistrationPropertyWritable(void) +{ + TestApplication application; + int propertyIndex1 = PROPERTY_REGISTRATION_START_INDEX + 200; + int propertyIndex2 = PROPERTY_REGISTRATION_START_INDEX + 201; + + // Add two properties, one with SetProperty, one without + PropertyRegistration property1( customType1, "prop-name-readwrite", propertyIndex1, Property::BOOLEAN, &SetProperty, &GetProperty ); + PropertyRegistration property2( customType1, "prop-name-readonly", propertyIndex2, Property::BOOLEAN, NULL, &GetProperty ); + + // Create custom-actor + TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( typeid(MyTestCustomActor) ); + DALI_TEST_CHECK( typeInfo ); + BaseHandle handle = typeInfo.CreateInstance(); + DALI_TEST_CHECK( handle ); + Actor customActor = Actor::DownCast( handle ); + DALI_TEST_CHECK( customActor ); + + // Check whether properties are writable + DALI_TEST_CHECK( customActor.IsPropertyWritable( propertyIndex1 ) ); + DALI_TEST_CHECK( ! customActor.IsPropertyWritable( propertyIndex2 ) ); + END_TEST; +} + +int UtcDaliPropertyRegistrationPropertyAnimatable(void) +{ + TestApplication application; + int propertyIndex = PROPERTY_REGISTRATION_START_INDEX + 400; + int animatablePropertyIndex = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 400; + + // These properties are not animatable + PropertyRegistration property1( customType1, "prop-name", propertyIndex, Property::BOOLEAN, &SetProperty, &GetProperty ); + + // These properties are animatable + AnimatablePropertyRegistration property2( customType1, "anim-prop-name", animatablePropertyIndex, Property::BOOLEAN ); + + // Create custom-actor + TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( typeid(MyTestCustomActor) ); + DALI_TEST_CHECK( typeInfo ); + BaseHandle handle = typeInfo.CreateInstance(); + DALI_TEST_CHECK( handle ); + Actor customActor = Actor::DownCast( handle ); + DALI_TEST_CHECK( customActor ); + + // Check if animatable + DALI_TEST_CHECK( ! customActor.IsPropertyAnimatable( propertyIndex ) ); + DALI_TEST_CHECK( customActor.IsPropertyAnimatable( animatablePropertyIndex ) ); + + // Create another instance of custom-actor + BaseHandle handle2 = typeInfo.CreateInstance(); + DALI_TEST_CHECK( handle2 ); + Actor customActor2 = Actor::DownCast( handle2 ); + DALI_TEST_CHECK( customActor2 ); + + // Check if animatable + DALI_TEST_CHECK( ! customActor2.IsPropertyAnimatable( propertyIndex ) ); + DALI_TEST_CHECK( customActor2.IsPropertyAnimatable( animatablePropertyIndex ) ); + END_TEST; +} + +int UtcDaliPropertyRegistrationInvalidGetAndSet(void) +{ + TestApplication application; + int propertyIndex = PROPERTY_REGISTRATION_START_INDEX + 2000; + int animatablePropertyIndex = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 2000; + + // Create custom-actor + TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( typeid(MyTestCustomActor) ); + DALI_TEST_CHECK( typeInfo ); + BaseHandle handle = typeInfo.CreateInstance(); + DALI_TEST_CHECK( handle ); + Actor customActor = Actor::DownCast( handle ); + DALI_TEST_CHECK( customActor ); + + // Try to set an index that hasn't been added + try + { + customActor.SetProperty( propertyIndex, true ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "! \"Cannot find property index", TEST_LOCATION ); + } + + try + { + customActor.SetProperty( animatablePropertyIndex, true ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "! \"Cannot find property index", TEST_LOCATION ); + } + + // Try to get an index that hasn't been added + try + { + (void) customActor.GetProperty< bool >( propertyIndex ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "! \"Cannot find property index", TEST_LOCATION ); + } + + try + { + (void) customActor.GetProperty< bool >( animatablePropertyIndex ); + tet_result( TET_FAIL ); + } + catch ( DaliException& e ) + { + DALI_TEST_ASSERT( e, "! \"Cannot find property index", TEST_LOCATION ); + } + END_TEST; +} + + +int UtcDaliLongPressGestureDetectorTypeRegistry(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Register Type + TypeInfo type; + type = TypeRegistry::Get().GetTypeInfo( "LongPressGestureDetector" ); + DALI_TEST_CHECK( type ); + BaseHandle handle = type.CreateInstance(); + DALI_TEST_CHECK( handle ); + LongPressGestureDetector detector = LongPressGestureDetector::DownCast( handle ); + DALI_TEST_CHECK( detector ); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + detector.Attach(actor); + + // Connect to signal through type + handle.ConnectSignal( &application, "long-press-detected", functor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit gesture + application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.voidFunctorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPanGestureDetectorTypeRegistry(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Register Type + TypeInfo type; + type = TypeRegistry::Get().GetTypeInfo( "PanGestureDetector" ); + DALI_TEST_CHECK( type ); + BaseHandle handle = type.CreateInstance(); + DALI_TEST_CHECK( handle ); + PanGestureDetector detector = PanGestureDetector::DownCast( handle ); + DALI_TEST_CHECK( detector ); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + detector.Attach(actor); + + // Connect to signal through type + handle.ConnectSignal( &application, "pan-detected", functor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit gesture + application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10)); + DALI_TEST_EQUALS(true, data.voidFunctorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliPinchGestureDetectorTypeRegistry(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Register Type + TypeInfo type; + type = TypeRegistry::Get().GetTypeInfo( "PinchGestureDetector" ); + DALI_TEST_CHECK( type ); + BaseHandle handle = type.CreateInstance(); + DALI_TEST_CHECK( handle ); + PinchGestureDetector detector = PinchGestureDetector::DownCast( handle ); + DALI_TEST_CHECK( detector ); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + detector.Attach(actor); + + // Connect to signal through type + handle.ConnectSignal( &application, "pinch-detected", functor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit gesture + application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.voidFunctorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTapGestureDetectorTypeRegistry(void) +{ + TestApplication application; + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Register Type + TypeInfo type; + type = TypeRegistry::Get().GetTypeInfo( "TapGestureDetector" ); + DALI_TEST_CHECK( type ); + BaseHandle handle = type.CreateInstance(); + DALI_TEST_CHECK( handle ); + TapGestureDetector detector = TapGestureDetector::DownCast( handle ); + DALI_TEST_CHECK( detector ); + + // Attach actor to detector + SignalData data; + GestureReceivedFunctor functor( data ); + detector.Attach(actor); + + // Connect to signal through type + handle.ConnectSignal( &application, "tap-detected", functor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit gesture + application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f))); + application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f))); + DALI_TEST_EQUALS(true, data.voidFunctorCalled, TEST_LOCATION); + END_TEST; +} + +int UtcDaliTypeRegistryNamedType(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + + // Create a normal actor + BaseHandle actorHandle = typeRegistry.GetTypeInfo( "Actor" ).CreateInstance(); + DALI_TEST_CHECK( actorHandle ); + Actor actor( Actor::DownCast( actorHandle ) ); + DALI_TEST_CHECK( actor ); + unsigned int actorPropertyCount( actor.GetPropertyCount() ); + + // Create Named Actor Type + BaseHandle namedHandle = typeRegistry.GetTypeInfo( "MyNamedActor" ).CreateInstance(); + DALI_TEST_CHECK( namedHandle ); + Actor namedActor( Actor::DownCast( namedHandle ) ); + DALI_TEST_CHECK( namedActor ); + unsigned int namedActorPropertyCount( namedActor.GetPropertyCount() ); + + DALI_TEST_CHECK( namedActorPropertyCount > actorPropertyCount ); + END_TEST; +} + +int UtcDaliTypeInfoGetActionNameP(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + + TypeInfo typeInfo = typeRegistry.GetTypeInfo( "Actor" ); + DALI_TEST_CHECK( typeInfo ); + + DALI_TEST_CHECK( 0 != typeInfo.GetActionCount() ); + + std::string name = typeInfo.GetActionName(0); + + DALI_TEST_EQUALS( name, "show", TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliTypeInfoGetActionNameN(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + + TypeInfo typeInfo = typeRegistry.GetTypeInfo( "Actor" ); + DALI_TEST_CHECK( typeInfo ); + + DALI_TEST_CHECK( 0 != typeInfo.GetActionCount() ); + + std::string name = typeInfo.GetActionName(std::numeric_limits::max()); + + DALI_TEST_EQUALS( 0u, name.size(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliTypeInfoGetSignalNameP(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + + TypeInfo typeInfo = typeRegistry.GetTypeInfo( "Actor" ); + DALI_TEST_CHECK( typeInfo ); + + DALI_TEST_CHECK( 0 != typeInfo.GetSignalCount() ); + + std::string name = typeInfo.GetSignalName(0); + + DALI_TEST_EQUALS( name, "touched", TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliTypeInfoGetSignalNameN(void) +{ + TestApplication application; + TypeRegistry typeRegistry = TypeRegistry::Get(); + + TypeInfo typeInfo = typeRegistry.GetTypeInfo( "Actor" ); + DALI_TEST_CHECK( typeInfo ); + + DALI_TEST_CHECK( 0 != typeInfo.GetSignalCount() ); + + std::string name = typeInfo.GetSignalName(std::numeric_limits::max()); + + DALI_TEST_EQUALS( 0u, name.size(), TEST_LOCATION ); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Uint16Pair.cpp b/automated-tests/src/dali/utc-Dali-Uint16Pair.cpp new file mode 100644 index 0000000..d372a2b --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Uint16Pair.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +#include +#include +#include + +using namespace Dali; + + +int UtcDaliUint16PairConstructor01P(void) +{ + Dali::TestApplication testApp; + + Uint16Pair v; + + DALI_TEST_EQUALS(v.GetX(), 0u, TEST_LOCATION); + DALI_TEST_EQUALS(v.GetY(), 0u, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliUint16PairConstructor02P(void) +{ + Dali::TestApplication testApp; + + Uint16Pair v(10,10); + + DALI_TEST_EQUALS(v.GetX(), 10u, TEST_LOCATION); + DALI_TEST_EQUALS(v.GetY(), 10u, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliUint16PairCopyConstructor01P(void) +{ + Dali::TestApplication testApp; + + Uint16Pair u(5,5); + Uint16Pair v(u); + DALI_TEST_EQUALS(v.GetX(), 5u, TEST_LOCATION); + DALI_TEST_EQUALS(v.GetY(), 5u, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliUint16PairGetWidthP(void) +{ + Dali::TestApplication testApp; + + Uint16Pair v(5,5); + DALI_TEST_EQUALS(v.GetWidth(), 5u, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliUint16PairGetHeightP(void) +{ + Dali::TestApplication testApp; + + Uint16Pair v(5,5); + DALI_TEST_EQUALS(v.GetHeight(), 5u, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliUint16PairGetXP(void) +{ + Dali::TestApplication testApp; + + Uint16Pair v(5,5); + DALI_TEST_EQUALS(v.GetX(), 5u, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliUint16PairGetYP(void) +{ + Dali::TestApplication testApp; + + Uint16Pair v(5,5); + DALI_TEST_EQUALS(v.GetY(), 5u, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliUint16PairEqualsP(void) +{ + Dali::TestApplication testApp; + + Uint16Pair v(5,5); + Uint16Pair u(5,5); + DALI_TEST_EQUALS(v == u, true, TEST_LOCATION); + + v = Uint16Pair(5,4); + u = Uint16Pair(5,5); + DALI_TEST_EQUALS(v == u, false, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliUint16PairNotEqualsP(void) +{ + Dali::TestApplication testApp; + + Uint16Pair v(5,5); + Uint16Pair u(5,5); + DALI_TEST_EQUALS(v != u, false, TEST_LOCATION); + + v = Uint16Pair(5,4); + u = Uint16Pair(5,5); + DALI_TEST_EQUALS(v != u, true, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliUint16PairLessThanP(void) +{ + Dali::TestApplication testApp; + + Uint16Pair u(5,5); + Uint16Pair v(6,6); + DALI_TEST_EQUALS(u < v, true, TEST_LOCATION); + + u = Uint16Pair(0,1); + v = Uint16Pair(1,0); + DALI_TEST_EQUALS(v < u, true, TEST_LOCATION); + + u = Uint16Pair(1,0); + v = Uint16Pair(0,1); + DALI_TEST_EQUALS(v < u, false, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliUint16PairGreaterThanP(void) +{ + Dali::TestApplication testApp; + + Uint16Pair u; + Uint16Pair v; + + u = Uint16Pair(0,1); + v = Uint16Pair(1,0); + DALI_TEST_EQUALS(u > v, true, TEST_LOCATION); + + u = Uint16Pair(1,0); + v = Uint16Pair(0,1); + DALI_TEST_EQUALS(v > u, true, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliUint16PairFromFloatVecP(void) +{ + Dali::TestApplication testApp; + + Dali::Vector2 v2(5.f, 5.f); + + Uint16Pair u = Uint16Pair::FromFloatVec2(v2); + DALI_TEST_EQUALS(u.GetX(), 5u, TEST_LOCATION); + DALI_TEST_EQUALS(u.GetY(), 5u, TEST_LOCATION); + + Dali::Vector3 v3(5.f, 5.f, 5.f); + + u = Uint16Pair::FromFloatVec2(v3); + DALI_TEST_EQUALS(u.GetX(), 5u, TEST_LOCATION); + DALI_TEST_EQUALS(u.GetY(), 5u, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliUint16PairFromFloatArrayP(void) +{ + Dali::TestApplication testApp; + + float array[] = {5.f, 5.f}; + + Uint16Pair u = Uint16Pair::FromFloatArray(array); + DALI_TEST_EQUALS(u.GetX(), 5u, TEST_LOCATION); + DALI_TEST_EQUALS(u.GetY(), 5u, TEST_LOCATION); + + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-Vector.cpp b/automated-tests/src/dali/utc-Dali-Vector.cpp new file mode 100644 index 0000000..0cf200d --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Vector.cpp @@ -0,0 +1,1371 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#define ENABLE_VECTOR_ASSERTS + +#include +#include +#include +#include + +using namespace Dali; + +namespace +{ +const Dali::VectorBase::SizeType ZERO(0); +} + +int UtcDaliEmptyVectorInt(void) +{ + tet_infoline("Testing Dali::Vector"); + + Vector< int > intvector; + + DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION ); + + intvector.Clear(); + DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION ); + + intvector.Release(); + DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVectorInt(void) +{ + tet_infoline("Testing Dali::Vector"); + + Vector< int > intvector; + + DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION ); + + intvector.PushBack( 11 ); + DALI_TEST_EQUALS( static_cast(1), intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(2), intvector.Capacity(), TEST_LOCATION ); + DALI_TEST_EQUALS( 11, intvector[ 0 ], TEST_LOCATION ); + + intvector.PushBack( 99 ); + DALI_TEST_EQUALS( static_cast(2), intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(2), intvector.Capacity(), TEST_LOCATION ); + DALI_TEST_EQUALS( 99, intvector[ 1 ], TEST_LOCATION ); + + intvector.PushBack( 34 ); + DALI_TEST_EQUALS( static_cast(3), intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(6), intvector.Capacity(), TEST_LOCATION ); + DALI_TEST_EQUALS( 11, intvector[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( 99, intvector[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( 34, intvector[ 2 ], TEST_LOCATION ); + + intvector.Clear(); + DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(6), intvector.Capacity(), TEST_LOCATION ); + intvector.PushBack( 123 ); + DALI_TEST_EQUALS( static_cast(1), intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( 123, intvector[ 0 ], TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVectorIntCopy(void) +{ + tet_infoline("Testing Dali::Vector::Copy"); + + Vector< int > intvector; + DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION ); + + intvector.PushBack( 99 ); + intvector.PushBack( 11 ); + intvector.PushBack( 34 ); + + // copy construct + Vector< int > intvector2( intvector ); + + DALI_TEST_EQUALS( intvector2.Count(), intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( intvector2.Capacity(), intvector.Capacity(), TEST_LOCATION ); + DALI_TEST_EQUALS( intvector2[ 0 ], intvector[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( intvector2[ 1 ], intvector[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( intvector2[ 2 ], intvector[ 2 ], TEST_LOCATION ); + + // assign + Vector< int > intvector3; + DALI_TEST_EQUALS( ZERO, intvector3.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, intvector3.Capacity(), TEST_LOCATION ); + intvector2 = intvector3; + DALI_TEST_EQUALS( intvector2.Count(), intvector3.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( intvector2.Capacity(), intvector3.Capacity(), TEST_LOCATION ); + + // copy empty + Vector< int > intvector4; + intvector4.Reserve( 100 ); + DALI_TEST_EQUALS( ZERO, intvector4.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(100), intvector4.Capacity(), TEST_LOCATION ); + intvector3 = intvector4; + DALI_TEST_EQUALS( ZERO, intvector3.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(100), intvector3.Capacity(), TEST_LOCATION ); + + // self copy + intvector4 = intvector4; + DALI_TEST_EQUALS( ZERO, intvector4.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(100), intvector4.Capacity(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVectorIntResize(void) +{ + tet_infoline("Testing Dali::Vector::Resize"); + + Vector< short > vector; + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION ); + + vector.Resize( 10u ); + DALI_TEST_EQUALS( static_cast(10), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(10), vector.Capacity(), TEST_LOCATION ); + + vector.Resize( 4u ); + DALI_TEST_EQUALS( static_cast(4), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(10), vector.Capacity(), TEST_LOCATION ); + + vector.Resize( 4u ); + DALI_TEST_EQUALS( static_cast(4), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(10), vector.Capacity(), TEST_LOCATION ); + + vector.Resize( 0u ); + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(10), vector.Capacity(), TEST_LOCATION ); + + vector.Resize( 12u, 123 ); + DALI_TEST_EQUALS( static_cast(12), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(12), vector.Capacity(), TEST_LOCATION ); + + DALI_TEST_EQUALS( vector[ 0 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 3 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 4 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 5 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 6 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 7 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 8 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 9 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 10 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 11 ], 123, TEST_LOCATION ); + + vector.Resize( 13u, 321 ); + DALI_TEST_EQUALS( static_cast(13), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(13), vector.Capacity(), TEST_LOCATION ); + + DALI_TEST_EQUALS( vector[ 0 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 3 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 4 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 5 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 6 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 7 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 8 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 9 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 10 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 11 ], 123, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 12 ], 321, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVectorIntErase(void) +{ + tet_infoline("Testing Dali::Vector::Erase"); + + Vector< char > vector; + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION ); + vector.PushBack( 1 ); + vector.PushBack( 2 ); + vector.PushBack( 3 ); + vector.PushBack( 4 ); + vector.PushBack( 5 ); + DALI_TEST_EQUALS( static_cast(5), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 1, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 2, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 3, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 3 ], 4, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 4 ], 5, TEST_LOCATION ); + + vector.Erase( vector.Begin() ); + DALI_TEST_EQUALS( static_cast(4), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 2, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 3, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 4, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 3 ], 5, TEST_LOCATION ); + + Vector< char >::Iterator ret = vector.Erase( std::find( vector.Begin(), vector.End(), 4 ) ); + DALI_TEST_EQUALS( static_cast(3), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 2, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 3, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 5, TEST_LOCATION ); + DALI_TEST_EQUALS( *ret, 5, TEST_LOCATION ); + + // try erasing last + vector.PushBack( 99 ); + DALI_TEST_EQUALS( static_cast(4), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 3 ], 99, TEST_LOCATION ); + ret = vector.Erase( vector.End() - 1 ); + DALI_TEST_EQUALS( static_cast(3), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ret, vector.End(), TEST_LOCATION ); + + try + { + // illegal erase, one past the end + vector.Erase( vector.End() ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "(iterator < End())", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + try + { + // illegal erase, one before the begin + vector.Erase( vector.Begin() - 1u ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "(iterator < End()) && (iterator >= Begin())", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + + DALI_TEST_EQUALS( static_cast(3), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 2, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 3, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 5, TEST_LOCATION ); + + vector.Erase( vector.Begin() + 1 ); + DALI_TEST_EQUALS( static_cast(2), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 2, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 5, TEST_LOCATION ); + + vector.Erase( vector.Begin() + 1 ); + DALI_TEST_EQUALS( static_cast(1), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 2, TEST_LOCATION ); + + try + { + // illegal erase, one past the end + vector.Erase( vector.Begin() + 1 ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "(iterator < End())", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + DALI_TEST_EQUALS( static_cast(1), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 2, TEST_LOCATION ); + + vector.Erase( vector.Begin() ); + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + + try + { + // illegal erase, one before the beginning + vector.Erase( vector.Begin() - 1 ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "(iterator < End())", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector.Begin(), vector.End(), TEST_LOCATION ); + + Vector< char >::Iterator endIter = vector.End(); + for( Vector< char >::Iterator iter = vector.Begin(); iter != endIter; ++iter ) + { + tet_result(TET_FAIL); + } + + vector.PushBack( 3 ); + DALI_TEST_EQUALS( static_cast(1), vector.Count(), TEST_LOCATION ); + + vector.Clear(); + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector.Begin(), vector.End(), TEST_LOCATION ); + + endIter = vector.End(); + for( Vector< char >::Iterator iter = vector.Begin(); iter != endIter; ++iter ) + { + tet_result(TET_FAIL); + } + + // test a vector of pointers + Vector< int* > ptrVector; + DALI_TEST_EQUALS( ZERO, ptrVector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ptrVector.Begin(), ptrVector.End(), TEST_LOCATION ); + + int* pointer = NULL; + ptrVector.PushBack( pointer ); + DALI_TEST_EQUALS( static_cast(1), ptrVector.Count(), TEST_LOCATION ); + + Vector< int* >::Iterator ptriter = std::find( ptrVector.Begin(), ptrVector.End(), pointer ); + ptriter = ptrVector.Erase( ptriter ); + DALI_TEST_EQUALS( ZERO, ptrVector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ptrVector.Begin(), ptrVector.End(), TEST_LOCATION ); + DALI_TEST_EQUALS( ptrVector.Begin(), ptriter, TEST_LOCATION ); + END_TEST; +} + + +int UtcDaliVectorDoubleRemove(void) +{ + tet_infoline("Testing Dali::Vector::Remove"); + + Vector< double > vector; + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + + vector.PushBack( 11.1 ); + vector.PushBack( 22.2 ); + vector.PushBack( 33.3 ); + vector.PushBack( 44.4 ); + DALI_TEST_EQUALS( static_cast(4), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 11.1, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 22.2, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 33.3, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 3 ], 44.4, TEST_LOCATION ); + + Vector< double >::Iterator res = std::find( vector.Begin(), vector.End(), 22.2 ); + DALI_TEST_EQUALS( 22.2, *res, TEST_LOCATION ); + vector.Remove( res ); + res = std::find( vector.Begin(), vector.End(), 22.2 ); + DALI_TEST_EQUALS( vector.End(), res, TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(3), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 11.1, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 44.4, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 33.3, TEST_LOCATION ); + + vector.Remove( vector.End() - 1 ); + DALI_TEST_EQUALS( static_cast(2), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 11.1, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 44.4, TEST_LOCATION ); + + vector.Remove( vector.Begin() ); + DALI_TEST_EQUALS( static_cast(1), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 44.4, TEST_LOCATION ); + + try + { + // illegal erase, one past the end + vector.Remove( vector.Begin() + 1 ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "(iterator < End()) && (iterator >= Begin())", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + DALI_TEST_EQUALS( static_cast(1), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 44.4, TEST_LOCATION ); + + vector.Remove( vector.Begin() ); + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + + try + { + // illegal erase, one before the beginning + vector.Remove( vector.Begin() - 1 ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "(iterator < End()) && (iterator >= Begin())", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + END_TEST; +} + +int UtcDaliVectorIntSwap(void) +{ + tet_infoline("Testing Dali::Vector::Swap"); + + Vector< int > intvector; + DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION ); + + intvector.PushBack( 11 ); + intvector.PushBack( 22 ); + intvector.PushBack( 33 ); + DALI_TEST_EQUALS( static_cast(3), intvector.Count(), TEST_LOCATION ); + + Vector< int > intvector2; + DALI_TEST_EQUALS( ZERO, intvector2.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, intvector2.Capacity(), TEST_LOCATION ); + + intvector2.Swap( intvector ); + DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(3), intvector2.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( 11, intvector2[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( 22, intvector2[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( 33, intvector2[ 2 ], TEST_LOCATION ); + + intvector.PushBack( 99 ); + intvector.PushBack( 88 ); + DALI_TEST_EQUALS( static_cast(2), intvector.Count(), TEST_LOCATION ); + + intvector.Swap( intvector2 ); + DALI_TEST_EQUALS( static_cast(2), intvector2.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( 99, intvector2[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( 88, intvector2[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( static_cast(3), intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( 11, intvector[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( 22, intvector[ 1 ], TEST_LOCATION ); + DALI_TEST_EQUALS( 33, intvector[ 2 ], TEST_LOCATION ); + + Vector< int > empty; + intvector.Swap( empty ); + DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVectorIterate(void) +{ + tet_infoline("Testing Dali::Vector::Begin"); + + Vector< float > floatvector; + DALI_TEST_EQUALS( ZERO, floatvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, floatvector.Capacity(), TEST_LOCATION ); + + floatvector.PushBack( 0.9f ); + floatvector.PushBack( 1.1f ); + floatvector.PushBack( 1.2f ); + DALI_TEST_EQUALS( static_cast(3), floatvector.Count(), TEST_LOCATION ); + + Vector< float >::Iterator iter = floatvector.Begin(); + int index = 0; + for( ; iter != floatvector.End(); ++iter, ++index ) + { + std::cout << "value " << *iter << std::endl; + DALI_TEST_EQUALS( *iter, floatvector[ index ], TEST_LOCATION ); + } + DALI_TEST_EQUALS( 3, index, TEST_LOCATION ); + + iter = std::find( floatvector.Begin(), floatvector.End(), 1.1f ); + DALI_TEST_EQUALS( 1.1f, *iter, TEST_LOCATION ); + + floatvector.Clear(); + iter = std::find( floatvector.Begin(), floatvector.End(), 1.1f ); + DALI_TEST_EQUALS( floatvector.End(), iter, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVectorPair(void) +{ + tet_infoline("Testing Dali::Vector< std::pair< int, float > >"); + + Vector< std::pair< int, float > > pairvector; + DALI_TEST_EQUALS( ZERO, pairvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, pairvector.Capacity(), TEST_LOCATION ); + + pairvector.PushBack( std::make_pair( 5, 0.1f ) ); + pairvector.PushBack( std::make_pair( 3, 0.2f ) ); + pairvector.PushBack( std::make_pair( 4, 0.3f ) ); + pairvector.PushBack( std::make_pair( 1, 0.4f ) ); + pairvector.PushBack( std::make_pair( 2, 0.5f ) ); + DALI_TEST_EQUALS( static_cast(5), pairvector.Count(), TEST_LOCATION ); + + Vector< std::pair< int, float > >::Iterator iter = pairvector.Begin(); + int index = 0; + for( ; iter != pairvector.End(); ++iter, ++index ) + { + std::cout << "pair " << (*iter).first << ":" << (*iter).second << std::endl; + DALI_TEST_EQUALS( (*iter).first, pairvector[ index ].first, TEST_LOCATION ); + DALI_TEST_EQUALS( (*iter).second, pairvector[ index ].second, TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliVectorAsserts(void) +{ + tet_infoline("Testing Dali::Vector< int* > exception handling"); + + // empty vector + Vector< int* > pointervector; + try + { + int* value = NULL; + pointervector[ 1 ] = value; + tet_printf("Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result(TET_FAIL); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "VectorBase::mData", TEST_LOCATION ); + } + catch(...) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + try + { + int* value = NULL; + value = pointervector[ 0 ]; + (void)value; // to "use" the value + tet_printf("Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result(TET_FAIL); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "VectorBase::mData", TEST_LOCATION ); + } + catch(...) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + Vector< int* >::Iterator iter = pointervector.Begin(); + if( iter != pointervector.End() ) + { + tet_result(TET_FAIL); + } + + try + { + pointervector.Erase( pointervector.Begin() ); + tet_printf("Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result(TET_FAIL); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "(iterator < End()) && (iterator >= Begin())", TEST_LOCATION ); + } + catch(...) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + iter = pointervector.Begin(); + if( iter != pointervector.End() ) + { + tet_result(TET_FAIL); + } + + try + { + pointervector.Remove( pointervector.Begin() ); + tet_printf("Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result(TET_FAIL); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "(iterator < End()) && (iterator >= Begin())", TEST_LOCATION ); + } + catch(...) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + iter = pointervector.Begin(); + if( iter != pointervector.End() ) + { + tet_result(TET_FAIL); + } + + // reserve 0 space + pointervector.Reserve( 0 ); + iter = pointervector.Begin(); + if( iter != pointervector.End() ) + { + tet_result(TET_FAIL); + } + + // reserve 1 space + pointervector.Reserve( 1 ); + iter = pointervector.Begin(); + if( iter != pointervector.End() ) + { + tet_result(TET_FAIL); + } + + try + { + int* value = NULL; + pointervector[ 1 ] = value; + tet_printf("Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result(TET_FAIL); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "index < VectorBase::Count()", TEST_LOCATION ); + } + catch(...) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + try + { + int* value = pointervector[ 1 ]; + (void)value; // to "use" the value + tet_printf("Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result(TET_FAIL); + } + catch(Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "index < VectorBase::Count()", TEST_LOCATION ); + } + catch(...) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + END_TEST; +} + +int UtcDaliVectorAcidTest(void) +{ + tet_infoline("Testing multiple Dali::Vector's"); + + // create multiple vectors + Vector< std::pair< float, float > > pairvector; + DALI_TEST_EQUALS( ZERO, pairvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, pairvector.Capacity(), TEST_LOCATION ); + Vector< double > doublevector; + DALI_TEST_EQUALS( ZERO, doublevector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, doublevector.Capacity(), TEST_LOCATION ); + Vector< int* > intptrvector; + DALI_TEST_EQUALS( ZERO, intptrvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, intptrvector.Capacity(), TEST_LOCATION ); + Vector< Dali::Actor* > actorptrvector; + DALI_TEST_EQUALS( ZERO, actorptrvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, actorptrvector.Capacity(), TEST_LOCATION ); + Vector< long > longvector; + DALI_TEST_EQUALS( ZERO, longvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, longvector.Capacity(), TEST_LOCATION ); + Vector< char > charvector; + DALI_TEST_EQUALS( ZERO, charvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, charvector.Capacity(), TEST_LOCATION ); + + // add items + static unsigned int acidCount = 10000; + int* ptr = NULL; + for( unsigned int i = 0; i < acidCount; ++i ) + { + ++ptr; + pairvector.PushBack( std::make_pair( i, i ) ); + doublevector.PushBack( (double)i ); + intptrvector.PushBack( (int*)ptr ); + actorptrvector.PushBack( (Dali::Actor*)ptr ); + longvector.PushBack( (long)i ); + charvector.PushBack( (char)i ); + } + DALI_TEST_EQUALS( acidCount, pairvector.Count(), TEST_LOCATION ); + std::size_t pairCapacity = pairvector.Capacity(); + DALI_TEST_EQUALS( acidCount, doublevector.Count(), TEST_LOCATION ); + std::size_t doubleCapacity = doublevector.Capacity(); + DALI_TEST_EQUALS( acidCount, intptrvector.Count(), TEST_LOCATION ); + std::size_t intptrCapacity = intptrvector.Capacity(); + DALI_TEST_EQUALS( acidCount, actorptrvector.Count(), TEST_LOCATION ); + std::size_t actorptrCapacity = actorptrvector.Capacity(); + DALI_TEST_EQUALS( acidCount, longvector.Count(), TEST_LOCATION ); + std::size_t longCapacity = longvector.Capacity(); + DALI_TEST_EQUALS( acidCount, charvector.Count(), TEST_LOCATION ); + std::size_t charCapacity = charvector.Capacity(); + + tet_printf("Dali::Vector< pair > capacity after %d pushbacks is %d", acidCount, pairCapacity ); + tet_printf("Dali::Vector< double > capacity after %d pushbacks is %d", acidCount, doubleCapacity ); + tet_printf("Dali::Vector< int* > capacity after %d pushbacks is %d", acidCount, intptrCapacity ); + tet_printf("Dali::Vector< Actor* > capacity after %d pushbacks is %d", acidCount, actorptrCapacity ); + tet_printf("Dali::Vector< long > capacity after %d pushbacks is %d", acidCount, longCapacity ); + tet_printf("Dali::Vector< char > capacity after %d pushbacks is %d", acidCount, charCapacity ); + + // erase items + for( unsigned int i = 0; i < acidCount; ++i ) + { + pairvector.Erase( pairvector.Begin() + ( i % pairvector.Count() ) ); + doublevector.Erase( doublevector.Begin() + ( i % doublevector.Count() ) ); + intptrvector.Erase( intptrvector.Begin() + ( i % intptrvector.Count() ) ); + actorptrvector.Erase( actorptrvector.Begin() + ( i % actorptrvector.Count() ) ); + longvector.Erase( longvector.Begin() + ( i % longvector.Count() ) ); + charvector.Erase( charvector.Begin() + ( i % charvector.Count() ) ); + } + DALI_TEST_EQUALS( ZERO, pairvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( pairCapacity, pairvector.Capacity(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, doublevector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( doubleCapacity, doublevector.Capacity(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, intptrvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( intptrCapacity, intptrvector.Capacity(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, actorptrvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( actorptrCapacity, actorptrvector.Capacity(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, longvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( longCapacity, longvector.Capacity(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, charvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( charCapacity, charvector.Capacity(), TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliVectorPushBack(void) +{ + tet_infoline( "Testing Dali::Vector< int* >PushBack(Element)" ); + + Vector vector; + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION ); + + vector.Reserve( 2u ); + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( 2u, vector.Capacity(), TEST_LOCATION ); + + vector.PushBack( 0u ); + vector.PushBack( 1u ); + vector.PushBack( 2u ); + + DALI_TEST_EQUALS( 3u, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( 6u, vector.Capacity(), TEST_LOCATION ); + + vector.PushBack( 3u ); + + DALI_TEST_EQUALS( 4u, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( 6u, vector.Capacity(), TEST_LOCATION ); + + DALI_TEST_EQUALS( 0u, vector[0u], TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, vector[1u], TEST_LOCATION ); + DALI_TEST_EQUALS( 2u, vector[2u], TEST_LOCATION ); + DALI_TEST_EQUALS( 3u, vector[3u], TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliVectorInsert01(void) +{ + tet_infoline( "Testing Dali::Vector< int* >Insert(Iterator, Element)" ); + + // Test order of array inserted-into: + Vector< unsigned int > orderedVector; + orderedVector.PushBack( 9u ); + for( unsigned int i = 8u; i <= 8u; --i ) + { + orderedVector.Insert( orderedVector.Begin(), i ); + DALI_TEST_EQUALS( 10u - i, orderedVector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( i, orderedVector[0u], TEST_LOCATION ); + } + + for( unsigned int i = 0u; i < 10u; ++i ) + { + DALI_TEST_EQUALS( i, orderedVector[i], TEST_LOCATION ); + } + + // Test insertion out of range in non-empty array throws: + try + { + orderedVector.Insert( orderedVector.Begin() + 99u, 99u ); + tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "( at <= End() ) && ( at >= Begin() )", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf( "Assertion test failed - wrong Exception\n" ); + tet_result( TET_FAIL ); + } + + try + { + orderedVector.Insert( orderedVector.Begin() - 1u, 99u ); + tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result( TET_FAIL ); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "( at <= End() ) && ( at >= Begin() )", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf( "Assertion test failed - wrong Exception\n" ); + tet_result( TET_FAIL ); + } + + // Test insertion part-way through a largish array retains ordering: + + // Build vector with hole in sequence: + Vector< unsigned int > longerVector; + const unsigned int insertionPoint = 131571u; + const unsigned int finalLength = 262143u; + for( unsigned int i = 0u; i < insertionPoint; ++i ) + { + longerVector.PushBack( i ); + } + for( unsigned int i = insertionPoint; i < finalLength; ++i ) + { + longerVector.PushBack( i + 1 ); + } + + // Fill the hole in the sequence: + longerVector.Insert( longerVector.Begin() + insertionPoint, insertionPoint ); + + // Check the sequence is monotonically increasing by one every time: + for( unsigned int i = 0u; i <= finalLength; ++i ) + { + DALI_TEST_EQUALS( i, longerVector[i], TEST_LOCATION ); + } + + // Insert into an empty vector + Vector< unsigned int > vector; + + vector.Insert( vector.End(), orderedVector.Begin(), orderedVector.End() ); + for( unsigned int i = 0u; i < 10u; ++i ) + { + DALI_TEST_EQUALS( i, vector[i], TEST_LOCATION ); + } + + vector.Clear(); + vector.Insert( vector.Begin(), orderedVector.Begin(), orderedVector.End() ); + for( unsigned int i = 0u; i < 10u; ++i ) + { + DALI_TEST_EQUALS( i, vector[i], TEST_LOCATION ); + } + + // Insert nothing. + vector.Insert( vector.Begin(), orderedVector.Begin(), orderedVector.Begin() ); + for( unsigned int i = 0u; i < 10u; ++i ) + { + DALI_TEST_EQUALS( i, vector[i], TEST_LOCATION ); + } + + vector.Insert( vector.Begin() + 5, vector.Begin() + 5, vector.Begin() + 5 ); + for( unsigned int i = 0u; i < 10u; ++i ) + { + DALI_TEST_EQUALS( i, vector[i], TEST_LOCATION ); + } + + // AutoInsert + vector.Clear(); + vector.PushBack( 0u ); + vector.PushBack( 1u ); + vector.PushBack( 2u ); + vector.PushBack( 3u ); + + vector.Insert( vector.Begin() + 2, vector.Begin(), vector.End() ); + DALI_TEST_EQUALS( 8u, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( 0u, vector[0u], TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, vector[1u], TEST_LOCATION ); + DALI_TEST_EQUALS( 0u, vector[2u], TEST_LOCATION ); + DALI_TEST_EQUALS( 1u, vector[3u], TEST_LOCATION ); + DALI_TEST_EQUALS( 2u, vector[4u], TEST_LOCATION ); + DALI_TEST_EQUALS( 3u, vector[5u], TEST_LOCATION ); + DALI_TEST_EQUALS( 2u, vector[6u], TEST_LOCATION ); + DALI_TEST_EQUALS( 3u, vector[7u], TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliVectorInsert02(void) +{ + tet_infoline("Testing Dali::Vector::Insert(Iterator,Iterator,Iterator)"); + + Vector< char > vector; + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION ); + vector.PushBack( 1 ); + vector.PushBack( 2 ); + vector.PushBack( 3 ); + vector.PushBack( 4 ); + vector.PushBack( 5 ); + + Vector< char > vector2; + DALI_TEST_EQUALS( ZERO, vector2.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, vector2.Capacity(), TEST_LOCATION ); + vector2.PushBack( 6 ); + vector2.PushBack( 7 ); + vector2.PushBack( 8 ); + vector2.PushBack( 9 ); + vector2.PushBack( 10 ); + + // Test insert at end + vector.Insert( vector.End(), vector2.Begin(), vector2.Begin() + 1u ); + DALI_TEST_EQUALS( static_cast(6), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 1, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 2, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 3, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 3 ], 4, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 4 ], 5, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 5 ], 6, TEST_LOCATION ); + + // Test insert at begin + vector.Insert( vector.Begin(), vector2.Begin()+1, vector2.Begin() + 2u ); + DALI_TEST_EQUALS( static_cast(7), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 7, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 1, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 2, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 3 ], 3, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 4 ], 4, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 5 ], 5, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 6 ], 6, TEST_LOCATION ); + + // Test insert in the middle + vector.Insert( vector.Begin() + 3, vector2.Begin()+3, vector2.End() ); + DALI_TEST_EQUALS( static_cast(9), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 7, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 1, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 2, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 3 ], 9, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 4 ], 10, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 5 ], 3, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 6 ], 4, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 7 ], 5, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 8 ], 6, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVectorIntInsertAssert(void) +{ + tet_infoline("Testing Dali::Vector::Insert(Iterator,Iterator,Iterator) asserts"); + + Vector< char > vector; + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION ); + vector.PushBack( 1 ); + vector.PushBack( 2 ); + + Vector< char > vector2; + DALI_TEST_EQUALS( ZERO, vector2.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, vector2.Capacity(), TEST_LOCATION ); + vector2.PushBack( 6 ); + vector2.PushBack( 7 ); + vector2.PushBack( 8 ); + vector2.PushBack( 9 ); + vector2.PushBack( 10 ); + + try + { + vector.Insert( vector.Begin() + 3u, vector2.Begin(), vector2.End() ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "( at <= End() ) && ( at >= Begin() )", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + try + { + vector.Insert( vector.Begin() - 1u, vector2.Begin(), vector2.End() ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "( at <= End() ) && ( at >= Begin() )", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + try + { + vector.Insert( vector.End(), vector2.End(), vector2.Begin() ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "( from <= to )", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + END_TEST; + } + + +int UtcDaliVectorIntEraseRange(void) +{ + tet_infoline("Testing Dali::Vector::Erase(Iterator,Iterator)"); + + Vector< char > vector; + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION ); + + // Try to delete from empty vector. + + vector.Erase( vector.Begin(), vector.End() ); + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION ); + + vector.PushBack( 1 ); + vector.PushBack( 2 ); + vector.PushBack( 3 ); + vector.PushBack( 4 ); + vector.PushBack( 5 ); + DALI_TEST_EQUALS( static_cast(5), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 1, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 2, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 3, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 3 ], 4, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 4 ], 5, TEST_LOCATION ); + + Vector< char >::Iterator ret; + + ret = vector.Erase( vector.Begin() + 1u, vector.Begin() + 2u ); + DALI_TEST_EQUALS( static_cast(4), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 1, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 3, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 4, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 3 ], 5, TEST_LOCATION ); + DALI_TEST_EQUALS( *ret, 3, TEST_LOCATION ); + + ret = vector.Erase( vector.Begin(), vector.Begin() + 2 ); + DALI_TEST_EQUALS( static_cast(2), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 4, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 5, TEST_LOCATION ); + DALI_TEST_EQUALS( *ret, 4, TEST_LOCATION ); + + // try erasing last + vector.PushBack( 99 ); + DALI_TEST_EQUALS( static_cast(3), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 99, TEST_LOCATION ); + ret = vector.Erase( vector.Begin() + 1u, vector.End() ); + DALI_TEST_EQUALS( static_cast(1), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 4, TEST_LOCATION ); + DALI_TEST_EQUALS( ret, vector.End(), TEST_LOCATION ); + + // try erasing all + vector.PushBack( 100 ); + vector.PushBack( 101 ); + vector.PushBack( 102 ); + + DALI_TEST_EQUALS( static_cast(4), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 4, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 100, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 101, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 3 ], 102, TEST_LOCATION ); + + ret = vector.Erase( vector.Begin(), vector.End() ); + DALI_TEST_EQUALS( static_cast(0), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ret, vector.End(), TEST_LOCATION ); + + // try erase from Iterator to the same Iterator. + vector.PushBack( 100 ); + vector.PushBack( 101 ); + vector.PushBack( 102 ); + + DALI_TEST_EQUALS( static_cast(3), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 100, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 101, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 102, TEST_LOCATION ); + + ret = vector.Erase( vector.Begin() + 1, vector.Begin() + 1 ); + + DALI_TEST_EQUALS( static_cast(3), vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 0 ], 100, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 1 ], 101, TEST_LOCATION ); + DALI_TEST_EQUALS( vector[ 2 ], 102, TEST_LOCATION ); + + DALI_TEST_EQUALS( *ret, 101, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliVectorIntEraseRangeAssert(void) +{ + tet_infoline("Testing Dali::Vector::Erase(Iterator,Iterator) asserts"); + + Vector< char > vector; + DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION ); + + + // Add some elements. + vector.PushBack( 1 ); + vector.PushBack( 2 ); + + // first out of bounds + try + { + vector.Erase( vector.Begin() + 3u, vector.Begin() + 4u ); + tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "( first <= End() ) && ( first >= Begin() )", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + try + { + vector.Erase( vector.Begin() - 1u, vector.End() ); + tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "( first <= End() ) && ( first >= Begin() )", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + // last out of bounds + + try + { + vector.Erase( vector.Begin(), vector.Begin() + 3u ); + tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "( last <= End() ) && ( last >= Begin() )", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + try + { + vector.Erase( vector.Begin(), vector.Begin() - 1u ); + tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "( last <= End() ) && ( last >= Begin() )", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + vector.PushBack( 3 ); + + // first > last + try + { + vector.Erase( vector.Begin() + 2u, vector.Begin() + 1u ); + tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION ); + tet_result(TET_FAIL); + } + catch( Dali::DaliException& e ) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "( first <= last )", TEST_LOCATION ); + } + catch( ... ) + { + tet_printf("Assertion test failed - wrong Exception\n" ); + tet_result(TET_FAIL); + } + + END_TEST; +} + +int UtcDaliVectorVector2P(void) +{ + tet_infoline("Testing Dali::Vector< Vector2 >"); + + Vector< Vector2 > classvector; + DALI_TEST_EQUALS( ZERO, classvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, classvector.Capacity(), TEST_LOCATION ); + + classvector.PushBack( Vector2() ); + + DALI_TEST_EQUALS( 1u, classvector.Count(), TEST_LOCATION ); + DALI_TEST_GREATER( classvector.Capacity(), ZERO, TEST_LOCATION ); + + classvector.PushBack( Vector2( 0.1f, 0.2f ) ); + + DALI_TEST_EQUALS( 2u, classvector.Count(), TEST_LOCATION ); + + DALI_TEST_EQUALS( Vector2(), classvector[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( Vector2( 0.1f, 0.2f ), classvector[ 1 ], TEST_LOCATION ); + + tet_result(TET_PASS); // for now + END_TEST; +} + +int UtcDaliVectorVector3P(void) +{ + tet_infoline("Testing Dali::Vector< Vector3 >"); + + Vector< Vector3 > classvector; + DALI_TEST_EQUALS( ZERO, classvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, classvector.Capacity(), TEST_LOCATION ); + + classvector.PushBack( Vector3() ); + + DALI_TEST_EQUALS( 1u, classvector.Count(), TEST_LOCATION ); + DALI_TEST_GREATER( classvector.Capacity(), ZERO, TEST_LOCATION ); + + classvector.PushBack( Vector3( 0.1f, 0.2f, 0.3f ) ); + + DALI_TEST_EQUALS( 2u, classvector.Count(), TEST_LOCATION ); + + DALI_TEST_EQUALS( Vector3(), classvector[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( Vector3( 0.1f, 0.2f, 0.3f ), classvector[ 1 ], TEST_LOCATION ); + + tet_result(TET_PASS); // for now + END_TEST; +} + +int UtcDaliVectorMatrixP(void) +{ + tet_infoline("Testing Dali::Vector< Matrix >"); + + Vector< Matrix > classvector; + DALI_TEST_EQUALS( ZERO, classvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, classvector.Capacity(), TEST_LOCATION ); + + classvector.PushBack( Matrix() ); + + DALI_TEST_EQUALS( 1u, classvector.Count(), TEST_LOCATION ); + DALI_TEST_GREATER( classvector.Capacity(), ZERO, TEST_LOCATION ); + + classvector.PushBack( Matrix::IDENTITY ); + + DALI_TEST_EQUALS( 2u, classvector.Count(), TEST_LOCATION ); + + DALI_TEST_EQUALS( Matrix(), classvector[ 0 ], TEST_LOCATION ); + DALI_TEST_EQUALS( Matrix::IDENTITY, classvector[ 1 ], TEST_LOCATION ); + + tet_result(TET_PASS); // for now + END_TEST; +} + +/* + * this does not compile at the moment + * Vector< Actor > classvector; this does not compile yet either + * +namespace +{ + +bool gConstructorCalled = false; +bool gDestructorCalled = false; + +struct ComplexType +{ + ComplexType() + { + gConstructorCalled = true; + } + ~ComplexType() + { + gDestructorCalled = true; + } +}; + +} // anonymous namespace + +int UtcDaliVectorComplex( void) +{ + tet_infoline("Testing Dali::Vector< ComplexType > "); + + Vector< ComplexType > classvector; + DALI_TEST_EQUALS( ZERO, classvector.Count(), TEST_LOCATION ); + DALI_TEST_EQUALS( ZERO, classvector.Capacity(), TEST_LOCATION ); + + DALI_TEST_EQUALS( false, gConstructorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( false, gDestructorCalled, TEST_LOCATION ); + classvector.PushBack( ComplexType() ); + DALI_TEST_EQUALS( true, gConstructorCalled, TEST_LOCATION ); + classvector.Clear(); + DALI_TEST_EQUALS( true, gDestructorCalled, TEST_LOCATION ); + tet_result(TET_PASS); // for now + END_TEST; +} +*/ diff --git a/automated-tests/src/dali/utc-Dali-Vector2.cpp b/automated-tests/src/dali/utc-Dali-Vector2.cpp new file mode 100644 index 0000000..822a6ae --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Vector2.cpp @@ -0,0 +1,609 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include // isfinite + +#include +#include +#include + +using namespace Dali; + +void utc_dali_vector2_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_vector2_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliVector2Constructor01P(void) +{ + TestApplication application; + Vector2 vec2; + DALI_TEST_EQUALS(vec2.x, 0.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(vec2.y, 0.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2Constructor02P(void) +{ + TestApplication application; + Vector2 vec2(1.f,1.f); + DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2Constructor03P(void) +{ + TestApplication application; + float array[] = {1.f,1.f}; + Vector2 vec2(array); + DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2Constructor04P(void) +{ + TestApplication application; + Vector3 vec3(1.f,1.f,1.f); + Vector3 vec2(vec3); + DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2Constructor05P(void) +{ + TestApplication application; + Vector4 vec4(1.f,1.f,1.f,1.f); + Vector2 vec2(vec4); + DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2CopyConstructor01P(void) +{ + TestApplication application; + float array[] = {1.f,1.f}; + Vector2 vec2; + vec2 = array; + DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2CopyConstructor02P(void) +{ + TestApplication application; + Vector3 vec3(1.f,1.f,1.f); + Vector3 vec2; + vec2 = vec3; + DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2CopyConstructor03P(void) +{ + TestApplication application; + Vector4 vec4(1.f,1.f,1.f,1.f); + Vector3 vec2; + vec2 = vec4; + DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION); + DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2AssignP(void) +{ + TestApplication application; + Vector2 v1(10.0f, 20.0f); + Vector2 r0(11.0f, 22.0f); + + v1 = r0; + DALI_TEST_EQUALS(v1, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2AssignP02(void) +{ + TestApplication application; + Vector2 v1(10.0f, 20.0f); + Vector4 r0(11.0f, 22.0f, 33.f, 44.f); + + v1 = r0; + DALI_TEST_EQUALS(v1, Vector2(r0.x, r0.y), TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2AssignP03(void) +{ + TestApplication application; + Vector2 v1(10.0f, 20.0f); + Vector3 r0(11.0f, 22.0f, 33.f); + + v1 = r0; + DALI_TEST_EQUALS(v1, Vector2(r0.x, r0.y), TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2AddP(void) +{ + TestApplication application; + Vector2 v0(1.0f, 2.0f); + Vector2 v1(10.0f, 20.0f); + Vector2 r0(11.0f, 22.0f); + + Vector2 v2 = v0+v1; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2AddAssignP(void) +{ + TestApplication application; + Vector2 v0(1.0f, 2.0f); + Vector2 v1(10.0f, 20.0f); + Vector2 r0(11.0f, 22.0f); + + v0 += v1; + DALI_TEST_EQUALS(v0, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2SubtractP(void) +{ + TestApplication application; + Vector2 v0(11.0f, 22.0f); + Vector2 v1(10.0f, 20.0f); + Vector2 r0(1.0f, 2.0f); + + Vector2 v2 = v0-v1; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector2SubtractAssignP(void) +{ + TestApplication application; + Vector2 v0(11.0f, 22.0f); + Vector2 v1(10.0f, 20.0f); + Vector2 r0(1.0f, 2.0f); + + v0 -= v1; + DALI_TEST_EQUALS(v0, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2NegateP(void) +{ + TestApplication application; + Vector2 v1(10.0f, 20.0f); + Vector2 r0(-10.0f, -20.0f); + + Vector2 v2 = -v1; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2Multiply01P(void) +{ + TestApplication application; + Vector2 v0(2.0f, 3.0f); + Vector2 v1(10.0f, 20.0f); + Vector2 r0(20.0f, 60.0f); + + Vector2 v2 = v0 * v1; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector2Multiply02P(void) +{ + TestApplication application; + Vector2 v0(2.0f, 3.0f); + Vector2 r0(20.0f, 30.0f); + + Vector2 v2 = v0 * 10.f; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector2MultiplyAssign01P(void) +{ + TestApplication application; + Vector2 v0(2.0f, 3.0f); + Vector2 v1(10.0f, 20.0f); + Vector2 r0(20.0f, 60.0f); + + v0 *= v1; + DALI_TEST_EQUALS(v0, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2MultiplyAssign02P(void) +{ + TestApplication application; + Vector2 v0(2.0f, 3.0f); + Vector2 r0(20.0f, 30.0f); + + v0 *= 10.f; + DALI_TEST_EQUALS(v0, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2Divide01P(void) +{ + TestApplication application; + Vector2 v0(1.0f, 1.0f); + Vector2 v1(2.0f, 3.0f); + Vector2 v2(4.0f, 9.0f); + + DALI_TEST_EQUALS( v0/v0, v0, TEST_LOCATION); + DALI_TEST_EQUALS( v1/v0, v1, TEST_LOCATION); + DALI_TEST_EQUALS( v1/v1, v0, TEST_LOCATION); + DALI_TEST_EQUALS( v2/v1, v1, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector2Divide02P(void) +{ + TestApplication application; + Vector2 v0(1.0f, 1.0f); + Vector2 v1(3.0f, 3.0f); + Vector2 v2(9.0f, 9.0f); + + DALI_TEST_EQUALS( v0/1.f, v0, TEST_LOCATION); + DALI_TEST_EQUALS( v1/1.f, v1, TEST_LOCATION); + DALI_TEST_EQUALS( v1/3.f, v0, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector2DivideAssign01P(void) +{ + TestApplication application; + Vector2 v0(1.0f, 1.0f); + Vector2 v1(2.0f, 3.0f); + Vector2 v2(4.0f, 9.0f); + + Vector2 v4(v0); + v4 /= v0; + DALI_TEST_EQUALS(v4, v0, TEST_LOCATION); + + Vector2 v5(v1); + v5 /= v0; + DALI_TEST_EQUALS(v5, v1, TEST_LOCATION); + + Vector2 v6(v1); + v6 /= v6; + DALI_TEST_EQUALS(v6, v0, TEST_LOCATION); + + v2 /= v1; + DALI_TEST_EQUALS(v2, v1, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector2DivideAssign02P(void) +{ + TestApplication application; + Vector2 v0(1.0f, 1.0f); + Vector2 v1(3.0f, 3.0f); + + Vector2 v4(v0); + v4 /= 1.f; + DALI_TEST_EQUALS(v4, v0, TEST_LOCATION); + + Vector2 v5(v1); + v5 /= 1.f; + DALI_TEST_EQUALS(v5, v1, TEST_LOCATION); + + Vector2 v6(v1); + v6 /= 3.f; + DALI_TEST_EQUALS(v6, v0, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector2EqualsP(void) +{ + TestApplication application; + Vector2 v0(1.0f, 2.0f); + Vector2 v1(1.0f, 2.0f); + + DALI_TEST_CHECK(v0 == v1); + + END_TEST; +} + +int UtcDaliVector2NotEqualsP(void) +{ + TestApplication application; + Vector2 v0(1.0f, 2.0f); + Vector2 v1(1.0f, 2.0f); + + Vector2 v2 = Vector2(0.0f, 2.0f); + DALI_TEST_CHECK(v0 != v2); + + v2 = Vector2(1.0f, 0.0f); + DALI_TEST_CHECK(v0 != v2); + + v2 = Vector2(1.0f, 77.0f); + DALI_TEST_CHECK(v0 != v2); + + v2 = Vector2(33.0f, 44.0f); + DALI_TEST_CHECK(v0 != v2); + END_TEST; +} + +int UtcDaliVector2OperatorSubscriptP(void) +{ + TestApplication application; + Vector2 testVector(1.0f, 2.0f); + + // read array subscripts + DALI_TEST_EQUALS( testVector[0], 1.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector[1], 2.0f, TEST_LOCATION ); + + // write array subscripts/read struct memebers + testVector[0] = 3.0f; + testVector[1] = 4.0f; + + DALI_TEST_EQUALS( testVector.x, 3.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector.y, 4.0f, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliVector2OperatorSubscriptN(void) +{ + TestApplication application; + Vector2 testVector(1.0f, 2.0f); + + try + { + float& w = testVector[4]; + if(w==0.0f); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "Vector element index out of bounds", TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliVector2OperatorConstSubscriptP(void) +{ + TestApplication application; + const Vector2 testVector2(3.0f, 4.0f); + const float& x = testVector2[0]; + const float& y = testVector2[1]; + DALI_TEST_EQUALS( x, 3.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( y, 4.0f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVector2OperatorConstSubscriptN(void) +{ + TestApplication application; + const Vector2 testVector2(3.0f, 4.0f); + + try + { + const float& w = testVector2[4]; + if(w==0.0f); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "Vector element index out of bounds" , TEST_LOCATION); + } + + + END_TEST; +} + + +int UtcDaliVector2LengthP(void) +{ + TestApplication application; + Vector2 v(1.0f, 2.0f); + DALI_TEST_EQUALS(v.Length(), sqrtf(v.x*v.x + v.y*v.y), 0.001f, TEST_LOCATION); + + Vector2 v1(0.0f, 0.0f); + DALI_TEST_EQUALS(v1.Length(), 0.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2LengthSquaredP(void) +{ + TestApplication application; + Vector2 v(1.0f, 2.0f); + DALI_TEST_EQUALS(v.LengthSquared(), v.x*v.x + v.y*v.y, 0.001f, TEST_LOCATION); + + Vector2 v1(0.0f, 0.0f); + DALI_TEST_EQUALS(v1.LengthSquared(), 0.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2NormalizeP(void) +{ + TestApplication application; + for (float f=0.0f; f<6.0f; f+=1.0f) + { + Vector2 v(cosf(f)*10.0f, cosf(f+1.0f)*10.0f); + v.Normalize(); + DALI_TEST_EQUALS(v.LengthSquared(), 1.0f, 0.001f, TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliVector2NormalizeN(void) +{ + TestApplication application; + Vector2 v(0.0f, 0.0f); + v.Normalize(); + DALI_TEST_EQUALS(v.LengthSquared(), 0.0f, 0.00001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2ClampVector2P(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Vector2::Clamp( const Vector2& v, const Vector2& min, const Vector2& max )"); + + Vector2 v0(2.0f, 0.8f); + Vector2 v1(-1.0f, 2.0f); + Vector2 v2(10.0f, 5.0f); + Vector2 v3(8.0f, 10.0f); + Vector2 v4(4.9f, 5.1f); + Vector2 min(1.0f, 4.0f); + Vector2 max(9.0f, 6.0f); + + v0.Clamp( min, max ); + v1.Clamp( min, max ); + v2.Clamp( min, max ); + v3.Clamp( min, max ); + v4.Clamp( min, max ); + + DALI_TEST_EQUALS( v0, Vector2(2.0f, 4.0f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( v1, Vector2(1.0f, 4.0f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( v2, Vector2(9.0f, 5.0f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( v3, Vector2(8.0f, 6.0f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( v4, Vector2(4.9f, 5.1f), 0.01f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVector2AsFloatP(void) +{ + TestApplication application; + Vector2 vec2(1.f,1.f); + float* p = vec2.AsFloat(); + + DALI_TEST_EQUALS( p[0], 1.f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( p[1], 1.f, 0.01f, TEST_LOCATION ); + + p[0] = 2.f; + p[1] = 2.f; + + DALI_TEST_EQUALS( p[0], 2.f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( p[1], 2.f, 0.01f, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliVector2ConstAsFloatP(void) +{ + TestApplication application; + Vector2 vec2(1.f,1.f); + const float* p = vec2.AsFloat(); + + DALI_TEST_EQUALS( p[0], 1.f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( p[1], 1.f, 0.01f, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliVector2XWidthP(void) +{ + TestApplication application; + Vector2 vec2(1.f,1.f); + + DALI_TEST_EQUALS( vec2.x, 1.f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( vec2.width, 1.f, 0.01f, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliVector2YHeightP(void) +{ + TestApplication application; + Vector2 vec2(1.f,1.f); + + DALI_TEST_EQUALS( vec2.y, 1.f, 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( vec2.height, 1.f, 0.01f, TEST_LOCATION ); + + END_TEST; +} + +int UtcDaliVector2OStreamOperatorP(void) +{ + TestApplication application; + std::ostringstream oss; + + Vector2 vector(1, 2); + + oss << vector; + + std::string expectedOutput = "[1, 2]"; + + DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION); + END_TEST; +} + + +int UtcDaliVector2MaxP(void) +{ + TestApplication application; + Vector2 v0(2.0f, 1.0f); + Vector2 v1(1.0f, 2.0f); + + DALI_TEST_EQUALS(Max(v0, v1), Vector2(2.0f, 2.0f), 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2MinP(void) +{ + TestApplication application; + Vector2 v0(2.0f, 1.0f); + Vector2 v1(1.0f, 2.0f); + + DALI_TEST_EQUALS(Min(v0, v1), Vector2(1.0f, 1.0f), 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector2ClampP(void) +{ + TestApplication application; + tet_infoline("Testing Dali::Vector2::Clamp( const Vector2& v, const float& min, const float& max )"); + + Vector2 v0(2.0f, 0.8f); + Vector2 v1(-1.0f, 2.0f); + + DALI_TEST_EQUALS( Clamp( v0, 0.9f, 1.1f ), Vector2(1.1f, 0.9f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( Clamp( v1, 1.0f, 1.0f ), Vector2(1.0f, 1.0f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( Clamp( v1, 0.0f, 3.0f ), Vector2(0.0f, 2.0f), 0.01f, TEST_LOCATION ); + END_TEST; +} + diff --git a/automated-tests/src/dali/utc-Dali-Vector3.cpp b/automated-tests/src/dali/utc-Dali-Vector3.cpp new file mode 100644 index 0000000..f96a7b2 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Vector3.cpp @@ -0,0 +1,660 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include // isfinite + +#include +#include +#include + +using namespace Dali; + +void utc_dali_vector3_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_vector3_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliVector3Constructor01P(void) +{ + TestApplication application; + Vector3 va; + DALI_TEST_EQUALS(va.x, 0.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(va.y, 0.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(va.z, 0.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Constructor02P(void) +{ + TestApplication application; + Vector3 va(1.f, 1.f, 1.f); + DALI_TEST_EQUALS(va.x, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(va.y, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(va.z, 1.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Constructor03P(void) +{ + TestApplication application; + float array [] = {1.f, 1.f, 1.f}; + Vector3 va(array); + DALI_TEST_EQUALS(va.x, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(va.y, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(va.z, 1.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Constructor04P(void) +{ + TestApplication application; + Vector2 vec2(1.f,1.f); + Vector3 va(vec2); + DALI_TEST_EQUALS(va.x, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(va.y, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(va.z, 0.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Constructor05P(void) +{ + TestApplication application; + Vector4 vec4(1.f, 1.f, 1.f, 1.f); + Vector3 va(vec4); + DALI_TEST_EQUALS(va.x, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(va.y, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(va.z, 1.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Assign01P(void) +{ + TestApplication application; + Vector3 v0; + const float array[] = { 1.0f, 2.0f, 3.0f }; + v0 = (const float*)array; + + DALI_TEST_EQUALS(v0.x, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.y, 2.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.z, 3.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Assign02P(void) +{ + TestApplication application; + Vector2 vec2_q(1.0f, 2.0f); + Vector3 vec3a; + vec3a = vec2_q; + + DALI_TEST_EQUALS(vec3a.x, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(vec3a.y, 2.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(vec3a.z, 0.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Assign03P(void) +{ + TestApplication application; + Vector4 vec4_q(4.0f, 3.0f, 2.0f, 1.0f); + Vector3 vec3b; + vec3b = vec4_q; + + DALI_TEST_EQUALS(vec3b.x, 4.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(vec3b.y, 3.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(vec3b.z, 2.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Add01P(void) +{ + TestApplication application; + Vector3 v0(1.0f, 2.0f, 3.0f); + Vector3 v1(10.0f, 20.0f, 30.0f); + Vector3 r0(11.0f, 22.0f, 33.0f); + + Vector3 v2 = v0+v1; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector3Add02P(void) +{ + TestApplication application; + Vector3 v0(1.0f, 2.0f, 3.0f); + Vector3 v1(10.0f, 20.0f, 30.0f); + Vector3 r0(11.0f, 22.0f, 33.0f); + + v0 += v1; + DALI_TEST_EQUALS(v0, r0, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector3Subtract01P(void) +{ + TestApplication application; + Vector3 v0(11.0f, 22.0f, 33.0f); + Vector3 v1(10.0f, 20.0f, 30.0f); + Vector3 r0(1.0f, 2.0f, 3.0f); + + Vector3 v2 = v0-v1; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector3Subtract02P(void) +{ + TestApplication application; + Vector3 v0(11.0f, 22.0f, 33.0f); + Vector3 v1(10.0f, 20.0f, 30.0f); + Vector3 r0(1.0f, 2.0f, 3.0f); + + v0 -= v1; + DALI_TEST_EQUALS(v0, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Multiply01P(void) +{ + TestApplication application; + Vector3 v0(2.0f, 3.0f, 4.0f); + Vector3 v1(10.0f, 20.0f, 30.0f); + Vector3 r0(20.0f, 60.0f, 120.0f); + + Vector3 v2 = v0 * v1; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Multiply02P(void) +{ + TestApplication application; + Vector3 v0(2.0f, 3.0f, 4.0f); + Vector3 r0(20.0f, 30.0f, 40.0f); + Vector3 v2 = v0 * 10.f; + DALI_TEST_EQUALS(v2, r0, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Multiply03P(void) +{ + TestApplication application; + Vector3 v0(2.0f, 3.0f, 4.0f); + Vector3 v1(10.0f, 20.0f, 30.0f); + Vector3 r0(20.0f, 60.0f, 120.0f); + v0 *= v1; + DALI_TEST_EQUALS(v0, r0, 0.001, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Multiply04P(void) +{ + TestApplication application; + Vector3 v0(2.0f, 3.0f, 4.0f); + Vector3 r0(20.0f, 30.0f, 40.0f); + v0 *= 10.f; + DALI_TEST_EQUALS(v0, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Multiply05P(void) +{ + TestApplication application; + Vector3 vec3(Vector3::YAXIS); + Quaternion rotation(Radian(Math::PI_2), Vector3::ZAXIS); + Vector3 result(-Vector3::XAXIS); + vec3 *= rotation; + DALI_TEST_EQUALS( vec3, result, 0.001, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVector3Divide01P(void) +{ + TestApplication application; + Vector3 v0(1.0f, 1.0f, 1.0f); + Vector3 v1(2.0f, 3.0f, 5.0f); + Vector3 v2(4.0f, 9.0f, 25.0f); + + DALI_TEST_EQUALS( v0/v0, v0, TEST_LOCATION); + DALI_TEST_EQUALS( v1/v0, v1, TEST_LOCATION); + DALI_TEST_EQUALS( v1/v1, v0, TEST_LOCATION); + DALI_TEST_EQUALS( v2/v1, v1, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector3Divide02P(void) +{ + TestApplication application; + Vector3 v0(3.0f, 6.0f, 9.0f); + Vector3 v1(1.0f, 2.0f, 3.0f); + Vector3 r(3.0f, 3.0f, 3.0f); + Vector3 v2 = v0 / v1; + DALI_TEST_EQUALS(v2, r, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Divide03P(void) +{ + TestApplication application; + Vector3 v0(3.0f, 6.0f, 9.0f); + Vector3 v1(1.0f, 2.0f, 3.0f); + Vector3 v2 = v0 / 3.f; + DALI_TEST_EQUALS(v2, v1, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Divide04P(void) +{ + TestApplication application; + Vector3 v0(3.0f, 6.0f, 9.0f); + Vector3 v1(1.0f, 1.0f, 1.0f); + Vector3 v4(v0); + v4 /= v0; + DALI_TEST_EQUALS(v4, v1, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3Divide05P(void) +{ + TestApplication application; + Vector3 v0(3.0f, 6.0f, 9.0f); + Vector3 v1(1.0f, 2.0f, 3.0f); + Vector3 v4(v0); + v4 /= 3.f; + DALI_TEST_EQUALS(v4, v1, TEST_LOCATION); + END_TEST; +} + + +int UtcDaliVector3NegateP(void) +{ + TestApplication application; + Vector3 v1(10.0f, 20.0f, 30.f); + Vector3 r0(-10.0f, -20.0f, -30.f); + + Vector3 v2 = -v1; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3EqualsP(void) +{ + TestApplication application; + Vector3 v0(1.0f, 2.0f, 3.0f); + Vector3 v1(1.0f, 2.0f, 3.0f); + + DALI_TEST_CHECK(v0 == v1); + END_TEST; +} + +int UtcDaliVector3NotEqualsP(void) +{ + TestApplication application; + Vector3 v0(1.0f, 2.0f, 3.0f); + Vector3 v1(1.0f, 2.0f, 3.0f); + Vector3 v2 = Vector3(0.0f, 2.0f, 3.0f); + DALI_TEST_CHECK(v0 != v2); + + v2 = Vector3(1.0f, 0.0f, 3.0f); + DALI_TEST_CHECK(v0 != v2); + + v2 = Vector3(1.0f, 2.0f, 0.0f); + DALI_TEST_CHECK(v0 != v2); + + v2 = Vector3(11.0f, 22.0f, 33.0f); + DALI_TEST_CHECK(v0 != v2); + END_TEST; +} + +int UtcDaliVector3OperatorSubscriptP(void) +{ + TestApplication application; + Vector3 testVector(1.0f, 2.0f, 3.0f); + + // read array subscripts + DALI_TEST_EQUALS( testVector[0], 1.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector[1], 2.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector[2], 3.0f, TEST_LOCATION ); + + // write array subscripts/read struct memebers + testVector[0] = 4.0f; + testVector[1] = 5.0f; + testVector[2] = 6.0f; + + DALI_TEST_EQUALS( testVector.x, 4.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector.y, 5.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector.z, 6.0f, TEST_LOCATION ); + + // write struct members/read array subscripts + testVector.x = 7.0f; + testVector.y = 8.0f; + testVector.z = 9.0f; + + DALI_TEST_EQUALS( testVector[0], 7.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector[1], 8.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector[2], 9.0f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVector3ConstOperatorSubscriptP(void) +{ + TestApplication application; + Vector3 testVector(1.0f, 2.0f, 3.0f); + + // write struct members/read array subscripts + const Vector3 testVector2(1.0f, 2.0f, 3.0f); + const float& x = testVector2[0]; + const float& y = testVector2[1]; + const float& z ( testVector2[2] ); + + DALI_TEST_EQUALS( x, 1.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( y, 2.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( z, 3.0f, TEST_LOCATION ); + + try + { + float& w = testVector[4]; + if(w==0.0f); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "index < 3", TEST_LOCATION ); + } + + try + { + const float& w = testVector2[4]; + if(w==0.0f); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT(e, "index < 3", TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliVector3DotP(void) +{ + TestApplication application; + DALI_TEST_EQUALS(Vector3::XAXIS.Dot(Vector3::YAXIS), 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector3::XAXIS.Dot(Vector3::ZAXIS), 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector3::XAXIS.Dot(Vector3::XAXIS), 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector3::YAXIS.Dot(Vector3::YAXIS), 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector3::ZAXIS.Dot(Vector3::ZAXIS), 1.0f, TEST_LOCATION); + + DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f).Dot(Vector3(1.0f, 0.0f, 0.0f)), 1.0f, TEST_LOCATION); + + for (float x = 0; x<6.0f; x+=1.0f) + { + Vector3 v0(cosf(x), sinf(x), 0.0f); + Vector3 v1(sinf(x), -cosf(x), 0.0f); + DALI_TEST_EQUALS(v0.Dot(v1), 0.0f, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.Dot(v0), 1.0f, 0.0001f, TEST_LOCATION); + + v0 = Vector3(cosf(x), 0.0f, sinf(x)); + v1 = Vector3(sinf(x), 0.0f, -cosf(x)); + DALI_TEST_EQUALS(v0.Dot(v0), 1.0f, 0.0001f, TEST_LOCATION); + } + + Vector3 v0 = Vector3(12.0f, 7.0f, 9.0f); + v0.Normalize(); + + Vector3 v1 = v0 * 2.0f; + DALI_TEST_EQUALS(v0.Dot(v1), 2.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3CrossP(void) +{ + TestApplication application; + DALI_TEST_EQUALS(Vector3::XAXIS.Cross(Vector3::YAXIS), Vector3::ZAXIS, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector3::YAXIS.Cross(Vector3::ZAXIS), Vector3::XAXIS, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector3::ZAXIS.Cross(Vector3::XAXIS), Vector3::YAXIS, 0.0001f, TEST_LOCATION); + + DALI_TEST_EQUALS(Vector3::XAXIS.Cross(Vector3::ZAXIS), -Vector3::YAXIS, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector3::YAXIS.Cross(Vector3::XAXIS), -Vector3::ZAXIS, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector3::ZAXIS.Cross(Vector3::YAXIS), -Vector3::XAXIS, 0.0001f, TEST_LOCATION); + + Vector3 v0(2.0f, 3.0f, 4.0f); + Vector3 v1(10.0f, 20.0f, 30.0f); + Vector3 result( (v0.y * v1.z) - (v0.z * v1.y), + (v0.z * v1.x) - (v0.x * v1.z), + (v0.x * v1.y) - (v0.y * v1.x) ); + + + DALI_TEST_EQUALS(v0.Cross(v1), result, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3LengthP(void) +{ + TestApplication application; + Vector3 v(1.0f, 2.0f, 3.0f); + DALI_TEST_EQUALS(v.Length(), sqrtf(v.x*v.x + v.y*v.y + v.z*v.z), 0.001f, TEST_LOCATION); + + Vector3 v1(0.0f, 0.0f, 0.0f); + DALI_TEST_EQUALS(v1.Length(), 0.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3LengthSquaredP(void) +{ + TestApplication application; + Vector3 v(1.0f, 2.0f, 3.0f); + DALI_TEST_EQUALS(v.LengthSquared(), v.x*v.x + v.y*v.y + v.z*v.z, 0.001f, TEST_LOCATION); + + Vector3 v1(0.0f, 0.0f, 0.0f); + DALI_TEST_EQUALS(v1.LengthSquared(), 0.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3NormalizeP(void) +{ + TestApplication application; + for (float f=0.0f; f<6.0f; f+=1.0f) + { + Vector3 v(cosf(f)*10.0f, cosf(f+1.0f)*10.0f, cosf(f+2.0f)*10.0f); + v.Normalize(); + DALI_TEST_EQUALS(v.LengthSquared(), 1.0f, 0.001f, TEST_LOCATION); + } + + Vector3 v(0.0f, 0.0f, 0.0f); + v.Normalize(); + DALI_TEST_EQUALS(v.LengthSquared(), 0.0f, 0.00001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3ClampVector3P(void) +{ + TestApplication application; + + Vector3 v0(2.0f, 0.8f, 0.0f); + Vector3 v1(-1.0f, 2.0f, 10.0f); + Vector3 v2(10.0f, 5.0f, 0.0f); + Vector3 v3(8.0f, 10.0f, 5.0f); + Vector3 v4(4.9f, 5.1f, 10.0f); + Vector3 min(1.0f, 4.0f, 1.5f); + Vector3 max(9.0f, 6.0f, 8.0f); + + v0.Clamp( min, max ); + v1.Clamp( min, max ); + v2.Clamp( min, max ); + v3.Clamp( min, max ); + v4.Clamp( min, max ); + + DALI_TEST_EQUALS( v0, Vector3(2.0f, 4.0f, 1.5f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( v1, Vector3(1.0f, 4.0f, 8.0f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( v2, Vector3(9.0f, 5.0f, 1.5f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( v3, Vector3(8.0f, 6.0f, 5.0f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( v4, Vector3(4.9f, 5.1f, 8.0f), 0.01f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVector3AsFloatP(void) +{ + TestApplication application; + float values[] = {0.0f, 1.0f, 2.0f}; + Vector3 v0(values); + + for (int i=0;i<3;++i) + { + DALI_TEST_EQUALS(v0.AsFloat()[i], values[i], TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliVector3ConstAsFloatP(void) +{ + TestApplication application; + float values[] = {0.0f, 1.0f, 2.0f}; + Vector3 v0(values); + + const Vector3 v1(values); + for (int i=0;i<3;++i) + { + DALI_TEST_EQUALS(v1.AsFloat()[i], values[i], TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliVector3ConstAsVectorXYP(void) +{ + TestApplication application; + float values[] = {0.0f, 1.0f, 2.0f}; + const Vector3 v0(values); + DALI_TEST_EQUALS(v0.GetVectorXY().x, values[0], TEST_LOCATION); + DALI_TEST_EQUALS(v0.GetVectorXY().y, values[1], TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3AsVectorXYP(void) +{ + TestApplication application; + float values[] = {0.0f, 1.0f, 2.0f}; + Vector3 v0(values); + + DALI_TEST_EQUALS(v0.GetVectorXY().x, values[0], TEST_LOCATION); + DALI_TEST_EQUALS(v0.GetVectorXY().y, values[1], TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3ConstAsVectorXZP(void) +{ + TestApplication application; + float values[] = {0.0f, 1.0f, 2.0f}; + const Vector3 v0(values); + + DALI_TEST_EQUALS(v0.GetVectorYZ().x, values[1], TEST_LOCATION); + DALI_TEST_EQUALS(v0.GetVectorYZ().y, values[2], TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3AsVectorXZP(void) +{ + TestApplication application; + float values[] = {0.0f, 1.0f, 2.0f}; + Vector3 v0(values); + + DALI_TEST_EQUALS(v0.GetVectorYZ().x, values[1], TEST_LOCATION); + DALI_TEST_EQUALS(v0.GetVectorYZ().y, values[2], TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3OStreamOperatorP(void) +{ + TestApplication application; + std::ostringstream oss; + + Vector3 vector(1, 2, 3); + + oss << vector; + + std::string expectedOutput = "[1, 2, 3]"; + + DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3MinP(void) +{ + TestApplication application; + Vector3 v0(2.0f, 2.0f, 1.0f); + Vector3 v1(1.0f, 1.0f, 2.0f); + + DALI_TEST_EQUALS(Min(v0, v1), Vector3(1.0f, 1.0f, 1.0f), 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3MaxP(void) +{ + TestApplication application; + Vector3 v0(2.0f, 1.0f, 3.0f); + Vector3 v1(1.0f, 2.0f, 3.0f); + + DALI_TEST_EQUALS(Max(v0, v1), Vector3(2.0f, 2.0f, 3.0f), 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector3ClampP(void) +{ + TestApplication application; + Vector3 v0( 2.0f, 1.0f, 0.0f ); + Vector3 v1( -1.0f, 2.0f, 1.0f ); + + DALI_TEST_EQUALS( Clamp( v0, 0.9f, 1.1f ), Vector3(1.1f, 1.0f, 0.9f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( Clamp( v1, 1.0f, 1.0f ), Vector3(1.0f, 1.0f, 1.0f), 0.01f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVector3ConstantsP(void) +{ + TestApplication application; + Vector3 va = Vector3::ZERO; + Vector3 vb = Vector3::ONE; + Vector3 vc = Vector3::XAXIS; + + DALI_TEST_EQUALS(va.x, 0.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(va.y, 0.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(va.z, 0.0f, 0.001f, TEST_LOCATION); + + DALI_TEST_EQUALS(vb.x, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(vb.y, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(vb.z, 1.0f, 0.001f, TEST_LOCATION); + + DALI_TEST_EQUALS(vc.x, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(vc.y, 0.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(vc.z, 0.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + diff --git a/automated-tests/src/dali/utc-Dali-Vector4.cpp b/automated-tests/src/dali/utc-Dali-Vector4.cpp new file mode 100644 index 0000000..e83f0d9 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-Vector4.cpp @@ -0,0 +1,667 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + +#include +#include +#include + +using namespace Dali; + +void utc_dali_vector4_startup(void) +{ + test_return_value = TET_UNDEF; +} + +void utc_dali_vector4_cleanup(void) +{ + test_return_value = TET_PASS; +} + +int UtcDaliVector4Constructor01P(void) +{ + Vector4 v; + DALI_TEST_EQUALS(v.x, 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.y, 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.z, 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.w, 0.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Constructor02P(void) +{ + Vector4 v(1.0f, 2.0f, 3.0f, 4.f); + DALI_TEST_EQUALS(v.x, 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.y, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.z, 3.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.w, 4.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Constructor03P(void) +{ + float f [] = {1.0f, 2.0f, 3.0f, 4.f}; + Vector4 v(f); + DALI_TEST_EQUALS(v.x, 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.y, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.z, 3.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.w, 4.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Constructor04P(void) +{ + Vector2 vec2(1.f, 2.f); + Vector4 v(vec2); + DALI_TEST_EQUALS(v.x, 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.y, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.z, 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.w, 0.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Constructor05P(void) +{ + Vector3 vec3(1.f, 2.f, 3.f); + Vector4 v(vec3); + DALI_TEST_EQUALS(v.x, 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.y, 2.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.z, 3.0f, TEST_LOCATION); + DALI_TEST_EQUALS(v.w, 0.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Assign01P(void) +{ + Vector4 v0; + const float array[] = { 1.0f, 2.0f, 3.0f, 4.f }; + v0 = (const float*)array; + + DALI_TEST_EQUALS(v0.x, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.y, 2.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.z, 3.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.w, 4.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Assign02P(void) +{ + Vector2 vec2(1.f, 2.f); + Vector4 v0; + v0 = vec2; + DALI_TEST_EQUALS(v0.x, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.y, 2.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.z, 0.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.z, 0.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Assign03P(void) +{ + Vector3 vec3(1.f, 2.f, 3.f); + Vector4 v0; + v0 = vec3; + DALI_TEST_EQUALS(v0.x, 1.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.y, 2.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.z, 3.0f, 0.001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.w, 0.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Add01P(void) +{ + Vector4 v0(1.0f, 2.0f, 3.0f, 4.0f); + Vector4 v1(10.0f, 20.0f, 30.0f, 40.0f); + Vector4 r0(11.0f, 22.0f, 33.0f, 44.0f); + + Vector4 v2 = v0+v1; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector4Add02P(void) +{ + Vector4 v0(1.0f, 2.0f, 3.0f, 4.0f); + Vector4 v1(10.0f, 20.0f, 30.0f, 40.0f); + Vector4 r0(11.0f, 22.0f, 33.0f, 44.0f); + + v0 += v1; + DALI_TEST_EQUALS(v0, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Subtract01P(void) +{ + Vector4 v0(11.0f, 22.0f, 33.0f, 44.0f); + Vector4 v1(10.0f, 20.0f, 30.0f, 40.0f); + Vector4 r0(1.0f, 2.0f, 3.0f, 4.0f); + + Vector4 v2 = v0-v1; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Subtract02P(void) +{ + Vector4 v0(11.0f, 22.0f, 33.0f, 44.0f); + Vector4 v1(10.0f, 20.0f, 30.0f, 40.0f); + Vector4 r0(1.0f, 2.0f, 3.0f, 4.0f); + + v0 -= v1; + DALI_TEST_EQUALS(v0, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Multiply01P(void) +{ + Vector4 v0(2.0f, 3.0f, 4.0f, 5.0f); + Vector4 v1(10.0f, 20.0f, 30.0f, 40.0f); + Vector4 r0(20.0f, 60.0f, 120.0f, 200.0f); + + Vector4 v2 = v0 * v1; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector4Multiply02P(void) +{ + Vector4 v0(2.0f, 4.0f, 8.0f, 16.0f); + const Vector4 r0(20.0f, 40.0f, 80.0f, 160.0f); + Vector4 v2 = v0 * 10.0f; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Multiply03P(void) +{ + Vector4 v0(2.0f, 3.0f, 4.0f, 5.0f); + Vector4 v1(10.0f, 20.0f, 30.0f, 40.0f); + Vector4 r0(20.0f, 60.0f, 120.0f, 200.0f); + + v0 *= v1; + DALI_TEST_EQUALS(v0, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Multiply04P(void) +{ + Vector4 v0(2.0f, 4.0f, 8.0f, 16.0f); + const Vector4 r0(20.0f, 40.0f, 80.0f, 160.0f); + Vector4 v2(r0); + v0 *= 10.0f; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Divide01P(void) +{ + Vector4 v0(1.0f, 1.0f, 1.0f, 1.0f); + Vector4 v1(2.0f, 3.0f, 5.0f, 7.0f); + Vector4 v2(4.0f, 9.0f, 25.0f, 49.0f); + + DALI_TEST_EQUALS( v0/v0, v0, TEST_LOCATION); + DALI_TEST_EQUALS( v1/v0, v1, TEST_LOCATION); + DALI_TEST_EQUALS( v1/v1, v0, TEST_LOCATION); + DALI_TEST_EQUALS( v2/v1, v1, TEST_LOCATION); + + + END_TEST; +} + +int UtcDaliVector4Divide02P(void) +{ + Vector4 v0(2.0f, 4.0f, 8.0f, 16.0f); + const Vector4 r0(20.0f, 40.0f, 80.0f, 160.0f); + const Vector4 r1(10.0f, 20.0f, 40.0f, 80.0f); + const Vector4 r2( 1.0f, 2.0f, 4.0f, 8.0f); + const Vector4 r3(2.0f, 4.0f, 8.0f, 16.0f); + + Vector4 v2 = r0 / 10.0f; + DALI_TEST_EQUALS(v2, r3, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector4Divide03P(void) +{ + Vector4 v0(1.0f, 1.0f, 1.0f, 1.0f); + Vector4 v1(2.0f, 3.0f, 5.0f, 7.0f); + Vector4 v2(4.0f, 9.0f, 25.0f, 49.0f); + + Vector4 v4(v0); + v4 /= v0; + DALI_TEST_EQUALS(v4, v0, TEST_LOCATION); + + Vector4 v5(v1); + v5 /= v0; + DALI_TEST_EQUALS(v5, v1, TEST_LOCATION); + + Vector4 v6(v1); + v6 /= v6; + DALI_TEST_EQUALS(v6, v0, TEST_LOCATION); + + v2 /= v1; + DALI_TEST_EQUALS(v2, v1, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector4Divide04P(void) +{ + Vector4 v0(2.0f, 4.0f, 8.0f, 16.0f); + const Vector4 r0(20.0f, 40.0f, 80.0f, 160.0f); + const Vector4 r1(10.0f, 20.0f, 40.0f, 80.0f); + const Vector4 r2( 1.0f, 2.0f, 4.0f, 8.0f); + const Vector4 r3(2.0f, 4.0f, 8.0f, 16.0f); + + Vector4 v2(r0); + v2 /= 10.0f; + DALI_TEST_EQUALS(v2, r3, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector4NegateP(void) +{ + TestApplication application; + Vector4 v1(10.0f, 20.0f, 30.f, 40.f); + Vector4 r0(-10.0f, -20.0f, -30.f, -40.f); + + Vector4 v2 = -v1; + DALI_TEST_EQUALS(v2, r0, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4EqualsP(void) +{ + Vector4 v0(1.0f, 2.0f, 3.0f, 4.0f); + Vector4 v1(1.0f, 2.0f, 3.0f, 4.0f); + + DALI_TEST_CHECK(v0 == v1); + END_TEST; +} + +int UtcDaliVector4NotEqualsP(void) +{ + Vector4 v0(1.0f, 2.0f, 3.0f, 4.0f); + Vector4 v1(1.0f, 2.0f, 3.0f, 4.0f); + + Vector4 v2 = Vector4(0.0f, 2.0f, 3.0f, 4.0f); + DALI_TEST_CHECK(v0 != v2); + + v2 = Vector4(1.0f, 0.0f, 3.0f, 4.0f); + DALI_TEST_CHECK(v0 != v2); + + v2 = Vector4(1.0f, 2.0f, 0.0f, 4.0f); + DALI_TEST_CHECK(v0 != v2); + + v2 = Vector4(1.0f, 2.0f, 3.0f, 0.0f); + DALI_TEST_CHECK(v0 != v2); + END_TEST; +} + +int UtcDaliVector4OperatorSubscriptP(void) +{ + Vector4 testVector(1.0f, 2.0f, 3.0f, 4.0f); + + // read array subscripts + DALI_TEST_EQUALS( testVector[0], 1.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector[1], 2.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector[2], 3.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector[3], 4.0f, TEST_LOCATION ); + + // write array subscripts/read struct memebers + testVector[0] = 5.0f; + testVector[1] = 6.0f; + testVector[2] = 7.0f; + testVector[3] = 8.0f; + + DALI_TEST_EQUALS( testVector.x, 5.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector.y, 6.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector.z, 7.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector.w, 8.0f, TEST_LOCATION ); + + // write struct members/read array subscripts + testVector.x = 9.0f; + testVector.y = 10.0f; + testVector.z = 11.0f; + testVector.w = 12.0f; + + DALI_TEST_EQUALS( testVector[0], 9.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector[1], 10.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector[2], 11.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( testVector[3], 12.0f, TEST_LOCATION ); + + END_TEST; +} + + +int UtcDaliVector4ConstOperatorSubscriptP(void) +{ + Vector4 testVector(1.0f, 2.0f, 3.0f, 4.0f); + + // write struct members/read array subscripts + const Vector4 testVector2(1.0f, 2.0f, 3.0f, 4.0f); + const float& x = testVector2[0]; + const float& y = testVector2[1]; + const float& z ( testVector2[2] ); + const float& w ( testVector2[3] ); + + DALI_TEST_EQUALS( x, 1.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( y, 2.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( z, 3.0f, TEST_LOCATION ); + DALI_TEST_EQUALS( w, 4.0f, TEST_LOCATION ); + + try + { + float& w = testVector[4]; + if(w==0.0f); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "index < 4", TEST_LOCATION ); + } + + try + { + const float& w = testVector2[4]; + if(w==0.0f); + tet_result(TET_FAIL); + } + catch (Dali::DaliException& e) + { + DALI_TEST_PRINT_ASSERT( e ); + DALI_TEST_ASSERT( e, "index < 4", TEST_LOCATION ); + } + END_TEST; +} + +int UtcDaliVector4Dot01P(void) +{ + DALI_TEST_EQUALS(Vector4::XAXIS.Dot(Vector4::YAXIS), 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::XAXIS.Dot(Vector4::ZAXIS), 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::XAXIS.Dot(Vector4::XAXIS), 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::YAXIS.Dot(Vector4::YAXIS), 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::ZAXIS.Dot(Vector4::ZAXIS), 1.0f, TEST_LOCATION); + + DALI_TEST_EQUALS(Vector4(1.0f, 0.0f, 0.0f, 1.0f).Dot(Vector4(1.0f, 0.0f, 0.0f, 1.0f)), 1.0f, TEST_LOCATION); + + // Test v0 . v0 and v0 . v1 (v1 is always 90 degrees out of phase with v0) + for (float x = 0; x<6.0f; x+=1.0f) + { + // vectors rotating in the XY plane. + Vector4 v0(cosf(x), sinf(x), 0.0f, 1.0f); + Vector4 v1(sinf(x), -cosf(x), 0.0f, 1.0f); + DALI_TEST_EQUALS(v0.Dot(v1), 0.0f, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.Dot(v0), 1.0f, 0.0001f, TEST_LOCATION); + + // vectors rotating in the XZ plane. + v0 = Vector4(cosf(x), 0.0f, sinf(x), 0.0f); + v1 = Vector4(sinf(x), 0.0f, -cosf(x), 0.0f); + DALI_TEST_EQUALS(v0.Dot(v1), 0.0f, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.Dot(v0), 1.0f, 0.0001f, TEST_LOCATION); + } + + Vector4 v0 = Vector4(12.0f, 7.0f, 9.0f, 14.0f); + v0.Normalize(); + + Vector4 v1 = v0 * 2.0f; + DALI_TEST_EQUALS(v0.Dot(v1), 2.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4DotVector302P(void) +{ + DALI_TEST_EQUALS(Vector4::XAXIS.Dot(Vector3::YAXIS), 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::XAXIS.Dot(Vector3::ZAXIS), 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::XAXIS.Dot(Vector3::XAXIS), 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::YAXIS.Dot(Vector3::YAXIS), 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::ZAXIS.Dot(Vector3::ZAXIS), 1.0f, TEST_LOCATION); + + DALI_TEST_EQUALS(Vector4(1.0f, 0.0f, 0.0f, 1.0f).Dot(Vector3(1.0f, 0.0f, 0.0f)), 1.0f, TEST_LOCATION); + + // Test v0 . v0b and v0 . v1 (v1 is always 90 degrees out of phase with v0) + for (float x = 0; x<6.0f; x+=1.0f) + { + // vectors rotating in the XY plane. + Vector4 v0(cosf(x), sinf(x), 0.0f, 1.0f); + Vector3 v0b(cosf(x), sinf(x), 0.0f); + Vector3 v1(sinf(x), -cosf(x), 0.0f); + DALI_TEST_EQUALS(v0.Dot(v1), 0.0f, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.Dot(v0b), 1.0f, 0.0001f, TEST_LOCATION); + + // vectors rotating in the XZ plane. + v0 = Vector4(cosf(x), 0.0f, sinf(x), 0.0f); + v0b = Vector3(cosf(x), 0.0f, sinf(x)); + v1 = Vector3(sinf(x), 0.0f, -cosf(x)); + DALI_TEST_EQUALS(v0.Dot(v1), 0.0f, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.Dot(v0b), 1.0f, 0.0001f, TEST_LOCATION); + } + + Vector4 v0 = Vector4(12.0f, 7.0f, 9.0f, 14.0f); + v0.Normalize(); + + Vector3 v1(v0 * 2.0f); + DALI_TEST_EQUALS(v0.Dot(v1), 2.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4Dot4P(void) +{ + DALI_TEST_EQUALS(Vector4::XAXIS.Dot4(Vector4::YAXIS), 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::XAXIS.Dot4(Vector4::ZAXIS), 0.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::YAXIS.Dot4(Vector4::ZAXIS), 0.0f, TEST_LOCATION); + + DALI_TEST_EQUALS(Vector4::XAXIS.Dot4(Vector4::XAXIS), 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::YAXIS.Dot4(Vector4::YAXIS), 1.0f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::ZAXIS.Dot4(Vector4::ZAXIS), 1.0f, TEST_LOCATION); + + DALI_TEST_EQUALS(Vector4(1.0f, 0.0f, 0.0f, 1.0f).Dot4(Vector4(1.0f, 0.0f, 0.0f, 1.0f)), 2.0f, TEST_LOCATION); + + for (float x = 0; x<6.0f; x+=1.0f) + { + Vector4 v0(cosf(x), sinf(x), 0.0f, 1.0f); + Vector4 v1(sinf(x), -cosf(x), 0.0f, 1.0f); + DALI_TEST_EQUALS(v0.Dot4(v1), 1.0f, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.Dot4(v0), 2.0f, 0.0001f, TEST_LOCATION); + + v0 = Vector4(cosf(x), 0.0f, sinf(x), 0.0f); + v1 = Vector4(sinf(x), 0.0f, -cosf(x), 0.0f); + DALI_TEST_EQUALS(v0.Dot4(v1), 0.0f, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(v0.Dot4(v0), 1.0f, 0.0001f, TEST_LOCATION); + } + + Vector4 v0(12.0f, 7.0f, 9.0f, 3.0f); + v0.Normalize(); + + Vector4 v1 = v0 * 2.0f; + DALI_TEST_EQUALS(v0.Dot4(v1), 2.0f + 3.0f*6.0f, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4CrossP(void) +{ + DALI_TEST_EQUALS(Vector4::XAXIS.Cross(Vector4::YAXIS), Vector4::ZAXIS, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::YAXIS.Cross(Vector4::ZAXIS), Vector4::XAXIS, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::ZAXIS.Cross(Vector4::XAXIS), Vector4::YAXIS, 0.0001f, TEST_LOCATION); + + DALI_TEST_EQUALS(Vector4::XAXIS.Cross(Vector4::ZAXIS), -Vector4::YAXIS, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::YAXIS.Cross(Vector4::XAXIS), -Vector4::ZAXIS, 0.0001f, TEST_LOCATION); + DALI_TEST_EQUALS(Vector4::ZAXIS.Cross(Vector4::YAXIS), -Vector4::XAXIS, 0.0001f, TEST_LOCATION); + + Vector4 v0(2.0f, 3.0f, 4.0f, 5.0f); + Vector4 v1(10.0f, 20.0f, 30.0f, 40.0f); + Vector4 result( (v0.y * v1.z) - (v0.z * v1.y), + (v0.z * v1.x) - (v0.x * v1.z), + (v0.x * v1.y) - (v0.y * v1.x), + 0.0f); + + DALI_TEST_EQUALS(v0.Cross(v1), result, 0.001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4LengthP(void) +{ + Vector4 v(1.0f, 2.0f, 3.0f, 4.0f); + DALI_TEST_EQUALS(v.Length(), sqrtf(v.x*v.x + v.y*v.y + v.z*v.z), 0.001f, TEST_LOCATION); + + Vector4 v1(0.0f, 0.0f, 0.0f, 0.0f); + DALI_TEST_EQUALS(v1.Length(), 0.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4LengthSquaredP(void) +{ + Vector4 v(1.0f, 2.0f, 3.0f, 4.0f); + DALI_TEST_EQUALS(v.LengthSquared(), v.x*v.x + v.y*v.y + v.z*v.z, 0.001f, TEST_LOCATION); + + Vector4 v1(0.0f, 0.0f, 0.0f, 0.0f); + DALI_TEST_EQUALS(v1.LengthSquared(), 0.0f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4NormalizeP(void) +{ + for (float f=0.0f; f<6.0f; f+=1.0f) + { + Vector4 v(cosf(f)*10.0f, cosf(f+1.0f)*10.0f, cosf(f+2.0f)*10.0f, 1.0f); + v.Normalize(); + DALI_TEST_EQUALS(v.LengthSquared(), 1.0f, 0.001f, TEST_LOCATION); + } + + Vector4 v(0.0f, 0.0f, 0.0f, 1.0f); + v.Normalize(); + DALI_TEST_EQUALS(v.LengthSquared(), 0.0f, 0.00001f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4ClampVector4P(void) +{ + tet_infoline("Testing Dali::Vector4::Clamp( const Vector4& v, const Vector4& min, const Vector4& max )"); + + Vector4 v0(2.0f, 0.8f, 0.0f, 5.0f); + Vector4 v1(-1.0f, 2.0f, 10.0f, -10.0f); + Vector4 v2(10.0f, 5.0f, 0.0f, 10.0f); + Vector4 v3(8.0f, 10.0f, 5.0f, -20.0f); + Vector4 v4(4.9f, 5.1f, 10.0f, 0.0f); + + Vector4 min(1.0f, -2.0f, -8.0f, -16.0f); + Vector4 max(2.0f, 4.0f, 4.0f, -8.0f); + + v0.Clamp( min, max ); + v1.Clamp( min, max ); + v2.Clamp( min, max ); + v3.Clamp( min, max ); + v4.Clamp( min, max ); + + DALI_TEST_EQUALS( v0, Vector4( 2.0f, 0.8f, 0.0f, -8.0f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( v1, Vector4( 1.0f, 2.0f, 4.0f, -10.0f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( v2, Vector4( 2.0f, 4.0f, 0.0f, -8.0f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( v3, Vector4( 2.0f, 4.0f, 4.0f, -16.0f), 0.01f, TEST_LOCATION ); + DALI_TEST_EQUALS( v4, Vector4( 2.0f, 4.0f, 4.0f, -8.0f), 0.01f, TEST_LOCATION ); + END_TEST; +} + +int UtcDaliVector4AsFloatP(void) +{ + float values[] = {0.0f, 1.0f, 2.0f, 3.0f}; + Vector4 v0(values); + + for (int i=0;i<4;++i) + { + DALI_TEST_EQUALS(v0.AsFloat()[i], values[i], TEST_LOCATION); + } + + END_TEST; +} + +int UtcDaliVector4ConstAsFloatP(void) +{ + float values[] = {0.0f, 1.0f, 2.0f, 3.0f}; + Vector4 v0(values); + + const Vector4 v1(values); + for (int i=0;i<4;++i) + { + DALI_TEST_EQUALS(v1.AsFloat()[i], values[i], TEST_LOCATION); + } + END_TEST; +} + +int UtcDaliVector4OStreamOperatorP(void) +{ + std::ostringstream oss; + + Vector4 vector(1.0f, 2.0f, 3.0f, 4.0f); + + oss << vector; + + std::string expectedOutput = "[1, 2, 3, 4]"; + + DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4MaxP(void) +{ + Vector4 v0(2.0f, 2.0f, 1.0f, 1.0f); + Vector4 v1(1.0f, 1.0f, 2.0f, 2.0f); + + DALI_TEST_EQUALS(Max(v0, v1), Vector4(2.0f, 2.0f, 2.0f, 2.0f), 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4MinP(void) +{ + Vector4 v0(2.0f, 2.0f, 1.0f, 1.0f); + Vector4 v1(1.0f, 1.0f, 2.0f, 2.0f); + + DALI_TEST_EQUALS(Min(v0, v1), Vector4(1.0f, 1.0f, 1.0f, 1.0f), 0.01f, TEST_LOCATION); + END_TEST; +} + +int UtcDaliVector4ClampP(void) +{ + tet_infoline("Testing Dali::Vector4::Clamp()"); + + Vector4 v0(2.0f, 2.0f, -2.0f, -2.0f); + DALI_TEST_EQUALS(Clamp(v0, -1.0f, 1.0f), Vector4(1.0f, 1.0f, -1.0f, -1.0f), 0.01f, TEST_LOCATION); + + Vector4 v1(1.0f, 0.0f, 0.0f, -1.0f); + DALI_TEST_EQUALS(Clamp(v1, -1.0f, 1.0f), v1, 0.01f, TEST_LOCATION); + + END_TEST; +} + +int UtcDaliVector4ConstantsP(void) +{ + float f[] = {2.0f, 3.0f, 4.0f, 5.0f}; + Vector4 v0(f); + Vector4 v1(f[0], f[1], f[2], f[3]); + Vector4 v2(v0); + + DALI_TEST_EQUALS(v0, v1, TEST_LOCATION); + DALI_TEST_EQUALS(v0, v2, TEST_LOCATION); + DALI_TEST_CHECK(v0 == v1); + END_TEST; +} diff --git a/automated-tests/src/dali/utc-Dali-WheelEvent.cpp b/automated-tests/src/dali/utc-Dali-WheelEvent.cpp new file mode 100644 index 0000000..9722454 --- /dev/null +++ b/automated-tests/src/dali/utc-Dali-WheelEvent.cpp @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + +using namespace Dali; + +namespace +{ + +// Key Event Test references +const static unsigned int SHIFT_MODIFIER = 0x1; +const static unsigned int CTRL_MODIFIER = 0x2; +const static unsigned int ALT_MODIFIER = 0x4; +const static unsigned int SHIFT_AND_CTRL_MODIFIER = SHIFT_MODIFIER | CTRL_MODIFIER; + + +// Stores data that is populated in the callback and will be read by the TET cases +struct SignalData +{ + SignalData() + : functorCalled(false) + {} + + void Reset() + { + functorCalled = false; + + receivedWheelEvent.type = WheelEvent::MOUSE_WHEEL; + receivedWheelEvent.direction = 0; + receivedWheelEvent.modifiers = 0; + receivedWheelEvent.point = Vector2::ZERO; + receivedWheelEvent.z = 0; + receivedWheelEvent.timeStamp = 0; + + wheeledActor.Reset(); + } + + bool functorCalled; + WheelEvent receivedWheelEvent; + Actor wheeledActor; +}; + +// Functor that sets the data when called +struct WheelEventReceivedFunctor +{ + WheelEventReceivedFunctor( SignalData& data ) : signalData( data ) { } + + bool operator()( Actor actor, const WheelEvent& wheelEvent ) + { + signalData.functorCalled = true; + signalData.receivedWheelEvent = wheelEvent; + signalData.wheeledActor = actor; + + return true; + } + + SignalData& signalData; +}; + +} // anonymous namespace + +int UtcDaliWheelEventConstructor(void) +{ + TestApplication application; // Reset all test adapter return codes + + WheelEvent event(WheelEvent::MOUSE_WHEEL, 1, SHIFT_MODIFIER, Vector2(1.0f, 1.0f), 1, 1000u); // coustruct a wheel event + + DALI_TEST_EQUALS(WheelEvent::MOUSE_WHEEL, event.type, TEST_LOCATION); // check type + DALI_TEST_EQUALS(1, event.direction, TEST_LOCATION); // check direction + DALI_TEST_EQUALS(SHIFT_MODIFIER, event.modifiers, TEST_LOCATION); // check modifier + DALI_TEST_EQUALS(Vector2(1.0f, 1.0f), event.point, TEST_LOCATION); // check modifier + DALI_TEST_EQUALS(1, event.z, TEST_LOCATION); // check modifier + DALI_TEST_EQUALS(1000u, event.timeStamp, TEST_LOCATION); // check modifier + END_TEST; +} + +// Positive test case for a method +int UtcDaliWheelEventIsShiftModifier(void) +{ + TestApplication application; // Reset all test adapter return codes + + WheelEvent event; + DALI_TEST_EQUALS(0u, event.modifiers, TEST_LOCATION); + + event.modifiers = SHIFT_MODIFIER; // Set to Shift Modifier + + DALI_TEST_EQUALS(SHIFT_MODIFIER, event.modifiers, TEST_LOCATION); // check able to set + + DALI_TEST_EQUALS(true, event.IsShiftModifier(), TEST_LOCATION); // check IsShiftModifier + + END_TEST; +} + +// Positive test case for a method +int UtcDaliWheelEventIsCtrlModifier(void) +{ + TestApplication application; // Reset all test adapter return codes + + WheelEvent event; + DALI_TEST_EQUALS(0u, event.modifiers, TEST_LOCATION); + + event.modifiers = CTRL_MODIFIER; // Set to Ctrl Modifier + + DALI_TEST_EQUALS(CTRL_MODIFIER, event.modifiers, TEST_LOCATION); // check able to set + + DALI_TEST_EQUALS(true, event.IsCtrlModifier(), TEST_LOCATION); // check IsCtrlModifier + END_TEST; +} + +// Positive test case for a method +int UtcDaliWheelEventIsAltModifier(void) +{ + TestApplication application; // Reset all test adapter return codes + + WheelEvent event; + DALI_TEST_EQUALS(0u, event.modifiers, TEST_LOCATION); + + event.modifiers = ALT_MODIFIER; // Set to Alt Modifier + + DALI_TEST_EQUALS(ALT_MODIFIER, event.modifiers, TEST_LOCATION); // check able to set + + DALI_TEST_EQUALS(true, event.IsAltModifier(), TEST_LOCATION); // IsAltModifier + END_TEST; +} + +// Positive fail test case for a method +int UtcDaliWheelEventIsNotShiftModifier(void) +{ + TestApplication application; // Reset all test adapter return codes + + WheelEvent event(WheelEvent::MOUSE_WHEEL, 1, CTRL_MODIFIER, Vector2(1.0f, 1.0f), 1, 1000u); + + DALI_TEST_EQUALS(CTRL_MODIFIER, event.modifiers, TEST_LOCATION); // check different modifier used + + DALI_TEST_EQUALS(false, event.IsShiftModifier(), TEST_LOCATION); + END_TEST; +} + +// Positive fail test case for a method +int UtcDaliWheelEventIsNotCtrlModifier(void) +{ + TestApplication application; // Reset all test adapter return codes + + WheelEvent event(WheelEvent::MOUSE_WHEEL, 1, ALT_MODIFIER, Vector2(1.0f, 1.0f), 1, 1000u); + + DALI_TEST_EQUALS(ALT_MODIFIER, event.modifiers, TEST_LOCATION); // check different modifier used + + DALI_TEST_EQUALS(false, event.IsCtrlModifier(), TEST_LOCATION); + END_TEST; +} + +// Positive fail test case for a method +int UtcDaliWheelEventIsNotAltModifier(void) +{ + TestApplication application; // Reset all test adapter return codes + + WheelEvent event(WheelEvent::MOUSE_WHEEL, 1, SHIFT_MODIFIER, Vector2(1.0f, 1.0f), 1, 1000u); + + DALI_TEST_EQUALS(SHIFT_MODIFIER, event.modifiers, TEST_LOCATION); // check different modifier used + + DALI_TEST_EQUALS(false, event.IsAltModifier(), TEST_LOCATION); + END_TEST; +} + +// Positive test case for a method +int UtcDaliWheelEventANDModifer(void) +{ + TestApplication application; // Reset all test adapter return codes + + WheelEvent event(WheelEvent::MOUSE_WHEEL, 1, SHIFT_AND_CTRL_MODIFIER, Vector2(1.0f, 1.0f), 1, 1000u); + DALI_TEST_EQUALS(true, event.IsCtrlModifier() && event.IsShiftModifier(), TEST_LOCATION); + + event.modifiers = SHIFT_MODIFIER; + + DALI_TEST_EQUALS(false, event.IsCtrlModifier() && event.IsShiftModifier(), TEST_LOCATION); + END_TEST; +} + +// Positive test case for a method +int UtcDaliWheelEventORModifer(void) +{ + TestApplication application; // Reset all test adapter return codes + + WheelEvent event(WheelEvent::MOUSE_WHEEL, 1, SHIFT_AND_CTRL_MODIFIER, Vector2(1.0f, 1.0f), 1, 1000u); + DALI_TEST_EQUALS(true, event.IsCtrlModifier() || event.IsAltModifier(), TEST_LOCATION); + + event.modifiers = SHIFT_MODIFIER; + + DALI_TEST_EQUALS(false, event.IsCtrlModifier() && event.IsAltModifier(), TEST_LOCATION); + END_TEST; +} + +int UtcDaliWheelEventSignalling(void) +{ + TestApplication application; // Reset all test adapter return codes + + Actor actor = Actor::New(); + actor.SetSize(100.0f, 100.0f); + actor.SetAnchorPoint(AnchorPoint::TOP_LEFT); + Stage::GetCurrent().Add(actor); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Connect to actor's wheel event signal + SignalData data; + WheelEventReceivedFunctor functor( data ); + actor.WheelEventSignal().Connect( &application, functor ); + + Vector2 screenCoordinates( 10.0f, 10.0f ); + Integration::WheelEvent event(Integration::WheelEvent::MOUSE_WHEEL, 0, SHIFT_MODIFIER, screenCoordinates, 1, 1000u); + + // Emit a wheel signal + application.ProcessEvent( event ); + DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( actor == data.wheeledActor ); + DALI_TEST_EQUALS(WheelEvent::MOUSE_WHEEL, data.receivedWheelEvent.type, TEST_LOCATION); // check type + DALI_TEST_EQUALS(0, data.receivedWheelEvent.direction, TEST_LOCATION); // check direction + DALI_TEST_EQUALS(SHIFT_MODIFIER, data.receivedWheelEvent.modifiers, TEST_LOCATION); // check modifier + DALI_TEST_EQUALS(screenCoordinates, data.receivedWheelEvent.point, TEST_LOCATION); // check modifier + DALI_TEST_EQUALS(1, data.receivedWheelEvent.z, TEST_LOCATION); // check modifier + DALI_TEST_EQUALS(1000u, data.receivedWheelEvent.timeStamp, TEST_LOCATION); // check modifier + data.Reset(); + + // Emit a wheel signal where the actor is not present, will hit the root actor though + Actor rootActor( Stage::GetCurrent().GetRootLayer() ); + + // Connect to root actor's wheel event signal + SignalData rootData; + WheelEventReceivedFunctor rootFunctor( rootData ); // Consumes signal + rootActor.WheelEventSignal().Connect( &application, rootFunctor ); + + screenCoordinates.x = screenCoordinates.y = 300.0f; + Integration::WheelEvent newEvent(Integration::WheelEvent::MOUSE_WHEEL, 0, SHIFT_MODIFIER, screenCoordinates, 1, 1000u); + application.ProcessEvent( newEvent ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION ); + DALI_TEST_CHECK( rootActor == rootData.wheeledActor ); + DALI_TEST_EQUALS(WheelEvent::MOUSE_WHEEL, rootData.receivedWheelEvent.type, TEST_LOCATION); // check type + DALI_TEST_EQUALS(0, rootData.receivedWheelEvent.direction, TEST_LOCATION); // check direction + DALI_TEST_EQUALS(SHIFT_MODIFIER, rootData.receivedWheelEvent.modifiers, TEST_LOCATION); // check modifier + DALI_TEST_EQUALS(screenCoordinates, rootData.receivedWheelEvent.point, TEST_LOCATION); // check modifier + DALI_TEST_EQUALS(1, rootData.receivedWheelEvent.z, TEST_LOCATION); // check modifier + DALI_TEST_EQUALS(1000u, rootData.receivedWheelEvent.timeStamp, TEST_LOCATION); // check modifier + + // Remove actor from stage + Stage::GetCurrent().Remove( actor ); + + // Render and notify + application.SendNotification(); + application.Render(); + + // Emit a move at the same point, we should not be signalled. + application.ProcessEvent( event ); + DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION ); + data.Reset(); + END_TEST; +} diff --git a/automated-tests/style/back_top.png b/automated-tests/style/back_top.png new file mode 100644 index 0000000000000000000000000000000000000000..19cbd763108a85a2a7c2954c0172b580a7ccb3b3 GIT binary patch literal 1122 zcmV-o1fBbdP)r0015c0ssI2d=e3600001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1NTWpK~!i%?ODH1 z+dvd{+C)SOk|P+hp$yOgm6jPqnTZ7I)Gcc=!k+>oS=pEnNXbkQnJGvNz!0%z0L2wZ zMoHzq^PTPU`E1|$a1~W&Wgzjp_uhTq`*labaU4TG(~7`{X?0Bdg%Hs6Om!S+dNe&# zjlfhpR}dWy9<9Q;9okCWbT-PlZmxGRYz)9cX@6&K*AzANaPz!$H3sR{X6o*f- z4b*pEk}JU4uwK_a%~5TJF*!IJ;>H6{=Ny#NbHyhHA$=!8ayEz&r+zXFgmpvfhqI?w|FUEqarP39Cc>f-quc3jEdu+U@+o)4zI3^xJNqzVuyjX!~+ej2wH~ z!#?9@^sW!Wb4xOgtua!P|?@BCZTN@<*r+%(Pxu0eDfun^ZQju zN7LD^EJhIPU3jryH{Y7jCsuOOy7#FG2=cVzO?_1 zlUSm)i8WXLUKd>&D<`V6w9Fo>i_18DN0a+_FQn-SR4r6UeIN$n?O7At&)G*bY)h>= zu2H-L&wm;uiKSmp^?}Eaeo3F#ad`p_g zkaTccl`IJj#%&VJotuA|7HL``L^*eEN#;^7^gJj%uZS@*os`d9+Ec76WDhY%&DLh+ zk~gPu{7RB6cX^W=C|O+bb10mksqr3fuC*y~*&4DVsdKGL=1E#fs&zGbAaCd)4J^Z) z7R;>36Esb7Ig3c*^kNl;p$CS#b-#ql94e#c+#y@;{KUk8jLy$r=fXIkvq!3R;o_DW zp;~~4fZ~5Q)UroYk~0FDo}2+zQ?Kb!!!PI6y7%M^u$p?EJ!<&nyjs(fGr(%NP!T_~pF%FN1_9_w2rCUjP6A07*qoM6N<$f@q*1S^xk5 literal 0 HcmV?d00001 diff --git a/automated-tests/style/blue.jpg b/automated-tests/style/blue.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d1db8f724fa76eb1f4efb914d24be05c187109d8 GIT binary patch literal 954 zcmex=eAA-4QK!nlZm zfsvIF3>ct*k%^gwm5rT)lZ%^?ff*tPBq6d$k^&4&jLghTEX=H|EG$4{YJqYLEP|{; ziiVDC!hwnGN`)dujT0AgC_8ODC>nI}gNkudQ4=SZn7D+bl&YG#hNhN@shPQjrIoXb ztDC!rr&n-DXjpheWK?oWYFc_mW>#@YX<2ziWmR)aYg>CqXV;|3Q>IRvK4a#rMT?g# zUABD1%2k^-Z`rzS`;MKv4jn#n^w{weCr@3veC6u3>o;!Rdidz^lc&#~zj*oTTk@SCu%S(U=?B5(qa)L@X*7#m8DOl#UiAmVu=Tcr^qMLDWl0zutf1t zBi|CmOpYi9pn9eTp$4HD$1WIZ_T(D&E;DSK>FjIRYjVusvPR}AiOW61}+8- zMh!;Ip3DVF!4kKUr80XGmjzt*N%l4DF*zlb)n;;8;#Ml}g5=B|uVf*RYM?(BumIgA z)*$QQbO~sVEYxs0nBhm2+=B!b0qtV}TDGM@LtqO7&{>=goIc4J5^Xb%%|f!ps7)#v aXp7m5W0y5@nSs8&EHMS7nw6pc|4jgm*fB5w literal 0 HcmV?d00001 diff --git a/automated-tests/style/gray.jpg b/automated-tests/style/gray.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f1acfdbe94c05b638ac06a84edf7c7bbb1125f3e GIT binary patch literal 866 zcmex=wkpZ3brsCPqdOf&yk%W)NUwVPR%vXJcmvVGd4iP7V$(4t91fUM?^_0R}-120_L^W=16jCP7AKLB{__7~~lk7+Hbd0r?0D z7@3$^SlNJ1;^GD>*eU>YJ~J~D(6Ov6EI`$@KzRlhK~^C}Lq|5@z(jVXLJ_0Ji3>TD zoi-j64Z8S2#W<;`iIYoATtZSxRZU$(Q_IBE%-q7#%Gt%$&E3P(D>x)HEIcAIDmf)J zEj=SMtGJ}Jth}PKs=1}Lt-YhOYtrN?Q>RUzF>}_U#Y>hhTfSoDs!f}>Y~8kf$Ie}c z4j(ys?D&b3r!HN-a`oEv8#iw~eDwIq(`V0LynOZX)8{W=zkUDl^B2fpj10^WZ^38f2KE_o9%~}YXK;@p{B?_ghnW!=dCY3JE*Eh+R}GQb@{A;m&0YWe@)1OTom7e@d9 literal 0 HcmV?d00001 diff --git a/automated-tests/style/jquery.min.js b/automated-tests/style/jquery.min.js new file mode 100644 index 0000000..198b3ff --- /dev/null +++ b/automated-tests/style/jquery.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.7.1 jquery.com | jquery.org/license */ +(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
"+""+"
",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
t
",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; +f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() +{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/automated-tests/style/orange.jpg b/automated-tests/style/orange.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ac4c7493f8b541b2d97af3982860fdfce378d658 GIT binary patch literal 934 zcmex=eAA-4QK!nlZm zfsvIF3>ct*k%^gwm5rT)lZ%^?ff*tPBq6d$k^&4&jLghTEX=H|EG$4{YJqYLEP|{; ziiVDC!hwnGN`)dujT0AgC_8ODC>nI}gNkudQ4=SZn7D+bl&YG#hNhN@shPQjrIoXb ztDC!rr&n-DXjpheWK?oWYFc_mW>#@YX<2ziWmR)aYg>CqXV;|3Q>IRvK4a#rMT?g# zUABD1%2k^-Z`rzS`;MKv4jn#n^w{weCr@3veC6u3>o;!Rdidz^lc&#~zj*oTqL?A@(1V@JrB8&TV2R?P3GG}?A^{LuY(jg0VkSov zg9gI_rUsz~p&3UOuq-pwkhqmB?UNK>xaFA1Wr}B8g@Ex zLJT$oT9usHlWW+!ASoDRpTiNL#f+LgUJ%CstzcM?1Tucn1imF64;_Hc1{xpe0W_I^ z0npHgAQm^!hfbG3j^|?VVt_diXl^FN7g9hL$o$JbKrt^ihznR5L>L0t|K9`v=nx~$ literal 0 HcmV?d00001 diff --git a/automated-tests/style/popup.js b/automated-tests/style/popup.js new file mode 100644 index 0000000..5f994f4 --- /dev/null +++ b/automated-tests/style/popup.js @@ -0,0 +1,1215 @@ +/** + * Copyright (c)2005-2009 Matt Kruse (javascripttoolbox.com) + * + * Dual licensed under the MIT and GPL licenses. + * This basically means you can use this code however you want for + * free, but don't claim to have written it yourself! + * Donations always accepted: http://www.JavascriptToolbox.com/donate/ + * + * Please do not link to the .js files on javascripttoolbox.com from + * your site. Copy the files locally to your server instead. + * + */ +/* ******************************************************************* */ +/* UTIL FUNCTIONS */ +/* ******************************************************************* */ +var Util = {'$VERSION':1.06}; + +// Util functions - these are GLOBAL so they +// look like built-in functions. + +// Determine if an object is an array +function isArray(o) { + return (o!=null && typeof(o)=="object" && typeof(o.length)=="number" && (o.length==0 || defined(o[0]))); +}; + +// Determine if an object is an Object +function isObject(o) { + return (o!=null && typeof(o)=="object" && defined(o.constructor) && o.constructor==Object && !defined(o.nodeName)); +}; + +// Determine if a reference is defined +function defined(o) { + return (typeof(o)!="undefined"); +}; + +// Iterate over an array, object, or list of items and run code against each item +// Similar functionality to Perl's map() function +function map(func) { + var i,j,o; + var results = []; + if (typeof(func)=="string") { + func = new Function('$_',func); + } + for (i=1; i>>=4; + } + while(hex.length<6) { hex='0'+hex; } + return "#" + hex; + }; + + // Convert hyphen style names like border-width to camel case like borderWidth + css.hyphen2camel = function(property) { + if (!defined(property) || property==null) { return null; } + if (property.indexOf("-")<0) { return property; } + var str = ""; + var c = null; + var l = property.length; + for (var i=0; i0) { + return bodies[0]; + } + } + return null; + }; + + // Get the amount that the main document has scrolled from top + // -------------------------------------------------------------------- + screen.getScrollTop = function() { + if (document.documentElement && defined(document.documentElement.scrollTop) && document.documentElement.scrollTop>0) { + return document.documentElement.scrollTop; + } + if (document.body && defined(document.body.scrollTop)) { + return document.body.scrollTop; + } + return null; + }; + + // Get the amount that the main document has scrolled from left + // -------------------------------------------------------------------- + screen.getScrollLeft = function() { + if (document.documentElement && defined(document.documentElement.scrollLeft) && document.documentElement.scrollLeft>0) { + return document.documentElement.scrollLeft; + } + if (document.body && defined(document.body.scrollLeft)) { + return document.body.scrollLeft; + } + return null; + }; + + // Util function to default a bad number to 0 + // -------------------------------------------------------------------- + screen.zero = function(n) { + return (!defined(n) || isNaN(n))?0:n; + }; + + // Get the width of the entire document + // -------------------------------------------------------------------- + screen.getDocumentWidth = function() { + var width = 0; + var body = screen.getBody(); + if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) { + var rightMargin = parseInt(CSS.get(body,'marginRight'),10) || 0; + var leftMargin = parseInt(CSS.get(body,'marginLeft'), 10) || 0; + width = Math.max(body.offsetWidth + leftMargin + rightMargin, document.documentElement.clientWidth); + } + else { + width = Math.max(body.clientWidth, body.scrollWidth); + } + if (isNaN(width) || width==0) { + width = screen.zero(self.innerWidth); + } + return width; + }; + + // Get the height of the entire document + // -------------------------------------------------------------------- + screen.getDocumentHeight = function() { + var body = screen.getBody(); + var innerHeight = (defined(self.innerHeight)&&!isNaN(self.innerHeight))?self.innerHeight:0; + if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) { + var topMargin = parseInt(CSS.get(body,'marginTop'),10) || 0; + var bottomMargin = parseInt(CSS.get(body,'marginBottom'), 10) || 0; + return Math.max(body.offsetHeight + topMargin + bottomMargin, document.documentElement.clientHeight, document.documentElement.scrollHeight, screen.zero(self.innerHeight)); + } + return Math.max(body.scrollHeight, body.clientHeight, screen.zero(self.innerHeight)); + }; + + // Get the width of the viewport (viewable area) in the browser window + // -------------------------------------------------------------------- + screen.getViewportWidth = function() { + if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) { + return document.documentElement.clientWidth; + } + else if (document.compatMode && document.body) { + return document.body.clientWidth; + } + return screen.zero(self.innerWidth); + }; + + // Get the height of the viewport (viewable area) in the browser window + // -------------------------------------------------------------------- + screen.getViewportHeight = function() { + if (!window.opera && document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) { + return document.documentElement.clientHeight; + } + else if (document.compatMode && !window.opera && document.body) { + return document.body.clientHeight; + } + return screen.zero(self.innerHeight); + }; + + return screen; +})();var Sort = (function(){ + var sort = {}; + sort.AlphaNumeric = function(a,b) { + if (a==b) { return 0; } + if (a0 && document.anchors[0].x) { + for (var i=0; i0) { + top -= el.scrollTop; + } + if (el.scrollLeft && el.scrollLeft>0) { + left -= el.scrollLeft; + } + } + } + // If this node is also the offsetParent, add on the offsets and reset to the new offsetParent + if (el == offsetParent) { + left += o.offsetLeft; + if (el.clientLeft && el.nodeName!="TABLE") { + left += el.clientLeft; + } + top += o.offsetTop; + if (el.clientTop && el.nodeName!="TABLE") { + top += el.clientTop; + } + o = el; + if (o.offsetParent==null) { + if (o.offsetLeft) { + left += o.offsetLeft; + } + if (o.offsetTop) { + top += o.offsetTop; + } + } + offsetParent = o.offsetParent; + } + } + + + if (originalObject.offsetWidth) { + width = originalObject.offsetWidth; + } + if (originalObject.offsetHeight) { + height = originalObject.offsetHeight; + } + + return {'left':left, 'top':top, 'width':width, 'height':height + }; + }; + + // Retrieve the position of an object's center point + // ================================================= + pos.getCenter = function(o) { + var c = this.get(o); + if (c==null) { return null; } + c.left = c.left + (c.width/2); + c.top = c.top + (c.height/2); + return c; + }; + + return pos; +})();// CLASS CONSTRUCTOR +// -------------------------------------------------------------------- +var Popup = function(div, options) { + this.div = defined(div)?div:null; + this.index = Popup.maxIndex++; + this.ref = "Popup.objects["+this.index+"]"; + Popup.objects[this.index] = this; + // Store a reference to the DIV by id, also + if (typeof(this.div)=="string") { + Popup.objectsById[this.div] = this; + } + if (defined(this.div) && this.div!=null && defined(this.div.id)) { + Popup.objectsById[this.div.id] = this.div.id; + } + // Apply passed-in options + if (defined(options) && options!=null && typeof(options)=="object") { + for (var i in options) { + this[i] = options[i]; + } + } + return this; +}; + +// CLASS PROPERTIES +// -------------------------------------------------------------------- +// Index of popup objects, to maintain a global reference if necessary +Popup.maxIndex = 0; +Popup.objects = {}; +Popup.objectsById = {}; + +// The z-index value that popups will start at +Popup.minZIndex = 101; + +// Class names to assign to other objects +Popup.screenClass = "PopupScreen"; +Popup.iframeClass = "PopupIframe"; +Popup.screenIframeClass = "PopupScreenIframe"; + +// CLASS METHODS +// -------------------------------------------------------------------- + +// Hide all currently-visible non-modal dialogs +Popup.hideAll = function() { + for (var i in Popup.objects) { + var p = Popup.objects[i]; + if (!p.modal && p.autoHide) { + p.hide(); + } + } +}; +// Catch global events as a trigger to hide auto-hide popups +Event.add(document, "mouseup", Popup.hideAll, false); + +// A simple class method to show a popup without creating an instance +Popup.show = function(divObject, referenceObject, position, options, modal) { + var popup; + if (defined(divObject)) { + popup = new Popup(divObject); + } + else { + popup = new Popup(); + popup.destroyDivOnHide = true; + } + if (defined(referenceObject)) { popup.reference = DOM.resolve(referenceObject); } + if (defined(position)) { popup.position = position; } + if (defined(options) && options!=null && typeof(options)=="object") { + for (var i in options) { + popup[i] = options[i]; + } + } + if (typeof(modal)=="boolean") { + popup.modal = modal; + } + popup.destroyObjectsOnHide = true; + popup.show(); + return popup; +}; + +// A simple class method to show a modal popup +Popup.showModal = function(divObject, referenceObject, position, options) { + Popup.show(divObject, referenceObject, position, options, true); +}; + +// A method to retrieve a popup object based on a div ID +Popup.get = function(divId) { + if (defined(Popup.objectsById[divId])) { + return Popup.objectsById[divId]; + } + return null; +}; + +// A method to hide a popup based on a div id +Popup.hide = function(divId) { + var popup = Popup.get(divId); + if (popup!=null) { + popup.hide(); + } +}; + +// PROTOTYPE PROPERTIES +// -------------------------------------------------------------------- +Popup.prototype.content = null; +Popup.prototype.className = "PopupDiv"; +Popup.prototype.style = null; // Styles to be applied to the DIV +Popup.prototype.width = null; +Popup.prototype.height = null; +Popup.prototype.top = null; +Popup.prototype.left = null; +Popup.prototype.offsetLeft = 0; +Popup.prototype.offsetTop = 0; +Popup.prototype.constrainToScreen = true; +Popup.prototype.autoHide = true; +Popup.prototype.useIframeShim = false; /*@cc_on @*/ /*@if (@_win32) {Popup.prototype.useIframeShim = true;} @end @*/ +Popup.prototype.iframe = null; +Popup.prototype.position = null; // vertical: "above top center bottom below", horizontal: "adjacent-left,left,center,right,adjacent-right" +Popup.prototype.reference = null; +Popup.prototype.modal = false; +Popup.prototype.destroyDivOnHide = false; +Popup.prototype.destroyObjectsOnHide = false; +Popup.prototype.screen = null; +Popup.prototype.screenIframeShim = null; +Popup.prototype.screenOpacity=.4; +Popup.prototype.screenColor="#cccccc"; + +// INSTANCE METHODS +// -------------------------------------------------------------------- + +// Show the popup +// -------------------------------------------------------------------- +Popup.prototype.show = function(options, modal) { + this.modal = this.modal || (typeof(modal)=="boolean" && modal); + if (defined(options) && options!=null && typeof(options)=="object") { + for (var i in options) { + this[i] = options[i]; + } + } + this.div = DOM.resolve(this.div); + CSS.setStyle(this.div,'position','absolute'); + + // If there is no div pre-defined to use, create one + if (this.div==null) { + this.div = this.createDiv(); + } + if (this.content!=null) { + this.div.innerHTML = this.content; + this.content = null; + } + if (this.className!=null) { + this.div.className = this.className; + } + if (this.style!=null) { + this.applyStyle(); + } + if (this.width!=null) { + this.div.style.width = this.width+"px"; + this.div.style.overflowX="auto"; + } + if (this.height!=null) { + this.div.style.height = this.height+"px"; + this.div.style.overflowY="auto"; + } + + // Do the actual display - this is a separate method so display transitions can be implemented + this.transition(); + + // Make sure clicks on the DIV don't bubble up to the document + this.div.onclick = function(e) { + Event.cancelBubble(Event.resolve(e)); + }; + this.div.onmouseup = this.div.onclick; + + // Focus to the DIV if possible + if (this.modal && this.div.focus) { + this.div.focus(); + } +}; + +// Show the popup but make it modal +// -------------------------------------------------------------------- +Popup.prototype.transition = function() { + if (this.modal) { + this.addScreen(); + } + + // Make the DIV displayed but hidden so its size can be measured + CSS.setStyle(this.div,'visibility','hidden'); + CSS.setStyle(this.div,'display','block'); + + // Position the popup + this.setPosition(); + + // Add the shim if necessary + if (this.useIframeShim) { + this.addIframeShim(); + } + + // Make sure the DIV is higher than the shim + this.div.style.zIndex = Popup.minZIndex++; + + CSS.setStyle(this.div,'display','block'); + CSS.setStyle(this.div,'visibility','visible'); +}; + +// Show the popup but make it modal +// -------------------------------------------------------------------- +Popup.prototype.showModal = function(options) { + this.show(options,true); +}; + +// Apply user styles to the DIV +// -------------------------------------------------------------------- +Popup.prototype.applyStyle = function() { + if (this.div!=null && this.style!=null && typeof(this.style)=="object") { + for (var i in this.style) { + this.div.style[i] = this.style[i]; + } + } +}; + +// Hide the popup +// -------------------------------------------------------------------- +Popup.prototype.hide = function() { + // If this was a temp object creating on-the-fly, then remove objects from the DOM so + // The document doesn't get littered with extra objects + if (this.destroyDivOnHide) { + DOM.removeNode(this.div); + this.div = null; + delete Popup.objects[this.id]; + } + else if (this.div!=null) { + CSS.setStyle(this.div,'display','none'); + } + + if (this.destroyObjectsOnHide) { + DOM.removeNode(this.iframe); + DOM.removeNode(this.screen); + DOM.removeNode(this.screenIframeShim); + } + else { + if (this.iframe!=null) { + this.iframe.style.display = "none"; + } + if (this.screen!=null) { + this.screen.style.display = "none"; + } + if (this.screenIframeShim!=null) { + this.screenIframeShim.style.display = "none"; + } + } +}; + +// Util funcs for position +// -------------------------------------------------------------------- +Popup.prototype.setTop = function(top) { + this.div.style.top = top+"px"; +}; +Popup.prototype.setLeft = function(left) { + this.div.style.left = left+"px"; +}; +Popup.prototype.getTop = function() { + return parseInt(CSS.getStyle(this.div,"top"),10); +}; +Popup.prototype.getLeft = function() { + return parseInt(CSS.getStyle(this.div,"left"),10); +}; + +// All the logic to position the popup based on various criteria +// -------------------------------------------------------------------- +Popup.prototype.setPosition = function() { + if (this.position!=null) { + var m = this.position.match(/^(\S+)\s+(\S+)/); + if (m!=null && m.length==3) { + var v = m[1]; + var h = m[2]; + + var ref = this.reference; + if (ref==null) { ref = Screen.getBody(); } + var p = Position.get(ref); + var refTop = p.top; + var refLeft = p.left; + var refWidth = DOM.getOuterWidth(ref); + var refHeight = DOM.getOuterHeight(ref); + + var width = DOM.getOuterWidth(this.div); + var height = DOM.getOuterHeight(this.div); + + var scrollLeft = Screen.getScrollLeft(); + var scrollTop = Screen.getScrollTop(); + + // Set vertical position relative to reference object + if (v=="above") { this.setTop(refTop-height+this.offsetTop); } + else if (v=="top") { this.setTop(refTop+this.offsetTop); } + else if (v=="center") { this.setTop(refTop+(refHeight/2)-(height/2)+this.offsetTop); } + else if (v=="bottom") { this.setTop(refTop+refHeight-height+this.offsetTop); } + else if (v=="below") { this.setTop(refTop+refHeight+this.offsetTop); } + + // Set horizontal position relative to reference object + if (h=="adjacent-left") { this.setLeft(refLeft-width+this.offsetLeft); } + else if (h=="left") { this.setLeft(refLeft+this.offsetLeft); } + else if (h=="center") { this.setLeft(refLeft+(refWidth/2)-(width/2)+this.offsetLeft); } + else if (h=="right") { this.setLeft(refLeft+refWidth-width+this.offsetLeft); } + else if (h=="adjacent-right") { this.setLeft(refLeft+refWidth+this.offsetLeft); } + } + } + else if (this.top==null && this.left==null) { + this.center(); + } + else { + if (this.top==null) { this.top=0; } + if (this.left==null) { this.left=0; } + this.div.style.top = this.top+this.offsetTop+"px"; + this.div.style.left = this.left+this.offsetLeft+"px"; + } + + // Re-position to make sure it stays on the screen + if (this.constrainToScreen) { + this.fitToScreen(); + } +}; + +// Append an object to the body +// -------------------------------------------------------------------- +Popup.prototype.appendToBody = function(o) { + var body = Screen.getBody(); + if (body && body.appendChild) { + body.appendChild(o); + } +}; + +// Create a new DIV object to be used for a popup +// -------------------------------------------------------------------- +Popup.prototype.createDiv = function() { + if (document.createElement) { + var d = document.createElement("DIV"); + d.style.position="absolute"; + d.style.display="block"; + d.style.visibility="hidden"; + this.appendToBody(d); + return d; + } + alert("ERROR: Couldn't create DIV element in Popup.prototype.createDiv()"); + return null; +}; + +// Create a new IFRAME object to be used behind the popup +// -------------------------------------------------------------------- +Popup.prototype.createIframe = function() { + if (document.createElement) { + var i= document.createElement("IFRAME"); + i.style.position="absolute"; + i.style.display="block"; + i.style.visibility="hidden"; + i.style.background="none"; + this.appendToBody(i); + return i; + } + else { + alert("ERROR: Couldn't create IFRAME object in Popup.prototype.createIframe()"); + } +}; + +// Add an IFRAME shim for the DIV +// -------------------------------------------------------------------- +Popup.prototype.addIframeShim = function() { + if (this.iframe==null) { + this.iframe = this.createIframe(); + } + this.iframe.className = Popup.iframeClass; + CSS.setStyle(this.iframe,'top',this.getTop()+"px"); + CSS.setStyle(this.iframe,'left',this.getLeft()+"px"); + CSS.setStyle(this.iframe,'width',DOM.getOuterWidth(this.div) + "px"); + CSS.setStyle(this.iframe,'height',DOM.getOuterHeight(this.div) + "px"); + CSS.setStyle(this.iframe,'zIndex',Popup.minZIndex++); + CSS.setStyle(this.iframe,'opacity',0); + CSS.setStyle(this.iframe,'visibility','visible'); + CSS.setStyle(this.iframe,'display','block'); +}; + +// Create a "screen" to make a popup modal +// -------------------------------------------------------------------- +Popup.prototype.addScreen = function() { + if (this.screen==null) { + this.screen = this.createDiv(); + this.screen.style.top="0px"; + this.screen.style.left="0px"; + this.screen.style.backgroundColor = this.screenColor; + this.screen.className=Popup.screenClass;; + CSS.setStyle(this.screen,"opacity",this.screenOpacity); + this.screen.onclick = function(e) { Event.cancelBubble(Event.resolve(e)); } + } + if (this.screenIframeShim==null) { + this.screenIframeShim = this.createIframe(); + this.screenIframeShim.style.top="0px"; + this.screenIframeShim.style.left="0px"; + this.screenIframeShim.className=Popup.screenIframeClass; + CSS.setStyle(this.screenIframeShim,"opacity",0); + } + this.screen.style.width = Screen.getDocumentWidth()+"px"; + this.screen.style.height = Screen.getDocumentHeight()+"px"; + this.screenIframeShim.style.width = Screen.getDocumentWidth()+"px"; + this.screenIframeShim.style.height = Screen.getDocumentHeight()+"px"; + this.screenIframeShim.style.zIndex = Popup.minZIndex++; + this.screenIframeShim.style.visibility="visible"; + this.screenIframeShim.style.display="block"; + this.screen.style.zIndex = Popup.minZIndex++; + this.screen.style.visibility="visible"; + this.screen.style.display="block"; +}; + +// Re-position the DIV so it stays on the screen +// -------------------------------------------------------------------- +Popup.prototype.fitToScreen = function() { + var width = DOM.getOuterWidth(this.div); + var height = DOM.getOuterHeight(this.div); + var top = this.getTop(); + var left = this.getLeft(); + + var clientWidth = Screen.getViewportWidth(); + var clientHeight = Screen.getViewportHeight(); + + var scrollLeft = Screen.getScrollLeft(); + var scrollTop = Screen.getScrollTop(); + + if (top-scrollTop+height>clientHeight) { + top = top - ((top+height) - (scrollTop+clientHeight)); + this.div.style.top = top + "px"; + } + if (left-scrollLeft+width>clientWidth) { + left = left - ((left+width) - (scrollLeft+clientWidth)); + this.div.style.left = left + "px"; + } + if (topeAA-4QK!nlZm zfsvIF3>ct*k%^gwm5rT)lZ%^?ff*tPBq6d$k^&4&jLghTEX=H|EG$4{YJqYLEP|{; ziiVDC!hwnGN`)dujT0AgC_8ODC>nI}gNkudQ4=SZn7D+bl&YG#hNhN@shPQjrIoXb ztDC!rr&n-DXjpheWK?oWYFc_mW>#@YX<2ziWmR)aYg>CqXV;|3Q>IRvK4a#rMT?g# zUABD1%2k^-Z`rzS`;MKv4jn#n^w{weCr@3veC6u3>o;!Rdidz^lc&#~zj*oT6sAHsIig>XiL))b}k321|c8>nspdx@(iG{%BBu(K&!4Y9QI+mEHH&37-Vju zLldT>k$fT&#Q10e(7~!v)3CT7ZvHIBwv~*6t02B`<~5MYY`B#y*2w8_bb+G-D>Ii9 JS3>>&n*dJ776JeO literal 0 HcmV?d00001 diff --git a/automated-tests/style/summary.xsl b/automated-tests/style/summary.xsl new file mode 100644 index 0000000..c034df8 --- /dev/null +++ b/automated-tests/style/summary.xsl @@ -0,0 +1,352 @@ + + + + + + + + + + + + + + + \n + + + + +
+ + + +
+ + + +
+
+
diff --git a/automated-tests/style/testresult.xsl b/automated-tests/style/testresult.xsl new file mode 100644 index 0000000..019b445 --- /dev/null +++ b/automated-tests/style/testresult.xsl @@ -0,0 +1,571 @@ + + + + + + + + + + + + + + + \n + + + + +
+ + + +
+ + + +
+
+
diff --git a/automated-tests/style/tests.css b/automated-tests/style/tests.css new file mode 100644 index 0000000..487bca0 --- /dev/null +++ b/automated-tests/style/tests.css @@ -0,0 +1,195 @@ +@charset "UTF-8"; +/* CSS Document */ +#testcasepage div,#testcasepage h1,#testcasepage p,#testcasepage table,#testcasepage tr,#testcasepage th,#testcasepage td + { + margin: 0; + padding: 0; + border: 0; + font-weight: inherit; + font-style: inherit; + font-size: 0.96em; + font-family: arial; + vertical-align: baseline; +} + +#title td, #btc td{ + margin: 0; + padding: 0; + border: 0; + font-weight: inherit; + font-style: inherit; + font-size: 0.96em; + font-family: arial; + vertical-align: baseline; +} + +td.Ratio { + text-align: left; + font-weight: normal; + padding: 4px 10px 4px 5px; + vertical-align: middle; +} + +th.Ratio { + width: 400px; +} + +#testcasepage p { + text-align: left; +} + +#suite_title { + text-align: left; +} + +#btc { + text-align: right; +} + +#btc table { + position: absolute; + right: 0px; + width: 600px; +} + +#testcasepage table { + border-collapse: separate; + border-spacing: 0; + margin-bottom: 1.4em; + vertical-align: middle; +} + +#testcasepage th,#testcasepage td { + text-align: left; + font-weight: normal; + padding: 4px 10px 4px 5px; + vertical-align: middle; +} + +#cases table { + width: 101%; +} + +#cases td { + border-left: 0px; + font-weight: normal; + border-bottom: 0px; +} + +#suite_summary table { + width: 100%; +} + + +#overview table { + width: 101%; +} + +#overview table, #overview td, #overview tr { + border-left: none; + border-bottom: none; + border-right: none; + vertical-align: top; +} + +#overview td{ + width: 50%; +} + +#capability table { + width: 50%; +} + +#fail_cases table { + width: 101%; +} + +#title table { + width: 101%; +} + +#device table { + width: 100%; +} + +#summary table { + width: 100%; +} + +#testcasepage th { + border-bottom: 1px solid #000; + background-color: #AAAAAA; + border-left: 1px solid #000; + border-top: 1px solid #000; + color: #000; + font-weight: bold; + vertical-align: bottom; +} + +#summary th:last-child,#summary td:last-child, #device th:last-child,#device td:last-child, #suite_summary th:last-child,#suite_summary td:last-child,#cases th:last-child,#cases td:last-child,#capability th:last-child,#capability td:last-child { + border-right: 1px solid #000; +} + +#testcasepage td { + font-weight: normal; +} + +#summary td, #device td, #capability td, #suite_summary td, #cases td{ + border-left: 1px solid; + font-weight: normal; + border-bottom: 1px solid; +} + +#testcasepage td.yellow_rate { + background-color: #ffcc00; +} + +#testcasepage td.green_rate { + background-color: #1E90FF; +} + +#testcasepage td.dgreen_rate { + background-color: #339933; +} + +#testcasepage td.red_rate { + background-color: #FF3333; +} + +#testcasepage td.orange_rate { + background-color: #FFA500; +} + +#testcasepage td.gray_rate { + background-color: #AAAAAA; +} + +#title table,#title tr,#title td { + border-left: none; + border-bottom: none; + text-align: center; +} + +#title td:last-child { + border-right: none; +} + +#testcasepage h1 { + font-size: 2em; + font-family: Arial, sans-serif; + font-weight: bold; + line-height: 1; + color: #000; + margin-bottom: 0.75em; + padding-top: 0.25em; + font-weight: bold; +} + +#goTopBtn { + right: 0px; + bottom: 0px; + position: fixed; + + position: absolute; + top: expression(parseInt(document.body.scrollTop)+document.body.clientHeight-40 + ); +} diff --git a/automated-tests/tcbuild b/automated-tests/tcbuild new file mode 120000 index 0000000..89c2de7 --- /dev/null +++ b/automated-tests/tcbuild @@ -0,0 +1 @@ +scripts/tcbuild.sh \ No newline at end of file diff --git a/automated-tests/templates/tct-package/README b/automated-tests/templates/tct-package/README new file mode 100644 index 0000000..0af341f --- /dev/null +++ b/automated-tests/templates/tct-package/README @@ -0,0 +1,43 @@ +The scripts contained in the automated-tests/scripts folder are based on +the Web Application Security & Privacy module test suite from Intel, +with the following license: + +---------------------------------------------- +License +---------------------------------------------- +Copyright (c) 2012 Intel Corporation. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of works must retain the original copyright notice, this list + of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the original copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +* Neither the name of Intel Corporation nor the names of its contributors + may be used to endorse or promote products derived from this work without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Authors: + Yue, Jianhui + +Modifications to scripts: +Added mechanism to build and execute tests with finer granularity. +Added option to generate tests for executing on desktop + +Copyright (c) 2014 Samsung Electronics Co., Ltd. + +Authors: + Steele, David diff --git a/automated-tests/templates/tct-package/inst.sh b/automated-tests/templates/tct-package/inst.sh new file mode 100755 index 0000000..c2888df --- /dev/null +++ b/automated-tests/templates/tct-package/inst.sh @@ -0,0 +1,37 @@ +#!/bin/bash +NAME=$(basename $(cd $(dirname $0);pwd)) +PKG_DIR=%{PKG_DIR} # directory supplied by external script +PKG_NAME=%{PKG_NAME} # name supplied by external script +PKG_FULLNAME=%{PKG_FULLNAME} # name supplied by external script + +#parse params +USAGE="Usage: ./inst.sh [-i] [-u] + -i install wgt and config environment + -u uninstall wgt and remove source file +[-i] option was set as default." + +function installpkg(){ + rpm -e `rpm -qa | grep $PKG_NAME` + rpm -ivh --quiet /$PKG_DIR/$PKG_FULLNAME + /tmp/add_all_smack_rule.sh +} + +function uninstallpkg(){ +### remove source file ### +if [ -d /opt/usr/media/tct/opt/$NAME ];then + rm -rf /opt/usr/media/tct/opt/$NAME + rpm -e $PKG_NAME +else + echo "Remove source file fail, please check if the source file exist: /opt/usr/media/tct/opt/$NAME ..." +fi +} + +case "$1" in + -h|--help) echo "$USAGE" + exit ;; + ""|-i) installpkg;; + -u) uninstallpkg;; + *) echo "Unknown option: $1" + echo "$USAGE" + exit ;; +esac diff --git a/build/scripts/dali_env b/build/scripts/dali_env new file mode 100755 index 0000000..d0a9416 --- /dev/null +++ b/build/scripts/dali_env @@ -0,0 +1,602 @@ +#!/usr/bin/perl + +# Copyright (c) 2014 Samsung Electronics Co., Ltd. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +use Config; +use Cwd; +use Cwd 'abs_path'; +use File::Basename; +use File::Path; +use File::Copy; +use File::Copy::Recursive qw(dircopy); +use strict; +use Getopt::Long; +use Pod::Usage; + +################################################################################ +# SYSTEM PACKAGES # +################################################################################ +# Add any required system packages to this list - if they are not present, then +# this script will attempt to install them for you. +my @system_packages = ( + "automake", + "cmake", + "g++", + "pkg-config", + "libtool", + "ccache", + "libboost-dev", + "libboost-thread-dev", + "libelementary-dev", + "libexif-dev", + "libgles2-mesa-dev", + "libdrm-dev", + "libgif-dev", + "libturbojpeg", + "libfribidi-dev", + "libharfbuzz-dev", + "doxygen", + "lcov", + "libcurl4-gnutls-dev" +); + +# Some packages like require building from source +my @source_pkgs = ( + + {"name" => "v8", + "force-rebuild" => 0, + "use_depot_tools" => 1, + "repo" => "https://chromium.googlesource.com/v8/v8.git", + "depot_tools_repo" => "https://chromium.googlesource.com/chromium/tools/depot_tools.git", + + # original version used with DALi is 3.25.19. 3.32.7 is the latest we can use before + # upgrading DALi to use c++0x or c++11 + "version" => " 3.32.7", "make" => "make -j8 library=shared", "build-mode" =>"debug" } +); + +### Detect any http proxy, part of v8 installation requires this information +my $http_proxy_port; +my $http_proxy_ip; + +if( exists $ENV{http_proxy} ) +{ + # string split into 3 items http, //ip, port + my @http_proxy_info = split( /:/,$ENV{http_proxy}, ); + + $http_proxy_ip = @http_proxy_info[1]; + $http_proxy_ip =~ s/[\/]//g;; # remove forward slashes + $http_proxy_port = @http_proxy_info[2]; +} + +# Make best guess as to where this program was run from (note, it is +# always possible to override the location of $0 by the calling +# program, so we can't really tell for sure that this is where we +# expect it to be. :/ + +my $new_env = 0; +my $exec_path = $0; +if($0 !~ m!^/!) +{ + $exec_path = abs_path($0); +} +$exec_path = dirname($exec_path); + +my $root_path = getcwd(); +if($exec_path =~ m!dali-env/opt/bin!) +{ + $root_path = $exec_path; + while($root_path !~ m!dali-env$!) + { + $root_path = dirname($root_path); + } +} +elsif($root_path =~ m!dali-env!) +{ + while($root_path !~ m!dali-env$!) + { + $root_path = dirname($root_path); + } +} +else +{ + $new_env = 1; + $root_path .= "/dali-env"; +} + +my $src_path = "$root_path/src-packages"; +my $sbs_path = "$root_path/target"; +my $install_path = "$root_path/opt"; + +my $opt_create=0; +my $opt_setenv=0; +my $opt_help=0; +my $opt_man=0; + +GetOptions("create" => \$opt_create, + "setenv" => \$opt_setenv, + "help" => \$opt_help, + "man" => \$opt_man) or pod2usage(2); + +pod2usage(1) if $opt_help; +pod2usage(-exitstatus => 0, -verbose => 2) if $opt_man; + + +################################################################################ + +sub create_env +{ + mkpath("$install_path/bin"); + mkpath("$install_path/lib/pkgconfig"); + mkpath("$install_path/include"); + mkpath("$install_path/share/aclocal"); + mkpath("$src_path"); + mkpath("$sbs_path"); + + copy($0, "$install_path/bin/dali_env"); + chmod(0755, "$install_path/bin/dali_env"); +} + +################################################################################ + +sub in_dali_env +{ + my $cwd = substr(getcwd(), 0, length($root_path)); + #print "cwd = $cwd\nroot = $root_path\n"; + return $cwd eq $root_path; +} + +################################################################################ + +sub create_setenv +{ + print <<"EOF"; +# To use the desktop libraries, please add the following lines to your .bashrc or +# create a setenv script from them, e.g. by running this command as follows +# \$ dali_env -s > setenv +# +# You can then source this script by using +# \$ . setenv +# +# Use DESKTOP_PREFIX when running configure in dali/build/tizen: +# \$ CXXFLAGS="-g -O0" ./configure --prefix=\$DESKTOP_PREFIX + +export DESKTOP_PREFIX=$install_path +export PATH=$install_path/bin:\$PATH +export LD_LIBRARY_PATH=$install_path/lib:\$LD_LIBRARY_PATH +export INCLUDEDIR=$install_path/include +export PKG_CONFIG_PATH=$install_path/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig + +EOF +} + +################################################################################ + +sub check_system_package +{ + my $package; + foreach $package (@_) + { + my @x=split(/\s+/, `dpkg -l $package|grep $package`); + if($x[0] ne "ii") + { + print "Attempting to install $package\n"; + system("sudo apt-get -y install $package"); + } + } +} + +sub check_system_packages +{ + print "Checking for required system packages (may require sudo password)\n"; + + check_system_package(@system_packages); + my $gnome_v =`dpkg -l gnome-common| tail -1| sed "s/ \\+/ /g" | cut -d' ' -f 3`; + my @am = split(/\./, `automake --version | head -1 | cut -f4 -d' '`); + if($gnome_v =~ /$2.24/ && $am[1]>10) + { + die "Gnome common and automake are not compatible - automake is too new\n"; + } + my @gpp_v = (`g++ --version | head -1` =~ /(\d+)\.(\d+)\.(\d+)/); + + if(! (($gpp_v[0] > 4) + || + ($gpp_v[0] == 4 && $gpp_v[1] > 4) + || + ($gpp_v[0] == 4 && $gpp_v[1] == 4 && $gpp_v[2] >= 5))) + { + die "You need g++ 4.5.1 or greater to build dali\n"; + } +} + +sub check_source_packages +{ + my $pkgref; + + foreach $pkgref (@source_pkgs) + { + my $pkg = $pkgref->{"name"}; + if($pkg eq "v8") + { + install_v8( $pkgref ); + } + } +} + +################################################################################ + +sub create_link +{ + my $arch=`uname -i`; + $arch =~ s/\r|\n//g; + + my $link = "/usr/lib/$arch-linux-gnu/libturbojpeg.so"; + + unless (-e $link) + { + print "Creating libjpegturbo symbolic link\n"; + system("sudo ln -s $link.0 $link"); + } +} + +################################################################################ +# Helper to run and print out the command being run and quit if it fails +# +sub run_command +{ + my $command = $_[0]; + my $ret; + print("Running: $command\n"); + $ret = system("$command"); + if($ret >> 8) { die "$command failed \n"; } +} + +################################################################################ +# later versions of v8 (post mid 2014) require googles depot_tools to build. +# +sub install_google_depot_tools +{ + +#### +# clone the depo_tools into the source directory and set the path up +#### + my $v8 = $_[0]; + + my $depot_tools_directory = $src_path . "/depot_tools"; + my $depot_tools_repo = $v8->{"depot_tools_repo"}; + + # clear the directory if exists + rmtree( $depot_tools_directory ); + + # clone the depot tools + run_command( "git clone " . $depot_tools_repo. " " . $depot_tools_directory ); + + # add it the the path + $ENV{PATH} = "$ENV{PATH}:$depot_tools_directory"; + + # need to setup a config file for the proxy + create_boto_config_file( $v8 , $depot_tools_directory ); + + # set the config location as an environment variable ( used by scripts depot_tools) + $ENV{NO_AUTH_BOTO_CONFIG}="$src_path/depot_tools/.boto"; + + # change to depot tools directory + chdir( $depot_tools_directory ); + + # fetch v8 + run_command("fetch --nohooks v8"); + +} + + +################################################################################ +# later versions of v8 use boto, which currently requires having proxy manually set +# +sub create_boto_config_file +{ + my $v8 = $_[0]; + my $depot_tools_directory = $_[1]; + print(" depot_tools directory = $depot_tools_directory\n"); + + print("Configuring boto with http proxy IP = ". $http_proxy_ip . ", Port = " . $http_proxy_port . "\n"); + +# Create the proxy info for the boto file +my $fileContents = <<"END"; +[Boto] +debug = 0 +num_retries = 2 + +proxy = $http_proxy_ip +proxy_port = $http_proxy_port +END + # Place the config file in the depot tools folder + my $filename = $depot_tools_directory . "/" . ".boto"; + print("Creating Boto config file with proxy settings to file ". $filename . "\n"); + my $fh; + open( $fh, '>', $filename ); + print { $fh } $fileContents; + close( $fh ); + + # export the environment variable + run_command("gclient config https://gclient.googlecode.com/svn/trunk/gclient"); + + run_command("gclient runhooks"); + + + +} +################################################################################ +# We need a specific version of V8 to work with DALi +# - Check a txt file in dali-env to see if v8 needs upgrading (checks gcc version too) +# - Clones the source +# - builds dependencies (v8 automatically clones it's GYP build system) +# - Builds it +# - Create a package file +# It is cloned, then built from source, we create a package file for it, then +# it's copied into dali-env +sub install_v8 +{ + my $v8 = $_[0]; + my $ret; + my $v8Version = $v8->{"version"} ; + print( "Checking if V8 ". $v8Version. " is installed \n"); + +#### +# Check currently installed version +# We create a text file with v8 and gcc version in the filename to compare with +# Version file is stored as "v8_2.3.4_installed_built_with_gcc_4_8_3.txt" +#### + # get the gcc version, so if the compiler is updated v8 is re-built + # note: v8 requires gcc version GCC >= 4.6 + my $gccVersion = `gcc --version | grep ^gcc | sed 's/^.* //g'`; + chomp( $gccVersion ); + my $versionTextFile = $src_path . "/v8_" . $v8Version. "_" . $v8->{"build-mode"} . "_installed_built_with_gcc_". $gccVersion .".txt"; + + # use stat to see if file exists + my @install_stats = stat $versionTextFile; + if( (scalar(@install_stats)) && $v8->{"force-rebuild"} != 1 ) + { + print("Correct V8 version installed\n"); + return; + } + else + { + # delete older versions of the version file first ( otherwise when downgrading it thinks version is still installed) + system( "rm " . $src_path . "/v8_*.txt >/dev/null 2>&1"); + } + + +#### +# Clone the v8 source repository and checkout the version we want +#### + # Need to clone it from repo + my $v8_source_directory; + + + + # newer version of v8 use depot_tools with gclient, git cloned builds do not work + if( $v8->{"use_depot_tools"} == 1) + { + install_google_depot_tools( $v8 ); + + # v8 is checkout out under depot_tools path + $v8_source_directory = $src_path . "/depot_tools/v8"; + } + else + { + $v8_source_directory = $src_path . "/v8"; + + # delete the old v8 source directpry if exists + rmtree( $v8_source_directory ); + + # clone the repository + run_command( "git clone " . $v8->{"repo"} . " " . $v8_source_directory ); + } + + # change to the source directoy for the checkout + chdir( $v8_source_directory ); + + # checkout the version DALi is compatible with + run_command( "git checkout ". $v8Version ); + +#### +# Run make dependencies then make for the specific target +#### + if( $v8->{"use_depot_tools"} == 1) + { + run_command("gclient sync"); + } + else + { + run_command("make dependencies"); + } + + # assemble the make command + my $makeCommand = $v8->{"make"}; + + # need to append architecture and build mode, e.g. x64.debug + my $buildTarget; + if( $Config{use64bitint} ) { + print("Building 64 bit version of V8\n"); + $buildTarget= "x64." . $v8->{"build-mode"} + } + else{ + print("Building 32 bit version of V8\n"); + $buildTarget= "ia32." . $v8->{"build-mode"} + } + $makeCommand .= " " . $buildTarget; + print("Running: $makeCommand\n"); + run_command( $makeCommand ); + +#### +# Manually install the library / header files +#### + + # Need to manually install (make install not available on v8 ) + my $libSourceDir = "$v8_source_directory/out/$buildTarget/lib.target/"; + my $headerSourceDir = "$v8_source_directory/include/"; + + my $libDestinationDir = $install_path . "/lib/"; + my $headerDestinationDir = $install_path . "/include/v8/"; + + # delete any current v8 libs + system( "rm " . $libDestinationDir . "libv8*"); + system( "rm " . $libDestinationDir . "libicu*"); + + + # copy the library and header files + dircopy( $libSourceDir, $libDestinationDir); + dircopy( $headerSourceDir, $headerDestinationDir); + + + # Copy libv8.so to libv8.so.version ( e.g. libv8.so.1.2.4) + my $v8SoFile = $libDestinationDir . "libv8.so"; + my $v8SoVersionFile = $libDestinationDir . "libv8.so." . $v8Version; + move( $v8SoFile, $v8SoVersionFile ); + + # symlink the libv8.so.1.2.3 to libv8.so + symlink( $v8SoVersionFile, $v8SoFile ); + print( "source dir = " . $libSourceDir . " dest dir ". $libDestinationDir . " \n" ); + + +#### +# Create the package file in, +# we keep the library files and header files in v8 sub-directories +#### +my $fileContents = <<"END"; +prefix=$install_path +exec_prefix=\${prefix} +apiversion=$v8Version +libdir=\${exec_prefix}/lib +includedir=\${prefix}/include/v8 + +Name: v8 JavaScript engine - runtime library +Description: V8 is Google's open source JavaScript engine. +Version: \${apiversion} +Libs: -L\${libdir} -lv8 -licuuc -licui18n +Cflags: -I\${includedir} +END + + my $filename = $install_path . "/lib/pkgconfig/" . "v8.pc"; + print("writing to file ". $filename . "\n"); + my $fh; + if( open( $fh, '>', $filename ) ) + { + print { $fh } $fileContents; + close( $fh ); + } + else + { + die "failed to create " . $filename ."\n"; + } + + print("Installed V8 " .$v8Version . " OK\n"); + +##### +# +#### + my $versionFile; + open( $versionFile, '>', $versionTextFile ); + close( $versionFile ); + print("Installing V8 version $v8Version\n"); + +} + + +################################################################################ +# MAIN +################################################################################ + + +if($opt_create) +{ + my $new_root = getcwd() . "/dali-env"; + + if($exec_path =~ m!dali-env/opt/bin!) + { + die "Already in a dali-env directory\n"; + # Could query if user wants to re-create? + } + elsif(-e $new_root) + { + die "A dali-env directory already exists here\n"; + } + + check_system_packages(); + + create_link(); + + create_env(); + + # do this after source directory structure created in create_env + check_source_packages(); + + create_setenv(); +} +elsif($opt_setenv) +{ + if(! -d $root_path) + { + die "$root_path does not exist\n"; + } + elsif($new_env) + { + die "$root_path is not an existing environment\n"; + } + create_setenv(); +} +else +{ + pod2usage(1); +} + +__END__ + +=head1 NAME + +dali_env - Create the DALi environment for Ubuntu + +=head1 SYNOPSIS + +dali_env [-c] [-s] [-h|-m] + +=head1 OPTIONS + +=over 28 + +=item B<-c|--create> + +Create a DALi environment directory in the current directory. + +=item B<-s|--setenv> + +Display environment variables to setup. + +=item B<-h|--help> + +Display this help + +=item B<-m|--man> + +Display the manual page + +=back + +=head1 DESCRIPTION + +B + +Gets the required dependencies for DALi and them to a local directory. Can also create a setenv script to point to the installation. + +=cut diff --git a/build/scripts/generate-shader-strings.pl b/build/scripts/generate-shader-strings.pl new file mode 100755 index 0000000..cafaa23 --- /dev/null +++ b/build/scripts/generate-shader-strings.pl @@ -0,0 +1,390 @@ +#!/usr/bin/perl -w + +############################################################################### + +use strict; +use FileHandle; +use Getopt::Long; +use Pod::Usage; + +############################################################################### + +sub OpenFileForWriting +{ + my($fileName) = shift; + + my $fh = FileHandle->new; + if (!$fh->open("> $fileName")) + { + die "Can't open $fileName for writing: $!\n"; + } + return $fh; +} + +############################################################################### + +sub CloseFile +{ + my($fh) = shift; + $fh->close; +} + +############################################################################### + +sub GenerateHeaderFileHeader +{ + my($headerFile) = shift; + my $time=localtime(); + print $headerFile <<"H_HEADER_END"; +// +// Automatically Generated on $time +// + +#ifndef __DALI_GENERATED_SHADERS_H_ +#define __DALI_GENERATED_SHADERS_H_ + +namespace Dali +{ +namespace Internal +{ + +H_HEADER_END +} + +############################################################################### + +sub GenerateHeaderFileFooter +{ + my($headerFile) = shift; + print $headerFile <<"H_FOOTER_END"; + +} // namespace Internal +} // namespace Dali + +#endif // __DALI_GENERATED_SHADERS_H_ +H_FOOTER_END +} + +############################################################################### + +sub GenerateSourceFileHeader +{ + my($sourceFile) = shift; + my $time=localtime(); + print $sourceFile <<"CPP_HEADER_END"; +// +// Automatically Generated on $time +// + +namespace Dali +{ +namespace Internal +{ + +CPP_HEADER_END +} + +############################################################################### + +sub GenerateSourceFileFooter +{ + my($sourceFile) = shift; + print $sourceFile <<"CPP_FOOTER_END"; +} // namespace Internal +} // namespace Dali +CPP_FOOTER_END +} + +############################################################################### + +my %shaders=(); + +sub GenerateStringsFromFile +{ + my($file) = shift; + my($dir) = shift; + + my $shadername = $file; + $shadername =~ s/-([a-z])/uc($1)/eg; + $shadername =~ s/^([a-z])/uc($1)/e; + $shadername =~ s/\.txt$//; + + my $state = 0; + + my $shader=""; + open MEM, "$dir/$file" || die "Can't open $file for reading: $!\n"; + while() + { + chomp; + if ($state == 0) + { + if (//) + { + $state = 1; + $shader = ""; + } + elsif (//) + { + $state = 1; + $shader = ""; + } + } + elsif ($state == 1) + { + if (m!!) + { + $state = 0; + $shaders{$shadername}->{"vertex"} = $shader; + } + elsif( m!!) + { + $state = 0; + $shaders{$shadername}->{"fragment"} = $shader; + } + else + { + ## Accumulate + $shader .= "$_\n"; +# print $sourceFile "\"$_\\n\"\n"; + } + } + } + close MEM; +} + +############################################################################### + +sub GetShaderFiles +{ + my ($dir) = shift; + opendir (DIR, $dir) || die "Can't open $dir for reading: $!\n"; + my @shaderFiles = grep { /\.txt$/ && -f "$dir/$_" } readdir DIR; + closedir DIR; + return @shaderFiles; +} + +############################################################################### + +sub PrintSourceLine +{ + my $sourceFile=shift; + my $line=shift; + chomp $line; + $line =~ s!//.*$!!; # Strip out comments + $line =~ s!\s*$!!; # Strip out trailing space + if( $line !~ m!^\s*$! ) + { + print $sourceFile "\"$line\\n\"\n"; + } +} + +sub PrintMacroLine +{ + my $sourceFile=shift; + my $line=shift; + chomp $line; + $line =~ s!//.*$!!; # Strip out comments + $line =~ s!\s*$!!; # Strip out trailing space + if( $line !~ m!^\s*$! ) + { + print $sourceFile "\"$line\\n\" \\\n"; + } +} + + +sub PrintShaderProgramWithMacros +{ + my $sourceFile=shift; + my $shadername=shift; + my $SHADERNAME=$shadername; + $SHADERNAME =~ s/([A-Z])/_$1/g; + substr($SHADERNAME,0,1)=""; + $SHADERNAME = uc($SHADERNAME); + + my $program_type=shift; + my $ProgramType=ucfirst($program_type); + my $PROGRAM_TYPE=uc($program_type); + my $custom=shift; + + my @lines=split(/\n/, $shaders{$shadername}->{$program_type} ); + + print $sourceFile "#define ${SHADERNAME}_PREFIX_${PROGRAM_TYPE} \\\n"; + LINE: while( scalar(@lines) ) + { + last LINE if $lines[0] =~ /main()/; + PrintMacroLine($sourceFile, shift(@lines)); + } + print $sourceFile "\n\n"; + + print $sourceFile "#define ${SHADERNAME}_POSTFIX_${PROGRAM_TYPE} \\\n"; + LINE: while( scalar(@lines) ) + { + PrintMacroLine($sourceFile, shift(@lines)); + } + print $sourceFile "\n\n"; + + if($custom) + { + print $sourceFile "extern const char* const Custom${shadername}Prefix${ProgramType};\n"; + print $sourceFile "const char* const Custom${shadername}Prefix${ProgramType}(\n"; + print $sourceFile " ${SHADERNAME}_PREFIX_${PROGRAM_TYPE}\n"; + print $sourceFile ");\n\n"; + + print $sourceFile "extern const char* const Custom${shadername}Postfix${ProgramType};\n"; + print $sourceFile "const char* const Custom${shadername}Postfix${ProgramType}(\n"; + print $sourceFile " ${SHADERNAME}_POSTFIX_${PROGRAM_TYPE}\n"; + print $sourceFile ");\n\n"; + } + print $sourceFile "extern const char* const ${shadername}${ProgramType};\n"; + print $sourceFile "const char* const ${shadername}${ProgramType}(\n"; + print $sourceFile " ${SHADERNAME}_PREFIX_${PROGRAM_TYPE}\n"; + print $sourceFile " ${SHADERNAME}_POSTFIX_${PROGRAM_TYPE}\n"; + print $sourceFile ");\n\n"; + +} + +sub PrintShaderProgram +{ + my $sourceFile=shift; + my $shadername=shift; + my $program_type=shift; + my $custom=shift; + my $ProgramType=ucfirst($program_type); + + my @lines=split(/\n/, $shaders{$shadername}->{$program_type} ); + + print $sourceFile "const char* const ${shadername}${ProgramType}(\n"; + for my $i (0..scalar(@lines)-1) + { + PrintSourceLine($sourceFile, $lines[$i]); + } + print $sourceFile ");\n\n"; + + if( $custom ) + { + print $sourceFile "const char* const Custom${shadername}Prefix${ProgramType}(\n"; + LINE: + while( scalar(@lines) ) + { + last LINE if $lines[0] =~ /main()/; + PrintSourceLine($sourceFile, shift(@lines)); + } + print $sourceFile ");\n\n"; + + print $sourceFile "const char* const Custom${shadername}Postfix${ProgramType}(\n"; + + while( scalar(@lines) ) + { + PrintSourceLine($sourceFile, shift(@lines)); + } + print $sourceFile ");\n\n"; + } +} + + +sub PrintShaderSources +{ + my($headerFile) = shift; + my($sourceFile) = shift; + my $shadername; + + # Strings are now in memory. Dump them back out again: + foreach $shadername (sort(keys(%shaders))) + { + print $headerFile "extern const char* const ${shadername}Vertex;\n"; + print $headerFile "extern const char* const ${shadername}Fragment;\n"; + + my $custom = 0; + if( $shadername !~ /TextDistanceField/ || $shadername eq "TextDistanceField" ) + { + print $headerFile "extern const char* const Custom${shadername}PrefixVertex;\n"; + print $headerFile "extern const char* const Custom${shadername}PostfixVertex;\n"; + print $headerFile "extern const char* const Custom${shadername}PrefixFragment;\n"; + print $headerFile "extern const char* const Custom${shadername}PostfixFragment;\n"; + $custom = 1; + } + PrintShaderProgramWithMacros($sourceFile, $shadername, "vertex", $custom); + PrintShaderProgramWithMacros($sourceFile, $shadername, "fragment", $custom); + } +} + +############################################################################### + +my($optHelp); +my($optMan); +my($shaderDir) = ""; +my($fileName) = ""; + +GetOptions( + "help" => \$optHelp, + "man" => \$optMan, + "shader-dir=s" => \$shaderDir, + "file-name=s" => \$fileName +) or pod2usage(2); + +pod2usage(1) if $optHelp; +pod2usage(-exitstatus => 0, -verbose => 2) if $optMan; + +if ($shaderDir eq "" || $fileName eq "") +{ + pod2usage(1); +} +else +{ + my $dir = $shaderDir; + my @shaderFiles = GetShaderFiles($dir); + + my $headerFile = OpenFileForWriting("$fileName.h"); + my $sourceFile = OpenFileForWriting("$fileName.cpp"); + + GenerateHeaderFileHeader($headerFile); + GenerateSourceFileHeader($sourceFile); + + my $file; + foreach $file (@shaderFiles) + { + GenerateStringsFromFile($file, $dir); + } + + PrintShaderSources($headerFile, $sourceFile); + + GenerateHeaderFileFooter($headerFile); + GenerateSourceFileFooter($sourceFile); + + CloseFile($headerFile); + CloseFile($sourceFile); +} + +############################################################################### + +__END__ + +=head1 NAME + +generate-shader-strings.pl - Given a shader directory and a file name, this script generates a header and source file where all the shaders in the directory are stored as vertex and fragment shader const char arrays. + +=head1 SYNOPSIS + +generate-shader-strings.pl -s= -f= + +generate-shader-strings.pl -shader-dir= -file-name= + +=head1 DESCRIPTION + +Given a shader directory and a file name, this script generates a header and source file where all the shaders in the directory are stored as vertex and fragment shader const char arrays. + +The shader files in the specified directory should have the suffix ".txt" and the vertex and fragment shaders should be encapsulated within * and * respectively in this text file. + +The generated source files will be called .h and .cpp. + +=head1 OPTIONS + +=over 36 + +=item B<-s|--shader-dir=> + +The directory the shader files should be loaded from. + +=item B<-f|--file-name> + +The name of the output files. diff --git a/build/tizen/.gitignore b/build/tizen/.gitignore new file mode 100644 index 0000000..644f5f5 --- /dev/null +++ b/build/tizen/.gitignore @@ -0,0 +1,21 @@ +/gmon.out +/aclocal.m4 +/autom4te.cache +/ar-lib +/compile +/config.guess +/config.log +/config.status +/config.sub +/configure +/depcomp +/install-sh +/libtool +/ltmain.sh +/missing +/demo/dali-demo +/dali-core.pc +/dali.pc +/dali-core/dali-shaders.cpp +/dali-core/dali-shaders.h +/documentation.list diff --git a/build/tizen/Makefile.am b/build/tizen/Makefile.am new file mode 100644 index 0000000..c1296f3 --- /dev/null +++ b/build/tizen/Makefile.am @@ -0,0 +1,59 @@ +# Copyright (c) 2014 Samsung Electronics Co., Ltd. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +SUBDIRS = dali-core + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = dali-core.pc + +MAINTAINERCLEANFILES = \ + aclocal.m4 \ + autom4te.cache \ + config.guess \ + config.sub \ + configure \ + depcomp \ + install-sh \ + ltmain.sh \ + missing \ + `find "$(srcdir)" -type f -name Makefile.in -print` \ + `find . \( -name "*.gcov" -o -name "*.gcno" -o -name "*.gcda" \) -print` + +CLEANFILES = \ + `find . \( -name "*.gcov" -o -name "*.gcno" -o -name "*.gcda" \) -print` + +COVERAGE_DIR=.cov +COVERAGE_OUTPUT_DIR=doc/coverage + +# From lcov version 1.10 onwards, branch coverage is off by default and earlier versions do not support the rc option +LCOV_OPTS=`if [ \`printf "\\\`lcov --version | cut -d' ' -f4\\\`\n1.10\n" | sort -V | head -n 1\` = 1.10 ] ; then echo "--rc lcov_branch_coverage=1" ; fi` + +cov_data: + @test -z $(COVERAGE_DIR) || mkdir -p $(COVERAGE_DIR) + @rm -f $(COVERAGE_DIR)/* + @cp dali-core/.libs/*.gcda dali-core/.libs/*.gcno $(COVERAGE_DIR) + @for i in `find $(COVERAGE_DIR) -name "libdali_core_la-*.gcda" -o -name "libdali_core_la-*.gcno"` ;\ + do mv $$i `echo $$i | sed s/libdali_core_la-//` ; echo $$i ; done + @for i in `find $(COVERAGE_DIR) -name "libdali_la-*.gcda" -o -name "libdali_la-*.gcno"` ;\ + do mv $$i `echo $$i | sed s/libdali_la-//` ; done + @cd $(COVERAGE_DIR) ; lcov $(LCOV_OPTS) --base-directory . --directory . -c -o dali.info + @cd $(COVERAGE_DIR) ; lcov $(LCOV_OPTS) --remove dali.info "*/dali-env/*" "/usr/include/*" -o dali.info + @test -z $(COVERAGE_OUTPUT_DIR) || mkdir -p $(COVERAGE_OUTPUT_DIR) + +coverage: cov_data + @genhtml $(LCOV_OPTS) -o $(COVERAGE_OUTPUT_DIR) $(COVERAGE_DIR)/dali.info + +reset_coverage: + @lcov -z --directory `pwd` diff --git a/build/tizen/configure.ac b/build/tizen/configure.ac new file mode 100644 index 0000000..5560206 --- /dev/null +++ b/build/tizen/configure.ac @@ -0,0 +1,117 @@ +# Copyright (c) 2014 Samsung Electronics Co., Ltd. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +m4_define([dali_version],[0.1.1]) +AC_INIT([dali], [dali_version]) +AM_INIT_AUTOMAKE([-Wall foreign]) + +AC_PROG_CXX +AC_PROG_LIBTOOL +AC_PROG_MKDIR_P + +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +LT_INIT + +DALI_VERSION=dali_version +AC_SUBST(DALI_VERSION) + +DALI_CFLAGS=-DPLATFORM_TIZEN + +AC_ARG_ENABLE(exportall, + [AC_HELP_STRING([--enable-exportall], + [enables the exporting of all the symbols in the library])], + [enable_exportall=yes], + [enable_exportall=no]) + +AC_ARG_ENABLE([debug], + [AC_HELP_STRING([--enable-debug], + [Turns on debugging])], + [enable_debug=$enableval], + [enable_debug=no]) + +AC_ARG_ENABLE([emscripten], + [AC_HELP_STRING([--enable-emscripten], + [Emscripten builds])], + [enable_emscripten=$enableval], + [enable_emscripten=no]) + +AC_ARG_ENABLE([backtrace], + [AC_HELP_STRING([--enable-backtrace], + [Backtrace for exceptions])], + [enable_backtrace=$enableval], + [enable_backtrace=yes]) + +if test "x$enable_debug" = "xyes"; then + DALI_CFLAGS="$DALI_CFLAGS -DDEBUG_ENABLED" +fi + +if test "x$enable_debug" = "xno" -a "x$enable_exportall" = "xno"; then + DALI_CFLAGS="$DALI_CFLAGS -fvisibility=hidden -DHIDE_DALI_INTERNALS" +fi + +if test "x$enable_emscripten" = "xyes"; then + DALI_CFLAGS="$DALI_CFLAGS -DEMSCRIPTEN -std=c++11" + # Automatically turn off backtrace support + enable_backtrace="no" +fi + +# Must come after Emscripten feature test +if test "x$enable_backtrace" = "xyes"; then + DALI_CFLAGS="$DALI_CFLAGS -DBACKTRACE_ENABLED" +fi + +if test x$DALI_DATA_RW_DIR != x; then + dataReadWriteDir=$DALI_DATA_RW_DIR +else + dataReadWriteDir=${prefix}/share/dali/ +fi + +if test x$DALI_DATA_RO_DIR != x; then + dataReadOnlyDir=$DALI_DATA_RO_DIR +else + dataReadOnlyDir=${prefix}/share/dali/ +fi + +DALI_CFLAGS="$DALI_CFLAGS -I${includedir}" +DALI_LDFLAGS="-L${libdir}" + +AC_SUBST(dataReadWriteDir) +AC_SUBST(dataReadOnlyDir) +AC_SUBST(DALI_CFLAGS) +AC_SUBST(DALI_LDFLAGS) + +# Specify the include directory for development headers +devincludepath=${includedir} +AC_SUBST(devincludepath) + +AC_CONFIG_FILES([ + Makefile + dali-core/Makefile + dali-core.pc +]) + +AC_OUTPUT + +echo " +Configuration +------------- + Prefix: $prefix + Debug Build: $enable_debug + Data Dir (Read/Write): $dataReadWriteDir + Data Dir (Read Only): $dataReadOnlyDir + Emscripten: $enable_emscripten + Backtrace: $enable_backtrace +" diff --git a/build/tizen/dali-core.pc.in b/build/tizen/dali-core.pc.in new file mode 100644 index 0000000..429a595 --- /dev/null +++ b/build/tizen/dali-core.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +apiversion=@DALI_VERSION@ +libdir=@libdir@ +includedir=@devincludepath@ + +Name: Samsung OpenGLES Toolkit +Description: 3D Canvas Toolkit using OpenGLES +Version: ${apiversion} +Requires: +Libs: -L${libdir} -ldali-core +Cflags: -I${includedir} diff --git a/build/tizen/dali-core/Makefile.am b/build/tizen/dali-core/Makefile.am new file mode 100644 index 0000000..0f5f12e --- /dev/null +++ b/build/tizen/dali-core/Makefile.am @@ -0,0 +1,159 @@ +# Copyright (c) 2015 Samsung Electronics Co., Ltd. + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Parse each file.list +# These files define _src_files & _header_files, +# where is the subdirectory from core_src_dir + +emoticons_dir = /usr/share/emoticons/ + +internal_src_dir = ../../../dali/internal +include ../../../dali/internal/file.list + +public_api_src_dir = ../../../dali/public-api +include ../../../dali/public-api/file.list + +devel_api_src_dir = ../../../dali/devel-api +include ../../../dali/devel-api/file.list + +platform_abstraction_src_dir = ../../../dali/integration-api +include ../../../dali/integration-api/file.list + +# Build the Dali libtool library + +src_files = $(internal_src_files) \ + $(effects_src_files) \ + $(platform_abstraction_src_files) \ + $(public_api_src_files) \ + $(devel_api_src_files) + +lib_LTLIBRARIES = libdali-core.la + +libdali_core_la_SOURCES = $(dali_shaders_src_file) \ + $(src_files) + +scripts_dir = ../../scripts +dali_shaders_script = $(scripts_dir)/generate-shader-strings.pl +dali_shaders_dir = ../../../dali/internal/render/shader-source + +$(nodist_libdali_core_la_OBJECTS): $(dali_shaders_src_file) + +dali_shaders_src_file = dali-shaders.cpp + +dali-shaders.cpp: $(dali_shaders_script) $(dali_shaders_dir)/*.txt + $< --shader-dir=$(dali_shaders_dir) --file-name=dali-shaders + +dali_core_includes = \ + -I../../.. + +cxx_flags = -Werror -Wall -Wextra -Wno-unused-parameter -Wfloat-equal + +libdali_core_la_CXXFLAGS = -DDALI_COMPILATION \ + -DDALI_DATA_RW_DIR="\"${daliReadWriteDir}\"" \ + -DDALI_DATA_RO_DIR="\"${daliReadOnlyDir}\"" \ + -DDALI_EMOTICON_DIR="\"${emoticons_dir}\"" \ + $(cxx_flags) \ + $(dali_core_includes) \ + $(DALI_CFLAGS) + +libdali_core_la_LIBADD = $(DALI_LDFLAGS) \ + -lpthread + +# Install headers under the correct subdirectories +platformabstractiondir = $(includedir)/dali/integration-api +platformabstractioneventsdir = $(includedir)/dali/integration-api/events + +platformabstraction_HEADERS = $(platform_abstraction_header_files) +platformabstractionevents_HEADERS = $(platform_abstraction_events_header_files) + +#devel api (used by adaptor / toolkit +develapidir = $(devincludepath)/dali/devel-api +develapiactorsdir = $(develapidir)/actors +develapianimationdir = $(develapidir)/animation +develapicommondir = $(develapidir)/common +develapieventsdir = $(develapidir)/events +develapigeometrydir = $(develapidir)/geometry +develapiimagesdir = $(develapidir)/images +develapimodelingdir = $(develapidir)/modeling +develapiobjectdir = $(develapidir)/object +develapirenderingdir = $(develapidir)/rendering +develapiscriptingdir = $(develapidir)/scripting + +develapi_HEADERS = $(devel_api_header_files) +develapiactors_HEADERS = $(devel_api_core_actors_header_files) +develapianimation_HEADERS = $(devel_api_core_animation_header_files) +develapicommon_HEADERS = $(devel_api_core_common_header_files) +develapievents_HEADERS = $(devel_api_core_events_header_files) +develapiimages_HEADERS = $(devel_api_core_images_header_files) +develapimodeling_HEADERS = $(devel_api_core_modeling_header_files) +develapiobject_HEADERS = $(devel_api_core_object_header_files) +develapirendering_HEADERS = $(devel_api_core_rendering_header_files) +develapiscripting_HEADERS = $(devel_api_core_scripting_header_files) + + + +#public api +publicapidir = $(devincludepath)/dali/public-api +publicapiactorsdir = $(publicapidir)/actors +publicapianimationdir = $(publicapidir)/animation +publicapicommondir = $(publicapidir)/common +publicapieventsdir = $(publicapidir)/events +publicapiimagesdir = $(publicapidir)/images +publicapimathdir = $(publicapidir)/math +publicapiobjectdir = $(publicapidir)/object +publicapirendertasksdir = $(publicapidir)/render-tasks +publicapishadereffectsdir = $(publicapidir)/shader-effects +publicapisignalsdir = $(publicapidir)/signals + +publicapisizenegotiationdir = $(publicapidir)/size-negotiation + +publicapi_HEADERS = $(public_api_header_files) +publicapiactors_HEADERS = $(public_api_core_actors_header_files) +publicapianimation_HEADERS = $(public_api_core_animation_header_files) +publicapicommon_HEADERS = $(public_api_core_common_header_files) +publicapievents_HEADERS = $(public_api_core_events_header_files) +publicapiimages_HEADERS = $(public_api_core_images_header_files) +publicapimath_HEADERS = $(public_api_core_math_header_files) +publicapirendertasks_HEADERS = $(public_api_core_render_tasks_header_files) +publicapiobject_HEADERS = $(public_api_core_object_header_files) +publicapisizenegotiation_HEADERS = $(public_api_core_size_negotiation_header_files) +publicapishadereffects_HEADERS = $(public_api_core_shader_effects_header_files) +publicapisignals_HEADERS = $(public_api_core_signals_header_files) + +CLEANFILES = dali-shaders.cpp \ + dali-shaders.h + +# linking test + +noinst_PROGRAMS = linker.test + +linker_test_SOURCES = linker-test.cpp \ + ../../../automated-tests/src/dali/dali-test-suite-utils/test-application.cpp \ + ../../../automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.cpp \ + ../../../automated-tests/src/dali/dali-test-suite-utils/test-render-controller.cpp \ + ../../../automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.cpp \ + ../../../automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.cpp \ + ../../../automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp \ + ../../../automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp + +linker_test_CXXFLAGS = \ + $(cxx_flags) \ + -I../../../automated-tests/src/dali/dali-test-suite-utils \ + $(dali_core_includes) \ + $(DALI_CFLAGS) + +linker_test_DEPENDENCIES = libdali-core.la +linker_test_LDADD = \ + libdali-core.la diff --git a/build/tizen/dali-core/linker-test.cpp b/build/tizen/dali-core/linker-test.cpp new file mode 100644 index 0000000..274c0dc --- /dev/null +++ b/build/tizen/dali-core/linker-test.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "dali/public-api/dali-core.h" + +#include +#include + +// Link with TET Test application, need to redefine TET functions +void tet_infoline(const char* str) +{ + puts(str); +} + +void tet_printf(const char* str, ...) +{ + va_list args; + va_start(args, str); + vprintf(str, args); + va_end(args); +} + + +#include "test-application.h" + +/***************************************************************************** + * Test to see if dali is linking correctly. + * Only really tests that the internal function/method definitions exist and + * links to functions/methods in other libraries linked by Dali-Core. + * If a definition of the Public or Integration API does not exist, then it + * will not be checked here. + * Also ensures TET Test Application is kept up-to-date. + */ + +int main(int argc, char **argv) +{ +#ifndef _ARCH_ARM_ + Dali::TestApplication application; +#endif + return 0; +} diff --git a/dali.manifest b/dali.manifest new file mode 100644 index 0000000..97e8c31 --- /dev/null +++ b/dali.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/dali/.gitignore b/dali/.gitignore new file mode 100644 index 0000000..6e92f57 --- /dev/null +++ b/dali/.gitignore @@ -0,0 +1 @@ +tags diff --git a/dali/devel-api/animation/path-constrainer.cpp b/dali/devel-api/animation/path-constrainer.cpp new file mode 100644 index 0000000..cb32010 --- /dev/null +++ b/dali/devel-api/animation/path-constrainer.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +PathConstrainer PathConstrainer::New() +{ + Internal::PathConstrainer* internal = Internal::PathConstrainer::New(); + return PathConstrainer(internal); +} + +PathConstrainer PathConstrainer::DownCast( BaseHandle handle ) +{ + return PathConstrainer( dynamic_cast(handle.GetObjectPtr()) ); +} + +PathConstrainer::PathConstrainer() +{ +} + +PathConstrainer::~PathConstrainer() +{ +} + +PathConstrainer::PathConstrainer(const PathConstrainer& handle) +:Handle(handle) +{ +} + +PathConstrainer::PathConstrainer(Internal::PathConstrainer* internal) +: Handle(internal) +{ +} + +PathConstrainer& PathConstrainer::operator=(const PathConstrainer& rhs) +{ + BaseHandle::operator=(rhs); + return *this; +} + +void PathConstrainer::Apply( Dali::Property target, Dali::Property source, const Vector2& range, const Vector2& wrap ) +{ + GetImplementation(*this).Apply( target, source, range, wrap ); +} + +void PathConstrainer::Remove( Dali::Handle& target ) +{ + GetImplementation(*this).Remove( target ); +} + + +} // Dali diff --git a/dali/devel-api/animation/path-constrainer.h b/dali/devel-api/animation/path-constrainer.h new file mode 100644 index 0000000..6790a25 --- /dev/null +++ b/dali/devel-api/animation/path-constrainer.h @@ -0,0 +1,136 @@ +#ifndef __DALI_PATH_CONSTRAINER_H__ +#define __DALI_PATH_CONSTRAINER_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +//EXTERNAL INCLUDES +#include //For FLT_MAX + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Internal DALI_INTERNAL +{ + class PathConstrainer; +} +/** + * @brief + * + * PathConstrainer applies constraints to objects to follow a path. + * A Vector3 property will be constrained to the position of the path and a Rotation property will be constrained to follow + * the tangent of the path given a forward vector in object's local space. + * + */ +class DALI_IMPORT_API PathConstrainer : public Handle +{ +public: + + /** + * @brief An enumeration of properties belonging to the PathConstrainer class. + */ + struct Property + { + enum + { + FORWARD = DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "forward" type Vector3 + POINTS, ///< name "points" type Array of Vector3 + CONTROL_POINTS ///< name "control-points" type Array of Vector3 + }; + }; + + /** + * @brief Create an initialized PathConstrainer handle. + * + * @return a handle to a newly allocated Dali resource. + */ + static PathConstrainer New(); + + /** + * @brief Downcast an Object handle to PathConstrainer handle. + * + * If handle points to a PathConstrainer object the downcast produces + * valid handle. If not the returned handle is left uninitialized. + * @param[in] handle to An object + * @return handle to a PathConstrainer object or an uninitialized handle + */ + static PathConstrainer DownCast( BaseHandle handle ); + + /** + * @brief Create an uninitialized PathConstrainer handle. + * + * This can be initialized with PathConstrainer::New(). Calling member + * functions with an uninitialized Dali::Object is not allowed. + */ + PathConstrainer(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~PathConstrainer(); + + /** + * @brief This copy constructor is required for (smart) pointer semantics. + * + * @param [in] handle A reference to the copied handle + */ + PathConstrainer(const PathConstrainer& handle); + + /** + * @brief This assignment operator is required for (smart) pointer semantics. + * + * @param [in] rhs A reference to the copied handle + * @return A reference to this + */ + PathConstrainer& operator=(const PathConstrainer& rhs); + + /** + * @brief Applies the path constraint to the target property + * + * @param[in] target Property to be constrained + * @param[in] source Property used as parameter for the path + * @param[in] range The range of values in the source property which will be mapped to [0,1] + * @param[in] wrap Wrapping domain. Source property will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1] + */ + void Apply( Dali::Property target, Dali::Property source, const Vector2& range, const Vector2& wrap = Vector2(-FLT_MAX, FLT_MAX) ); + + /** + * @brief Removes the path constraint in the target object + * + * @param[in] target A handle to an object constrained by the PathConstrainer + */ + void Remove( Dali::Handle& target ); + +public: // Not intended for application developers + /** + * @brief This constructor is used by Dali::New() methods. + * + * @param[in] pathConstrainer A pointer to an internal PathConstrainer resource + */ + explicit DALI_INTERNAL PathConstrainer(Internal::PathConstrainer* pathConstrainer); +}; + +} // namespace Dali + +#endif // __DALI_PATH_CONSTRAINER_H__ diff --git a/dali/devel-api/common/hash.cpp b/dali/devel-api/common/hash.cpp new file mode 100644 index 0000000..1cfcf11 --- /dev/null +++ b/dali/devel-api/common/hash.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace //unnamed namespace +{ + +/* + * djb2 (http://www.cse.yorku.ca/~oz/hash.html) + */ +const std::size_t INITIAL_HASH_VALUE = 5381; + +inline void HashString( const char* string, std::size_t& hash ) +{ + while( int c = *string++ ) + { + hash = hash * 33 + c; + } +} + +} // unnamed namespace + +std::size_t CalculateHash( const std::string& toHash) +{ + std::size_t hash( INITIAL_HASH_VALUE ); + + HashString( toHash.c_str(), hash ); + + return hash; +} + +std::size_t CalculateHash( const std::string& string1, const std::string& string2 ) +{ + std::size_t hash( INITIAL_HASH_VALUE ); + + HashString( string1.c_str(), hash); + HashString( string2.c_str(), hash ); + + return hash; +} + +} // namespace Dali diff --git a/dali/devel-api/common/hash.h b/dali/devel-api/common/hash.h new file mode 100644 index 0000000..246907b --- /dev/null +++ b/dali/devel-api/common/hash.h @@ -0,0 +1,48 @@ +#ifndef __DALI_HASH__ +#define __DALI_HASH__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +//INTERNAL INCLUDES +#include + +namespace Dali +{ + +/** + * @brief Create a hash code for a string + * @param toHash string to hash + * @return hash code + */ +DALI_IMPORT_API std::size_t CalculateHash( const std::string& toHash ); + +/** + * @brief Create a hash code for 2 strings combined. + * Allows a hash to be calculated without concatenating the strings and allocating any memory. + * @param string1 first string + * @param string2 second string + * @return hash code + */ +DALI_IMPORT_API std::size_t CalculateHash( const std::string& string1, const std::string& string2 ); + +} // namespace Dali + +#endif // __DALI_HASH__ diff --git a/dali/devel-api/common/map-wrapper.h b/dali/devel-api/common/map-wrapper.h new file mode 100644 index 0000000..070f0e9 --- /dev/null +++ b/dali/devel-api/common/map-wrapper.h @@ -0,0 +1,47 @@ +#ifndef __DALI_MAP_H__ +#define __DALI_MAP_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + + +#ifndef HIDE_DALI_INTERNALS + +# include + +#else + +// ensure that default visibility is used with any class that is used as an exception type +# include +# include +# include + +# include +# include +# undef _GLIBCXX_VISIBILITY_ATTR +# define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ ("hidden"))) +# include +# undef _GLIBCXX_VISIBILITY_ATTR +# define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ (#V))) // restore `_GLIBCXX_VISIBILITY_ATTR` + +#endif //ifndef HIDE_DALI_INTERNALS + + +#endif /* __DALI_MAP_H__ */ diff --git a/dali/devel-api/common/mutex.cpp b/dali/devel-api/common/mutex.cpp new file mode 100644 index 0000000..37f9d33 --- /dev/null +++ b/dali/devel-api/common/mutex.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ + +struct Mutex::MutexImpl +{ + pthread_mutex_t mutex; + bool locked; +}; + +Mutex::Mutex() +: mImpl( new MutexImpl ) +{ + pthread_mutex_init( &mImpl->mutex, NULL ); + mImpl->locked = false; +} + +Mutex::~Mutex() +{ + pthread_mutex_destroy( &mImpl->mutex ); + // nothing else to do as there is no Lock/Unlock API + // ScopedLock destructor will always unlock the mutex + delete mImpl; +} + +bool Mutex::IsLocked() +{ + return mImpl->locked; +} + +Mutex::ScopedLock::ScopedLock( Mutex& mutex ) +: mMutex( mutex ) +{ + pthread_mutex_lock( &mMutex.mImpl->mutex ); + mMutex.mImpl->locked = true; +} + +Mutex::ScopedLock::~ScopedLock() +{ + mMutex.mImpl->locked = false; + pthread_mutex_unlock( &mMutex.mImpl->mutex ); +} + +} // namespace Dali diff --git a/dali/devel-api/common/mutex.h b/dali/devel-api/common/mutex.h new file mode 100644 index 0000000..cd41f9a --- /dev/null +++ b/dali/devel-api/common/mutex.h @@ -0,0 +1,92 @@ +#ifndef __DALI_MUTEX_H__ +#define __DALI_MUTEX_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +/** + * The top level DALi namespace + */ +namespace Dali +{ + +/** + * Class to synchronize access to critical resources from multiple threads + */ +class DALI_IMPORT_API Mutex +{ +public: + + /** + * @brief Constructor, acquires the mutex from the underlying OS + */ + Mutex(); + + /** + * @brief Destructor, non virtual as this is not meant as a base class + */ + ~Mutex(); + + /** + * @brief Check if the mutex is locked + * @return true if the mutex is locked + */ + bool IsLocked(); + +public: + + /** + * Helper class to do a scoped lock on a mutex implementing the RAII idiom. + * Note! this class *does not* prevent a deadlock in the case when same thread is + * locking the same mutex twice. + */ + class ScopedLock + { + public: + + /** + * Constructor + * @param mutex to lock + */ + ScopedLock( Mutex& mutex ); + + /** + * Destructor, releases the lock + */ + ~ScopedLock(); + + private: + Mutex& mMutex; + }; + +private: + + /// Not implemented as Mutex is not copyable + Mutex( const Mutex& ); + const Mutex& operator= ( const Mutex& ); + + struct MutexImpl; + MutexImpl* mImpl; + +}; + +} // namespace Dali + +#endif // __DALI_MUTEX_H__ diff --git a/dali/devel-api/common/ref-counted-dali-vector.h b/dali/devel-api/common/ref-counted-dali-vector.h new file mode 100644 index 0000000..d3719d7 --- /dev/null +++ b/dali/devel-api/common/ref-counted-dali-vector.h @@ -0,0 +1,73 @@ +#ifndef __REF_COUNTED_DALI_VECTOR_H__ +#define __REF_COUNTED_DALI_VECTOR_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +/** + * @brief A reference counting wrapper for a vector class that allows + * a set of referencing smart pointers to collaborate in managing its + * lifetime and eventually cleaning it up. + * + * This should only be allocated on the new/delete heap, not a thread's + * stack. + * @tparam T type of the data that the vector holds + */ +template< typename T > +class RefCountedVector : public RefObject +{ +public: + /** + * @brief Construct empty vector. + */ + RefCountedVector() + { + } + + /** + * @brief Get the referenced vector. + * + * @return A reference to the vector that this object wraps. + */ + Vector< T >& GetVector() + { + return mVector; + } + +protected: + virtual ~RefCountedVector() + { + } + +private: + // Disable copy-constructing and copying: + RefCountedVector(const RefCountedVector &); ///< Undefined + RefCountedVector & operator = (const RefCountedVector &); ///< Undefined + + Vector< T > mVector; ///< The vector of data +}; + +} // namespace Dali + +#endif /* __REF_COUNTED_DALI_VECTOR_H__ */ diff --git a/dali/devel-api/common/set-wrapper.h b/dali/devel-api/common/set-wrapper.h new file mode 100644 index 0000000..d3b3ab1 --- /dev/null +++ b/dali/devel-api/common/set-wrapper.h @@ -0,0 +1,45 @@ +#ifndef __DALI_SET_H__ +#define __DALI_SET_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +// EXTERNAL INCLUDES + +#ifndef HIDE_DALI_INTERNALS + +# include + +#else + +// ensure that default visibility is used with any class that is used as an exception type +# include +# include +# include + +# include +# include +# undef _GLIBCXX_VISIBILITY_ATTR +# define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ ("hidden"))) +# include +# undef _GLIBCXX_VISIBILITY_ATTR +# define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ (#V))) // restore `_GLIBCXX_VISIBILITY_ATTR` + +#endif //ifndef HIDE_DALI_INTERNALS + +#endif /* __DALI_SET_H__ */ diff --git a/dali/devel-api/events/hit-test-algorithm.cpp b/dali/devel-api/events/hit-test-algorithm.cpp new file mode 100644 index 0000000..666143c --- /dev/null +++ b/dali/devel-api/events/hit-test-algorithm.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace HitTestAlgorithm +{ + +bool HitTest( Stage stage, const Vector2& screenCoordinates, Results& results, HitTestFunction func ) +{ + return Internal::HitTestAlgorithm::HitTest( GetImplementation(stage), screenCoordinates, results, func ); +} + +bool HitTest( RenderTask& renderTask, const Vector2& screenCoordinates, Results& results, HitTestFunction func ) +{ + Stage stage = Stage::GetCurrent(); + return Internal::HitTestAlgorithm::HitTest( GetImplementation( stage ), GetImplementation(renderTask), screenCoordinates, results, func ); +} + +} // namespace HitTestAlgorithm + +} // namespace Dali diff --git a/dali/devel-api/events/hit-test-algorithm.h b/dali/devel-api/events/hit-test-algorithm.h new file mode 100644 index 0000000..913a2af --- /dev/null +++ b/dali/devel-api/events/hit-test-algorithm.h @@ -0,0 +1,163 @@ +#ifndef __DALI_HIT_TEST_ALGORITHM_H__ +#define __DALI_HIT_TEST_ALGORITHM_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include + + +namespace Dali +{ + +class RenderTask; + +/** + * @brief This namespace is provided for application developers to do hit-test for the actors. + * + *

Hit Test Algorithm:

+ * + * Hit testing is dependent on the camera used, which is specific to each RenderTask. For each RenderTask, + * hit testing starts from the top-most layer and we go through all the layers until we have a hit or there + * are none left. Before we perform a hit test within a layer, we check if all the layer's parents meet the + * conditions defined by the function ((e.g. whether it is visible)). If they are not, we skip hit testing + * the actors in that layer altogether. Otherwise, we walk through the actor tree within a layer to check + * whether the actors within the actor tree should be hit-tested. + * + * The following pseudocode gives an example of what the function can typically check, which should normally + * be provided by the application code: + * + * @code + * HIT-TEST-FUNCTION( ACTOR, TRAVERSE-TYPE ) + * { + * if( TRAVERSE-TYPE == CHECK_ACTOR ) // Check whether current actor should be hit-tested + * { + * if( ACTOR-IS-VISIBLE && + * ACTOR-WORLD-COLOR-IS-NOT-TRANSPARENT ) + * { + * HITTABLE = TRUE + * } + * } + * else if( TRAVERSE-TYPE == DESCEND_ACTOR_TREE ) ///< Check whether the actor tree should be descended to hit-test its children. + * { + * if( ACTOR-IS-VISIBLE ) + * { + * HITTABLE = TRUE + * } + * } + * } + * @endcode + * + * The following pseudocode explains how the algorithm performs the hit-test with the above functor: + * + * @code + * HIT-TEST-WITHIN-LAYER( ACTOR ) + * { + * // Depth-first traversal within current layer, visiting parent first + * + * // Check whether current actor should be hit-tested + * IF ( HIT-TEST-FUNCTION( ACTOR, CHECK_ACTOR ) && + * ACTOR-HAS-NON-ZERO-SIZE ) + * { + * // Hit-test current actor + * IF ( ACTOR-HIT ) + * { + * IF ( DISTANCE-TO-ACTOR < DISTANCE-TO-LAST-HIT-ACTOR ) + * { + * // The current actor is the closest actor that was underneath the touch + * LAST-HIT-ACTOR = CURRENT-ACTOR + * } + * } + * } + * + * // Keep checking children, in case we hit something closer + * FOR-EACH CHILD (in order) + * { + * IF ( HIT-TEST-FUNCTION( ACTOR, DESCEND_ACTOR_TREE ) && + * ACTOR-IS-NOT-A-LAYER ) + * { + * // Continue traversal for this child's sub-tree + * HIT-TEST-WITHIN-LAYER ( CHILD ) + * } + * // else we skip the sub-tree with from this child + * } + * } + * @endcode + */ +namespace HitTestAlgorithm +{ + +/** + * @brief How the actor tree should be traversed. + */ +enum TraverseType +{ + CHECK_ACTOR, ///< Hit test the given actor. + DESCEND_ACTOR_TREE ///< Check whether the actor tree should be descended to hit-test its children. +}; + +/** + * @brief Results structure containing the hit actor and where it was hit. + */ +struct Results +{ + Actor actor; ///< The hit actor. + Vector2 actorCoordinates; ///< The actor coordinates. +}; + +/** + * @brief Definition of a hit-test function to use in HitTest() method to check if the actor is hittable (e.g. touchable or focusable). + * + * @return true, if the actor is hittable, false otherwise. + */ +typedef bool (*HitTestFunction)(Actor actor, TraverseType type); + +/** + * @brief Given screen coordinates, this method returns the hit actor & the local coordinates relative to + * the top-left (0.0f, 0.0f, 0.5f) of the actor. + * + * An actor is only hittable if the actor meets all the conditions + * defined by the given function (see HitTestAlgorithm). + * + * Typically, if an actor has a zero size or its world color is fully transparent, it should not be + * hittable; and if an actor's visibility flag is unset, its children should not be hittable either. + * + * @param[in] stage The stage. + * @param[in] screenCoordinates The screen coordinates. + * @param[out] results The results of the hit-test, only modified if something is hit + * @param[in] func The function to use in the hit-test algorithm. + * @return true if something was hit + */ +DALI_IMPORT_API bool HitTest( Stage stage, const Vector2& screenCoordinates, Results& results, HitTestFunction func ); + +/** + * @brief Hit test specific to a given RenderTask. + * + * @param[in] renderTask The render task for hit test + * @param[in] screenCoordinates The screen coordinates. + * @param[out] results The results of the hit-test, only modified if something is hit + * @param[in] func The function to use in the hit-test algorithm. + * @return true if something was hit + */ +DALI_IMPORT_API bool HitTest( RenderTask& renderTask, const Vector2& screenCoordinates, Results& results, HitTestFunction func ); + +} // namespace HitTestAlgorithm + +} // namespace Dali + +#endif // __DALI_HIT_TEST_ALGORITHM_H__ diff --git a/dali/devel-api/file.list b/dali/devel-api/file.list new file mode 100644 index 0000000..5c00ebf --- /dev/null +++ b/dali/devel-api/file.list @@ -0,0 +1,55 @@ +# Add devel source files here for DALi internal developer files used by Adaptor & Toolkit + +devel_api_src_files = \ + $(devel_api_src_dir)/animation/path-constrainer.cpp \ + $(devel_api_src_dir)/common/hash.cpp \ + $(devel_api_src_dir)/common/mutex.cpp \ + $(devel_api_src_dir)/events/hit-test-algorithm.cpp \ + $(devel_api_src_dir)/images/atlas.cpp \ + $(devel_api_src_dir)/images/distance-field.cpp \ + $(devel_api_src_dir)/object/property-buffer.cpp \ + $(devel_api_src_dir)/object/weak-handle.cpp \ + $(devel_api_src_dir)/rendering/cull-face.cpp \ + $(devel_api_src_dir)/rendering/geometry.cpp \ + $(devel_api_src_dir)/rendering/material.cpp \ + $(devel_api_src_dir)/rendering/renderer.cpp \ + $(devel_api_src_dir)/rendering/sampler.cpp \ + $(devel_api_src_dir)/rendering/shader.cpp \ + $(devel_api_src_dir)/scripting/scripting.cpp + +# Add devel header files here DALi internal developer files used by Adaptor & Toolkit + +devel_api_core_animation_header_files = \ + $(devel_api_src_dir)/animation/path-constrainer.h + +devel_api_core_common_header_files = \ + $(devel_api_src_dir)/common/hash.h \ + $(devel_api_src_dir)/common/map-wrapper.h \ + $(devel_api_src_dir)/common/mutex.h \ + $(devel_api_src_dir)/common/ref-counted-dali-vector.h \ + $(devel_api_src_dir)/common/set-wrapper.h + +devel_api_core_events_header_files = \ + $(devel_api_src_dir)/events/hit-test-algorithm.h + +devel_api_core_images_header_files = \ + $(devel_api_src_dir)/images/atlas.h \ + $(devel_api_src_dir)/images/distance-field.h + +devel_api_core_object_header_files = \ + $(devel_api_src_dir)/object/property-buffer.h \ + $(devel_api_src_dir)/object/type-registry-helper.h \ + $(devel_api_src_dir)/object/weak-handle.h + +devel_api_core_rendering_header_files = \ + $(devel_api_src_dir)/rendering/cull-face.h \ + $(devel_api_src_dir)/rendering/geometry.h \ + $(devel_api_src_dir)/rendering/material.h \ + $(devel_api_src_dir)/rendering/renderer.h \ + $(devel_api_src_dir)/rendering/sampler.h \ + $(devel_api_src_dir)/rendering/shader.h + +devel_api_core_scripting_header_files = \ + $(devel_api_src_dir)/scripting/scripting.h + + diff --git a/dali/devel-api/images/atlas.cpp b/dali/devel-api/images/atlas.cpp new file mode 100644 index 0000000..f7f96d1 --- /dev/null +++ b/dali/devel-api/images/atlas.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +Atlas Atlas::New( SizeType width, + SizeType height, + Pixel::Format pixelFormat, + bool recoverContext ) +{ + DALI_ASSERT_ALWAYS( 0u != width && "Invalid Atlas width requested" ); + DALI_ASSERT_ALWAYS( 0u != height && "Invalid Atlas height requested" ); + + return Atlas( Internal::Atlas::New( width, height, pixelFormat, recoverContext ) ); +} + +Atlas::Atlas() +{ +} + +void Atlas::Clear( const Vector4& color ) +{ + GetImplementation( *this ).Clear( color ); +} + +bool Atlas::Upload( BufferImage bufferImage, + SizeType xOffset, + SizeType yOffset ) +{ + return GetImplementation(*this).Upload( GetImplementation(bufferImage), xOffset, yOffset ); +} + +bool Atlas::Upload( const std::string& url, + SizeType xOffset, + SizeType yOffset ) +{ + return GetImplementation(*this).Upload( url, xOffset, yOffset ); +} + +Atlas Atlas::DownCast( BaseHandle handle ) +{ + return Atlas( dynamic_cast(handle.GetObjectPtr()) ); +} + +Atlas::~Atlas() +{ +} + +Atlas::Atlas( const Atlas& handle ) +: Image( handle ) +{ +} + +Atlas& Atlas::operator=( const Atlas& rhs ) +{ + BaseHandle::operator=(rhs); + return *this; +} + +Atlas::Atlas( Internal::Atlas* internal ) +: Image( internal ) +{ +} + +} // namespace Dali diff --git a/dali/devel-api/images/atlas.h b/dali/devel-api/images/atlas.h new file mode 100644 index 0000000..025b9ad --- /dev/null +++ b/dali/devel-api/images/atlas.h @@ -0,0 +1,156 @@ +#ifndef __DALI_ATLAS_H__ +#define __DALI_ATLAS_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Internal DALI_INTERNAL +{ +class Atlas; +} + +/** + * @brief An Atlas is a large image containing multiple smaller images. + * + * Buffer image and resource image( by providing the url ) are supported for uploading. + * Images must be uploaded at a specified position, to populate the Atlas. + * The client is responsible for generating the appropriate geometry (UV coordinates) needed to draw images within the Atlas. + * + * For context recovery after loss: + * By default, the atlas will re-upload the resource images automatically, + * while the buffer images are left to the client to upload again by connecting to the Stage::ContextRegainedSignal(). + * If resource and buffer images are mixed and they overlap inside the atlas, the recovered contents may be incorrect. + * In these case, switch off the context recovery by calling SetContextRecovery( false ), + * and upload both buffer images and resource image to the atlas in order to restore the atlas. + */ +class DALI_IMPORT_API Atlas : public Image +{ +public: + + typedef uint32_t SizeType; + +public: + + /** + * @brief Create a new Atlas. + * + * @pre width & height are greater than zero. + * The maximum size of the atlas is limited by GL_MAX_TEXTURE_SIZE. + * @param [in] width The atlas width in pixels. + * @param [in] height The atlas height in pixels. + * @param [in] pixelFormat The pixel format (rgba 32 bit by default). + * @param [in] recoverContext Whether re-uploading the resource images automatically when regaining the context( true by default ) + * @return A handle to a new Atlas. + */ + static Atlas New( SizeType width, + SizeType height, + Pixel::Format pixelFormat = Pixel::RGBA8888, + bool recoverContext = true ); + + /** + * @brief Create an empty handle. + * + * Calling member functions of an empty handle is not allowed. + */ + Atlas(); + + /** + * @brief Clear the Atlas with the given color + * + * @note The Atlas does not clear itself automatically during construction. + * Application should call this clear function to avoid getting garbage pixels in the atlas. + * By calling Clear, all the current uploaded image information will be lost. + * @param [in] color The color used to clear the Atlas. + */ + void Clear( const Vector4& color ); + + /** + * @brief Upload a buffer image to the atlas. + * + * @pre The pixel format of this buffer image must match the Atlas format. + * @param [in] bufferImage The buffer image to upload. + * @param [in] xOffset Specifies an offset in the x direction within the atlas. + * @param [in] yOffset Specifies an offset in the y direction within the atlas. + * @return True if the image has compatible pixel format and fits within the atlas at the specified offset. + */ + bool Upload( BufferImage bufferImage, + SizeType xOffset, + SizeType yOffset ); + + /** + * @brief Upload a resource image to atlas + * + * @param [in] url The URL of the resource image file to use + * @param [in] xOffset Specifies an offset in the x direction within the atlas. + * @param [in] yOffset Specifies an offset in the y direction within the atlas. + * @return True if the image has compatible pixel format and fits within the atlas at the specified offset. + */ + bool Upload( const std::string& url, + SizeType xOffset, + SizeType yOffset ); + /** + * @brief Downcast an Object handle to Atlas. + * + * If handle points to a Atlas the downcast produces valid + * handle. If not the returned handle is left uninitialized. + * + * @param[in] handle to An object + * @return handle to a Atlas or an empty handle + */ + static Atlas DownCast( BaseHandle handle ); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~Atlas(); + + /** + * @brief This copy constructor is required for (smart) pointer semantics. + * + * @param [in] handle A reference to the copied handle + */ + Atlas( const Atlas& handle ); + + /** + * @brief This assignment operator is required for (smart) pointer semantics. + * + * @param [in] rhs A reference to the copied handle + * @return A reference to this + */ + Atlas& operator=( const Atlas& rhs); + +public: // Not intended for application developers + + explicit DALI_INTERNAL Atlas( Internal::Atlas* ); +}; + +} // namespace Dali + +#endif // __DALI_ATLAS_H__ diff --git a/dali/devel-api/images/distance-field.cpp b/dali/devel-api/images/distance-field.cpp new file mode 100644 index 0000000..134f9c4 --- /dev/null +++ b/dali/devel-api/images/distance-field.cpp @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace +{ + +float Interpolate( float a, float b, float factor ) +{ + return a * (1.0f - factor) + b * factor; +} + +float Bilinear( float a, float b, float c, float d, float dx, float dy ) +{ + return Interpolate( Interpolate( a, b, dx), Interpolate( c, d, dx ), dy ); +} + +void ScaleField( int width, int height, float* in, int targetWidth, int targetHeight, float* out ) +{ + float xScale = static_cast< float >(width) / targetWidth; + float yScale = static_cast< float >(height) / targetHeight; + + // for each row in target + for(int y = 0; y < targetHeight; ++y) + { + const int sampleY = static_cast< int >( yScale * y ); + const int otherY = std::min( sampleY + 1, height - 1 ); + const float dy = (yScale * y ) - sampleY; + + // for each column in target + for (int x = 0; x < targetWidth; ++x) + { + const int sampleX = static_cast< int >( xScale * x ); + const int otherX = std::min( sampleX + 1, width - 1 ); + const float dx = (xScale * x) - sampleX; + + float value = Bilinear( in[ sampleY * width + sampleX ], + in[ sampleY * width + otherX ], + in[ otherY * width + sampleX ], + in[ otherY * width + otherX ], + dx, dy ); + + out[y * targetWidth + x] = std::min( value, 1.0f ); + } + } +} + +#define SQUARE(a) ((a) * (a)) +const float MAX_DISTANCE( 1e20 ); + +/** + * Distance transform of 1D function using squared distance + */ +void DistanceTransform( float *source, float* dest, unsigned int length ) +{ + int parabolas[length]; // Locations of parabolas in lower envelope + float edge[length + 1]; // Locations of boundaries between parabolas + int rightmost(0); // Index of rightmost parabola in lower envelope + + parabolas[0] = 0; + edge[0] = -MAX_DISTANCE; + edge[1] = +MAX_DISTANCE; + for( unsigned int i = 1; i <= length - 1; i++ ) + { + const float initialDistance( source[i] + SQUARE( i ) ); + int parabola = parabolas[rightmost]; + float newDistance( (initialDistance - (source[parabola] + SQUARE( parabola ))) / (2 * i - 2 * parabola) ); + while( rightmost > 0 && newDistance <= edge[rightmost] ) + { + rightmost--; + parabola = parabolas[rightmost]; + newDistance = (initialDistance - (source[parabola] + SQUARE( parabola ))) / (2 * i - 2 * parabola); + } + + rightmost++; + parabolas[rightmost] = i; + edge[rightmost] = newDistance; + edge[rightmost + 1] = MAX_DISTANCE; + } + + rightmost = 0; + for( unsigned int i = 0; i <= length - 1; ++i ) + { + while( edge[rightmost + 1] < i ) + { + ++rightmost; + } + dest[i] = SQUARE( i - parabolas[rightmost] ) + source[parabolas[rightmost]]; + } +} + +/** + * Distance transform of 2D function using squared distance + */ +void DistanceTransform( float* data, unsigned int width, unsigned int height, float* sourceBuffer, float* destBuffer ) +{ + // transform along columns + for( unsigned int x = 0; x < width; ++x ) + { + for( unsigned int y = 0; y < height; ++y ) + { + sourceBuffer[y] = data[ y * width + x ]; + } + + DistanceTransform( sourceBuffer, destBuffer, height ); + + for( unsigned int y = 0; y < height; y++ ) + { + data[y * width + x] = destBuffer[y]; + } + } + + // transform along rows + for( unsigned int y = 0; y < height; ++y ) + { + for( unsigned int x = 0; x < width; ++x ) + { + sourceBuffer[x] = data[ y * width + x ]; + } + + DistanceTransform( sourceBuffer, destBuffer, width ); + + for( unsigned int x = 0; x < width; x++ ) + { + data[y * width + x] = destBuffer[x]; + } + } +} + +} // namespace + +void GenerateDistanceFieldMap(const unsigned char* const imagePixels, const Size& imageSize, + unsigned char* const distanceMap, const Size& distanceMapSize, + const float fieldRadius, const unsigned int fieldBorder, bool highQuality) +{ + GenerateDistanceFieldMap( imagePixels, imageSize, distanceMap, distanceMapSize, fieldBorder, imageSize, highQuality ); +} + +void GenerateDistanceFieldMap(const unsigned char* const imagePixels, const Size& imageSize, + unsigned char* const distanceMap, const Size& distanceMapSize, + const unsigned int fieldBorder, + const Vector2& maxSize, + bool highQuality) +{ + // constants to reduce redundant calculations + const int originalWidth( static_cast(imageSize.width) ); + const int originalHeight( static_cast(imageSize.height) ); + const int paddedWidth( originalWidth + (fieldBorder * 2 ) ); + const int paddedHeight( originalHeight + (fieldBorder * 2 ) ); + const int scaledWidth( static_cast(distanceMapSize.width) ); + const int scaledHeight( static_cast(distanceMapSize.height) ); + const int maxWidth( static_cast(maxSize.width) + (fieldBorder * 2 )); + const int maxHeight( static_cast(maxSize.height) + (fieldBorder * 2 ) ); + + const int bufferLength( std::max( maxWidth, std::max(paddedWidth, scaledWidth) ) * + std::max( maxHeight, std::max(paddedHeight, scaledHeight) ) ); + + std::vector outsidePixels( bufferLength, 0.0f ); + std::vector insidePixels( bufferLength, 0.0f ); + + float* outside( outsidePixels.data() ); + float* inside( insidePixels.data() ); + + for( int y = 0; y < paddedHeight; ++y ) + { + for ( int x = 0; x < paddedWidth; ++x) + { + if( y < (int)fieldBorder || y >= (paddedHeight - (int)fieldBorder) || + x < (int)fieldBorder || x >= (paddedWidth - (int)fieldBorder) ) + { + outside[ y * paddedWidth + x ] = MAX_DISTANCE; + inside[ y * paddedWidth + x ] = 0.0f; + } + else + { + unsigned int pixel( imagePixels[ (y - fieldBorder) * originalWidth + (x - fieldBorder) ] ); + outside[ y * paddedWidth + x ] = (pixel == 0) ? MAX_DISTANCE : SQUARE((255 - pixel) / 255.0f); + inside[ y * paddedWidth + x ] = (pixel == 255) ? MAX_DISTANCE : SQUARE(pixel / 255.0f); + } + } + } + + // perform distance transform if high quality requested, else use original figure + if( highQuality ) + { + // create temporary buffers for DistanceTransform() + const int tempBufferLength( std::max(paddedWidth, paddedHeight) ); + std::vector tempSourceBuffer( tempBufferLength, 0.0f ); + std::vector tempDestBuffer( tempBufferLength, 0.0f ); + + // Perform distance transform for pixels 'outside' the figure + DistanceTransform( outside, paddedWidth, paddedHeight, tempSourceBuffer.data(), tempDestBuffer.data() ); + + // Perform distance transform for pixels 'inside' the figure + DistanceTransform( inside, paddedWidth, paddedHeight, tempSourceBuffer.data(), tempDestBuffer.data() ); + } + + // distmap = outside - inside; % Bipolar distance field + for( int y = 0; y < paddedHeight; ++y) + { + for( int x = 0; x < paddedWidth; ++x ) + { + const int offset( y * paddedWidth + x ); + float pixel( sqrtf(outside[offset]) - sqrtf(inside[offset]) ); + pixel = 128.0f + pixel * 16.0f; + pixel = Clamp( pixel, 0.0f, 255.0f ); + outside[offset] = (255.0f - pixel) / 255.0f; + } + } + + // scale the figure to the distance field tile size + ScaleField( paddedWidth, paddedHeight, outside, scaledWidth, scaledHeight, inside ); + + // convert from floats to integers + for( int y = 0; y < scaledHeight; ++y ) + { + for( int x = 0; x < scaledWidth; ++x ) + { + float pixel( inside[ y * scaledWidth + x ] ); + distanceMap[y * scaledWidth + x ] = static_cast< unsigned char >(pixel * 255.0f); + } + } +} + +} // namespace Dali diff --git a/dali/devel-api/images/distance-field.h b/dali/devel-api/images/distance-field.h new file mode 100644 index 0000000..d0ebf2a --- /dev/null +++ b/dali/devel-api/images/distance-field.h @@ -0,0 +1,50 @@ +#ifndef __DALI_DISTANCE_FIELD_H__ +#define __DALI_DISTANCE_FIELD_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +struct Vector2; + +/** + * @brief Generate a distance field map from a source image. + * + * @param[in] imagePixels A pointer to a buffer containing the source image + * @param[in] imageSize The size, width and height, of the source image + * @param[out] distanceMap A pointer to a buffer to receive the calculated distance field map. + * Note: This must not overlap with imagePixels for correct distance field map generation. + * @param[in] distanceMapSize The size, width and height, of the distance field map + * @param[in] fieldBorder The amount of distance field cells to add around the data (for glow/shadow effects) + * @param[in] maxSize The image is scaled from this size to distanceMapSize + * @param[in] highQuality Set true to generate high quality distance fields + */ +DALI_IMPORT_API void GenerateDistanceFieldMap( const unsigned char* const imagePixels, const Vector2& imageSize, + unsigned char* const distanceMap, const Vector2& distanceMapSize, + const unsigned int fieldBorder, + const Vector2& maxSize, + bool highQuality = true); + +} //namespace Dali + +#endif // ifndef __DALI_DISTANCE_FIELD_H__ diff --git a/dali/devel-api/object/property-buffer.cpp b/dali/devel-api/object/property-buffer.cpp new file mode 100644 index 0000000..9eb3d39 --- /dev/null +++ b/dali/devel-api/object/property-buffer.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include // Dali::PropertyBuffer + +// INTERNAL INCLUDES +#include // Dali::Property::Map +#include // Dali::Internal::ObjectHelper +#include // Dali::Internal::PropertyBuffer + +namespace Dali +{ + +PropertyBuffer PropertyBuffer::New( Dali::Property::Map& bufferFormat, std::size_t size ) +{ + Internal::PropertyBufferPtr propertyBuffer = Internal::PropertyBuffer::New(); + + propertyBuffer->SetFormat( bufferFormat ); + propertyBuffer->SetSize( size ); + + return PropertyBuffer( propertyBuffer.Get() ); +} + +PropertyBuffer::PropertyBuffer() +{ +} + +PropertyBuffer::~PropertyBuffer() +{ +} + +PropertyBuffer::PropertyBuffer( const PropertyBuffer& handle ) +: Handle( handle ) +{ +} + +PropertyBuffer PropertyBuffer::DownCast( BaseHandle handle ) +{ + return PropertyBuffer( dynamic_cast(handle.GetObjectPtr())); +} + +PropertyBuffer& PropertyBuffer::operator=( const PropertyBuffer& handle ) +{ + BaseHandle::operator=( handle ); + return *this; +} + +void PropertyBuffer::SetSize( std::size_t size ) +{ + GetImplementation(*this).SetSize( size ); +} + +std::size_t PropertyBuffer::GetSize() const +{ + return GetImplementation(*this).GetSize(); +} + +void PropertyBuffer::SetData( void* data ) +{ + GetImplementation(*this).SetData( data ); +} + +PropertyBuffer::PropertyBuffer( Internal::PropertyBuffer* pointer ) +: Handle( pointer ) +{ +} + +} // namespace Dali diff --git a/dali/devel-api/object/property-buffer.h b/dali/devel-api/object/property-buffer.h new file mode 100644 index 0000000..a29c4b5 --- /dev/null +++ b/dali/devel-api/object/property-buffer.h @@ -0,0 +1,183 @@ +#ifndef DALI_PROPERTY_BUFFER_H +#define DALI_PROPERTY_BUFFER_H + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include // std::size_t +#include // std::string + +// INTERNAL INCLUDES +#include // Dali::Handle +#include // Dali::Property::Index +#include // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX +#include // Dali::Property::Map + +namespace Dali +{ + +namespace Internal DALI_INTERNAL +{ +class PropertyBuffer; +} + +/** + * @brief PropertyBuffer is a handle to an object that contains a buffer of structured properties + * + * PropertyBuffers can be used to provide data to Geometry objects. + * + * Example: + * + * const float halfQuadSize = .5f; + * struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; }; + * TexturedQuadVertex texturedQuadVertexData[4] = { + * { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) }, + * { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) }, + * { Vector2(-halfQuadSize, halfQuadSize), Vector2(0.f, 1.f) }, + * { Vector2( halfQuadSize, halfQuadSize), Vector2(1.f, 1.f) } }; + * + * Property::Map texturedQuadVertexFormat; + * texturedQuadVertexFormat["aPosition"] = Property::VECTOR2; + * texturedQuadVertexFormat["aTexCoord"] = Property::VECTOR2; + * PropertyBuffer texturedQuadVertices = PropertyBuffer::New( texturedQuadVertexFormat, 4 ); + * texturedQuadVertices.SetData(texturedQuadVertexData); + * + * // Create indices + * unsigned int indexData[6] = { 0, 3, 1, 0, 2, 3 }; + * Property::Map indexFormat; + * indexFormat["indices"] = Property::INTEGER; + * PropertyBuffer indices = PropertyBuffer::New( indexFormat, 6 ); + * indices.SetData(indexData); + * + * // Create the geometry object + * Geometry texturedQuadGeometry = Geometry::New(); + * texturedQuadGeometry.AddVertexBuffer( texturedQuadVertices ); + * texturedQuadGeometry.SetIndexBuffer( indices ); + * + */ +class DALI_IMPORT_API PropertyBuffer : public Handle +{ +public: + + /** + * @brief An enumeration of properties belonging to the PropertyBuffer class. + */ + struct Property + { + enum + { + SIZE = DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "size", type INTEGER + BUFFER_FORMAT, ///< name "buffer-format", type MAP + }; + }; + + /** + * @brief Create a PropertyBuffer + * + * Static property buffers use less memory. + * + * @param[in] bufferFormat Map of names and types that describes the components of the buffer + * @param[in] size The number of elements in the property buffer + * @return Handle to a newly allocated PropertyBuffer + */ + static PropertyBuffer New( Dali::Property::Map& bufferFormat, std::size_t size ); + + /** + * @brief Default constructor, creates an empty handle + */ + PropertyBuffer(); + + /** + * @brief Destructor + */ + ~PropertyBuffer(); + + /** + * @brief Copy constructor, creates a new handle to the same object + * + * @param[in] handle Handle to an object + */ + PropertyBuffer( const PropertyBuffer& handle ); + + /** + * @brief Downcast to a property buffer handle. + * + * If not a property buffer the returned property buffer handle is left uninitialized. + * @param[in] handle to an object + * @return property buffer handle or an uninitialized handle + */ + static PropertyBuffer DownCast( BaseHandle handle ); + + /** + * @brief Assignment operator, changes this handle to point at the same object + * + * @param[in] handle Handle to an object + * @return Reference to the assigned object + */ + PropertyBuffer& operator=( const PropertyBuffer& handle ); + + /** + * @brief Set the number of elements in the buffer + * + * Calling this function is equivalent to setting the property SIZE + * + * @param[in] size Number of elements to expand or contract the buffer + */ + void SetSize( std::size_t size ); + + /** + * @brief Get the number of elements in the buffer + * + * @return Number of elements to expand or contract the buffer + */ + std::size_t GetSize() const; + + /** + * @brief Update the whole buffer information + * + * This function expects a pointer to an array of structures with the same + * format that was given in the construction, and the number of elements to + * be the same as the size of the buffer. + * + * If the initial structure was: { { "position", VECTOR3}, { "uv", VECTOR2 } } + * and a size of 10 elements, this function should be called with a pointer equivalent to: + *
+   * struct Vertex {
+   *   Dali::Vector3 position;
+   *   Dali::Vector2 uv;
+   * };
+   * Vertex vertices[ 10 ] = { ... };
+   * propertyBuffer.SetData( vertices );
+   * 
+ * + * @param[in] data A pointer to the data that will be copied to the buffer. + */ + void SetData( void* data ); + +public: + /** + * @brief The constructor + * + * @param [in] pointer A pointer to a newly allocated PropertyBuffer + */ + explicit DALI_INTERNAL PropertyBuffer( Internal::PropertyBuffer* pointer ); +}; + +} // namespace Dali + +#endif // DALI_PROPERTY_BUFFER_H diff --git a/dali/devel-api/object/type-registry-helper.h b/dali/devel-api/object/type-registry-helper.h new file mode 100644 index 0000000..7d6b90b --- /dev/null +++ b/dali/devel-api/object/type-registry-helper.h @@ -0,0 +1,90 @@ +#ifndef __DALI_TYPE_REGISTRY_HELPER_H__ +#define __DALI_TYPE_REGISTRY_HELPER_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * @brief These macros are used to use the type-registry to register properties and signals. + * This forces registration to be done in a standard way across actors and controls and facilitates future compile-time checks to be added. + * + * Note: Currently a compile time check is done for the order of the properties. The order is not critical to registration, but helps maintain the ordering between the header and implementations to avoid properties being added out of place. + * + * Note: The signal macro also generates string const chars. + */ +#define DALI_TOKEN_PASTE_EXPAND( x, y ) x ## y +#define DALI_TOKEN_PASTE( x, y ) DALI_TOKEN_PASTE_EXPAND(x, y) + +#define DALI_PROPERTY_REGISTRATION_INTERNAL( count, typeRegistrationObject, objectNamespace, objectType, text, valueType, enumIndex ) \ + PropertyRegistration DALI_TOKEN_PASTE( property, count ) ( typeRegistrationObject, text, objectNamespace::objectType::Property::enumIndex, Property::valueType, &objectType::SetProperty, &objectType::GetProperty ); \ + DALI_COMPILE_TIME_ASSERT( ( objectNamespace::objectType::Property::enumIndex - objectNamespace::objectType::PROPERTY_START_INDEX ) == count ); + +#define DALI_ANIMATABLE_PROPERTY_REGISTRATION_INTERNAL( count, typeRegistrationObject, objectNamespace, objectType, text, valueType, enumIndex) \ + AnimatablePropertyRegistration DALI_TOKEN_PASTE( property, count ) ( typeRegistrationObject, text, objectNamespace::objectType::Property::enumIndex, Property::valueType ); + +#define DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION_INTERNAL( count, typeRegistrationObject, objectNamespace, objectType, text, enumIndex, baseEnumIndex, componentIndex) \ + AnimatablePropertyComponentRegistration DALI_TOKEN_PASTE( property, count ) ( typeRegistrationObject, text, objectNamespace::objectType::Property::enumIndex, objectNamespace::objectType::Property::baseEnumIndex, componentIndex ); + +#define DALI_SIGNAL_REGISTRATION_INTERNAL( count, typeRegistrationObject, objectNamespace, objectType, text, textVariable ) \ + const char* const textVariable = text; \ + SignalConnectorType DALI_TOKEN_PASTE( signalConnector, count ) ( typeRegistrationObject, text, &objectNamespace::Internal::objectType::DoConnectSignal ); + +#define DALI_ACTION_REGISTRATION_INTERNAL( count, typeRegistrationObject, objectNamespace, objectType, text, textVariable ) \ + const char* const textVariable = text; \ + TypeAction DALI_TOKEN_PASTE( signalConnector, count ) ( typeRegistrationObject, text, &objectNamespace::Internal::objectType::DoAction ); + +// For use within implementations: + +#define DALI_TYPE_REGISTRATION_BEGIN( thisType, baseType, createFunction ) \ + TypeRegistration typeRegistration( typeid( thisType ), typeid( baseType ), createFunction ); + +#define DALI_TYPE_REGISTRATION_BEGIN_CREATE( thisType, baseType, createFunction, createAtStartup ) \ + TypeRegistration typeRegistration( typeid( thisType ), typeid( baseType ), createFunction, createAtStartup ); + +#define DALI_PROPERTY_REGISTRATION( objectNamespace, objectType, text, valueType, enumIndex ) \ + DALI_PROPERTY_REGISTRATION_INTERNAL( __COUNTER__, typeRegistration, objectNamespace, objectType, text, valueType, enumIndex ) + +#define DALI_ANIMATABLE_PROPERTY_REGISTRATION( objectNamespace, objectType, text, valueType, enumIndex ) \ + DALI_ANIMATABLE_PROPERTY_REGISTRATION_INTERNAL( __COUNTER__, typeRegistration, objectNamespace, objectType, text, valueType, enumIndex ) + +#define DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( objectNamespace, objectType, text, enumIndex, baseEnumIndex, componentIndex ) \ + DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION_INTERNAL( __COUNTER__, typeRegistration, objectNamespace, objectType, text, enumIndex, baseEnumIndex, componentIndex ) + +#define DALI_SIGNAL_REGISTRATION( objectNamespace, objectType, text, textVariable ) \ + DALI_SIGNAL_REGISTRATION_INTERNAL( __COUNTER__, typeRegistration, objectNamespace, objectType, text, textVariable ) + +#define DALI_ACTION_REGISTRATION( objectNamespace, objectType, text, textVariable ) \ + DALI_ACTION_REGISTRATION_INTERNAL( __COUNTER__, typeRegistration, objectNamespace, objectType, text, textVariable ) + +#define DALI_TYPE_REGISTRATION_END( ) // Empty for now, can be used to perform checks. + + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_TYPE_REGISTRY_HELPER_H__ diff --git a/dali/devel-api/object/weak-handle.cpp b/dali/devel-api/object/weak-handle.cpp new file mode 100644 index 0000000..94bb88f --- /dev/null +++ b/dali/devel-api/object/weak-handle.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +struct WeakHandleBase::Impl : public Internal::Object::Observer +{ + // Construction + Impl() + : mObject( NULL ) + { + } + + // Construction + Impl( Handle& handle ) + : mObject( NULL ) + { + if(handle) + { + mObject = static_cast( handle.GetObjectPtr() ); + if(mObject) + { + mObject->AddObserver( *this ); + } + } + } + + // Destruction + ~Impl() + { + if( mObject ) + { + mObject->RemoveObserver( *this ); + } + } + + /** + * From Object::Observer + */ + virtual void SceneObjectAdded( Internal::Object& object ) + { + } + + /** + * From Object::Observer + */ + virtual void SceneObjectRemoved( Internal::Object& object ) + { + } + + /** + * From Object::Observer + */ + virtual void ObjectDestroyed( Internal::Object& object ) + { + mObject = NULL; + } + + // Data + Internal::Object* mObject; +}; + +WeakHandleBase::WeakHandleBase() +: mImpl( new Impl() ) +{ +} + +WeakHandleBase::WeakHandleBase( Handle& handle ) +: mImpl( new Impl( handle ) ) +{ +} + +WeakHandleBase::~WeakHandleBase() +{ + delete mImpl; + mImpl = NULL; +} + +WeakHandleBase::WeakHandleBase(const WeakHandleBase& handle) +: mImpl( NULL ) +{ + Handle object = handle.GetBaseHandle(); + mImpl = new Impl(object); +} + +WeakHandleBase& WeakHandleBase::operator=( const WeakHandleBase& rhs ) +{ + if( this != &rhs ) + { + delete mImpl; + + Handle handle = rhs.GetBaseHandle(); + mImpl = new Impl(handle); + } + + return *this; +} + +bool WeakHandleBase::operator==( const WeakHandleBase& rhs ) const +{ + return this->mImpl->mObject == rhs.mImpl->mObject; +} + +bool WeakHandleBase::operator!=( const WeakHandleBase& rhs ) const +{ + return !( *this == rhs ); +} + +Handle WeakHandleBase::GetBaseHandle() const +{ + return Handle( mImpl->mObject ); +} + +} // Dali diff --git a/dali/devel-api/object/weak-handle.h b/dali/devel-api/object/weak-handle.h new file mode 100644 index 0000000..2e24758 --- /dev/null +++ b/dali/devel-api/object/weak-handle.h @@ -0,0 +1,220 @@ +#ifndef __DALI_WEAK_HANDLE_H__ +#define __DALI_WEAK_HANDLE_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +/** + * @brief Base class to store a weak pointer to an internal Dali object. The handle to the object + * can be accessed if the object exists, and such access is not reference counted. When the object + * is deleted, the weak pointer will be set to NULL, and any further attmpt to access to a deleted + * object will return an empty handle. + * + */ +class DALI_IMPORT_API WeakHandleBase +{ + +public: + + /** + * @brief Default constructor which provides an uninitialized Dali::WeakHandleBase. + */ + WeakHandleBase(); + + /** + * @brief This constructor creates a weak handle of the Dali object. + * + * @param [in] handle A reference to the handle of the Dali object. + */ + WeakHandleBase( Handle& handle ); + + /** + * @brief Destructor to free resources. + */ + ~WeakHandleBase(); + + /** + * @brief Copy constructor. + * + * @param [in] handle A reference to the copied WeakHandleBase + */ + WeakHandleBase(const WeakHandleBase& handle); + + /** + * @brief Assignment operator. + * + * It makes this WeakHandleBase point to the same internal Dali object as the copied WeakHandleBase + * @param [in] rhs A reference to the copied WeakHandleBase + * @return A reference to this WeakHandleBase + */ + WeakHandleBase& operator=( const WeakHandleBase& rhs ); + + /** + * @brief Equality operator overload. + * + * @param [in] rhs A reference to the compared WeakHandleBase. + * @return true if the handle points to the same Dali resource, or if both are uninitialized. + */ + bool operator==(const WeakHandleBase& rhs) const; + + /** + * @brief Inequality operator overload. + * + * @param [in] rhs A reference to the compared WeakHandleBase. + * @return true if the handle points to the different Dali resources. + */ + bool operator!=(const WeakHandleBase& rhs) const; + + /** + * @brief Gets the handle to the Dali object. + * + * @return The handle of the Dali object pointed by this WeakHandleBase or an empty handle if the Dali object doesn't exist. + */ + Handle GetBaseHandle() const; + +protected: + + struct Impl; + Impl* mImpl; +}; + +/** + * @brief Type CustomActors support + */ +template +struct CustomActors +{ + /** + * This flag tells Dali if a class is derived from CustomActor. + */ + enum { IS_CUSTOM_ACTOR = __is_base_of(Dali::CustomActor, Type) }; +}; + +template +struct TypeCustomActors : public CustomActors< Type > +{ +}; + +template < bool CustomActorType > +class InternalTypeName +{ +public: // Typedefs + + typedef Dali::Internal::CustomActor InternalObjectType; +}; + +template <> +class InternalTypeName< false > +{ +public: // Typedefs + + typedef Dali::Internal::Actor InternalObjectType; +}; + +/** + * @brief Weak handle for the given type of Dali object. + */ +template < class T > +class WeakHandle : public WeakHandleBase +{ +public: // Typedefs + + typedef typename InternalTypeName< TypeCustomActors::IS_CUSTOM_ACTOR >::InternalObjectType InternalObjectType; + +public: + + /** + * @copydoc Dali::WeakHandleBase::WeakHandleBase() + */ + WeakHandle() + : WeakHandleBase() + { + } + + /** + * @copydoc Dali::WeakHandleBase::WeakHandleBase(Handle&) + */ + WeakHandle( T& handle ) + : WeakHandleBase( handle ) + { + } + + /** + * @copydoc Dali::WeakHandleBase::~WeakHandleBase() + */ + ~WeakHandle() {} + + /** + * @copydoc Dali::WeakHandleBase::WeakHandleBase(const WeakHandleBase&) + */ + WeakHandle(const WeakHandle& handle) + : WeakHandleBase( handle ) + { + } + + /** + * @copydoc Dali::WeakHandleBase::operator=() + */ + WeakHandle& operator=( const WeakHandle& rhs ) + { + WeakHandleBase::operator=(rhs); + return *this; + } + + /** + * @copydoc Dali::WeakHandleBase::operator==() + */ + bool operator==(const WeakHandle& rhs) const + { + return WeakHandleBase::operator==(rhs); + } + + /** + * @copydoc Dali::WeakHandleBase::operator!=() + */ + bool operator!=(const WeakHandle& rhs) const + { + return WeakHandleBase::operator!=(rhs); + } + + /** + * @copydoc Dali::WeakHandleBase::GetHandle() + */ + T GetHandle() + { + Handle handle( GetBaseHandle() ); + if( handle ) + { + return T( reinterpret_cast< InternalObjectType* >( handle.GetObjectPtr() ) ); + } + else + { + return T(); + } + } +}; + +} // namespace Dali + +#endif // __DALI_WEAK_HANDLE_H__ diff --git a/dali/devel-api/rendering/cull-face.cpp b/dali/devel-api/rendering/cull-face.cpp new file mode 100644 index 0000000..4f1cc99 --- /dev/null +++ b/dali/devel-api/rendering/cull-face.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +void SetCullFace( ImageActor actor, CullFaceMode mode ) +{ + GetImplementation( actor ).SetCullFace( mode ); +} + +CullFaceMode GetCullFace( ImageActor actor ) +{ + return GetImplementation( actor ).GetCullFace(); +} + +} //namespace Dali diff --git a/dali/devel-api/rendering/cull-face.h b/dali/devel-api/rendering/cull-face.h new file mode 100644 index 0000000..84aa9e3 --- /dev/null +++ b/dali/devel-api/rendering/cull-face.h @@ -0,0 +1,58 @@ +#ifndef DALI_CULL_FACE_H +#define DALI_CULL_FACE_H + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +/** + * @brief Face culling modes. + */ +enum CullFaceMode +{ + CullNone, ///< Face culling disabled + CullFront, ///< Cull front facing polygons + CullBack, ///< Cull back facing polygons + CullFrontAndBack ///< Cull front and back facing polygons +}; + +class ImageActor; + +/** + * @brief Set the face-culling mode for an image-actor. + * + * @param[in] actor The image-actor to set the cull-face on. + * @param[in] mode The culling mode. + */ +DALI_IMPORT_API void SetCullFace( ImageActor actor, CullFaceMode mode); + +/** + * @brief Retrieve the face-culling mode for an image-actor. + * + * @param[in] actor The image-actor whose cull-face is required. + * @return mode The culling mode. + */ +DALI_IMPORT_API CullFaceMode GetCullFace( ImageActor actor ); + +} //namespace Dali + +#endif // DALI_CULL_FACE_H diff --git a/dali/devel-api/rendering/geometry.cpp b/dali/devel-api/rendering/geometry.cpp new file mode 100644 index 0000000..4b12f05 --- /dev/null +++ b/dali/devel-api/rendering/geometry.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use *this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include // Dali::Geometry + +// INTERNAL INCLUDES +#include // Dali::Internal::Geometry + +namespace Dali +{ + +Geometry Geometry::New() +{ + Internal::GeometryPtr geometry = Internal::Geometry::New(); + return Geometry( geometry.Get() ); +} + +Geometry::Geometry() +{ +} + +Geometry::~Geometry() +{ +} + +Geometry::Geometry( const Geometry& handle ) +: Handle( handle ) +{ +} + +Geometry Geometry::DownCast( BaseHandle handle ) +{ + return Geometry( dynamic_cast(handle.GetObjectPtr())); +} + +Geometry& Geometry::operator=( const Geometry& handle ) +{ + BaseHandle::operator=( handle ); + return *this; +} + +std::size_t Geometry::AddVertexBuffer( PropertyBuffer& vertexBuffer ) +{ + DALI_ASSERT_ALWAYS( vertexBuffer && "VertexBuffer is not initialized "); + return GetImplementation(*this).AddVertexBuffer( GetImplementation( vertexBuffer ) ); +} + +std::size_t Geometry::GetNumberOfVertexBuffers() const +{ + return GetImplementation(*this).GetNumberOfVertexBuffers(); +} + +void Geometry::RemoveVertexBuffer( std::size_t index ) +{ + GetImplementation(*this).RemoveVertexBuffer( index ); +} + +void Geometry::SetIndexBuffer( PropertyBuffer& indexBuffer ) +{ + DALI_ASSERT_ALWAYS( indexBuffer && "indexBuffer is not initialized "); + GetImplementation(*this).SetIndexBuffer( GetImplementation( indexBuffer ) ); +} + +void Geometry::SetGeometryType( GeometryType geometryType ) +{ + GetImplementation(*this).SetGeometryType( geometryType ); +} + +Geometry::GeometryType Geometry::GetGeometryType() const +{ + return GetImplementation(*this).GetGeometryType(); +} + +void Geometry::SetRequiresDepthTesting( bool requiresDepthTest ) +{ + GetImplementation(*this).SetRequiresDepthTesting( requiresDepthTest ); +} + +bool Geometry::GetRequiresDepthTesting() const +{ + return GetImplementation(*this).GetRequiresDepthTesting(); +} + +Geometry::Geometry( Internal::Geometry* pointer ) +: Handle( pointer ) +{ +} + +} //namespace Dali diff --git a/dali/devel-api/rendering/geometry.h b/dali/devel-api/rendering/geometry.h new file mode 100644 index 0000000..cb8986e --- /dev/null +++ b/dali/devel-api/rendering/geometry.h @@ -0,0 +1,192 @@ +#ifndef DALI_GEOMETRY_H +#define DALI_GEOMETRY_H + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include // std::size_t + +// INTERNAL INCLUDES +#include // Dali::Handle +#include // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX +#include // Dali::PropertyBuffer + +namespace Dali +{ + +namespace Internal DALI_INTERNAL +{ +class Geometry; +} + +/** + * @brief Geometry is handle to an object that can be used to define a geometric elements. + */ +class DALI_IMPORT_API Geometry : public Handle +{ +public: + + enum GeometryType + { + POINTS, + LINES, + LINE_LOOP, + LINE_STRIP, + TRIANGLES, + TRIANGLE_FAN, + TRIANGLE_STRIP + }; + + /** + * @brief An enumeration of properties belonging to the Geometry class. + */ + struct Property + { + enum + { + GEOMETRY_TYPE = DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "depth-index", type STRING + GEOMETRY_CENTER, ///< name "geometry-center", type VECTOR3 + GEOMETRY_HALF_EXTENTS, ///< name "geometry-half-extents", type VECTOR3 + REQUIRES_DEPTH_TEST, ///< name "requires-depth-testing", type BOOLEAN + }; + }; + + /** + * @brief Creates a new Geometry object + * + * @return An handle to a newly allocated Geometry + */ + static Geometry New(); + + /** + * @brief Default constructor, creates an empty handle + */ + Geometry(); + + /** + * @brief Destructor + */ + ~Geometry(); + + /** + * @brief Copy constructor, creates a new handle to the same object + * + * @param[in] handle Handle to an object + */ + Geometry( const Geometry& handle ); + + /** + * @brief Downcast to a geometry. + * + * If not the returned handle is left uninitialized. + * @param[in] handle to an object + * @return geometry handle or an uninitialized handle + */ + static Geometry DownCast( BaseHandle handle ); + + /** + * @brief Assignment operator, changes this handle to point at the same object + * + * @param[in] handle Handle to an object + * @return Reference to the assigned object + */ + Geometry& operator=( const Geometry& handle ); + + /** + * @brief Add a PropertyBuffer to be used as source of geometry vertices + * + * @param[in] vertexBuffer PropertyBuffer to be used as source of geometry vertices + * @return Index of the newly added buffer, can be used with RemoveVertexBuffer to remove + * this buffer if no longer required + */ + std::size_t AddVertexBuffer( PropertyBuffer& vertexBuffer ); + + /** + * @brief Retrieve the number of vertex buffers that have been added to this geometry + * + * @return Number of vertex buffers that have been added to this geometry + */ + std::size_t GetNumberOfVertexBuffers() const; + + /** + * @brief Remove a vertex buffer + * + * The index must be between 0 and GetNumberOfVertexBuffers() + * + * @param[in] index Index to the vertex buffer to remove + */ + void RemoveVertexBuffer( std::size_t index ); + + /** + * @brief Set a PropertyBuffer to be used as a source of indices for the geometry + * + * This buffer is required to have exactly one component and it must be of the type Property::INTEGER + * + * By setting this buffer the will case the geometry to be rendered using indices. + * To unset call SetIndexBuffer with an empty handle. + * + * @param[in] indexBuffer PropertyBuffer to be used as a source of indices for the geometry + */ + void SetIndexBuffer( PropertyBuffer& indexBuffer ); + + /** + * @brief Set the type of primitives this geometry contains + * + * @param[in] geometryType Type of primitives this geometry contains + */ + void SetGeometryType( GeometryType geometryType ); + + /** + * @brief Get the type of primitives this geometry contains + * + * Calling this function sets the property GEOMETRY_TYPE + * + * @return Type of primitives this geometry contains + */ + GeometryType GetGeometryType() const; + + /** + * @brief Set if the geometry requires depth testing + * + * Should be set to true if this geometry has overlapping triangles in arbitrary order + * + * Calling this function is equivalent to setting the REQUIRES_DEPTH_TESTING property + * + * @param[in] requiresDepthTest Specifies if the geometry requires depth testing + */ + void SetRequiresDepthTesting( bool requiresDepthTest ); + + /** + * @brief Return if the geometry requires depth testing + * + * @return True if the geometry requires depth testing + */ + bool GetRequiresDepthTesting() const; + +public: + /** + * @brief The constructor + * + * @param [in] pointer A pointer to a newly allocated Geometry + */ + explicit DALI_INTERNAL Geometry( Internal::Geometry* pointer ); +}; + +} //namespace Dali + +#endif // DALI_GEOMETRY_H diff --git a/dali/devel-api/rendering/material.cpp b/dali/devel-api/rendering/material.cpp new file mode 100644 index 0000000..af2fd92 --- /dev/null +++ b/dali/devel-api/rendering/material.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include // Dali::Material + +// INTERNAL INCLUDES +#include // Dali::Internal::Material +#include // Dali::Internal::Sampler +#include // Dali::Internal::Shader + +namespace Dali +{ + +Material Material::New( Shader shader ) +{ + // TODO: MESH_REWORK + Internal::MaterialPtr material = Internal::Material::New(); + material->SetShader( GetImplementation(shader) ); + + return Material( material.Get() ); +} + +Material::Material() +{ +} + +Material::~Material() +{ +} + +Material::Material( const Material& handle ) +: Handle( handle ) +{ +} + +Material Material::DownCast( BaseHandle handle ) +{ + return Material( dynamic_cast(handle.GetObjectPtr())); +} + +Material& Material::operator=( const Material& handle ) +{ + BaseHandle::operator=( handle ); + return *this; +} + +void Material::SetShader( Shader& shader ) +{ + DALI_ASSERT_ALWAYS( shader && "Shader handle is uninitialized" ); + GetImplementation(*this).SetShader( GetImplementation( shader ) ); +} + +Shader Material::GetShader() const +{ + Internal::Shader* shaderPtr( GetImplementation(*this).GetShader() ); + return Dali::Shader( shaderPtr ); +} + +void Material::AddSampler( Sampler& sampler ) +{ + DALI_ASSERT_ALWAYS( sampler && "Sampler handle is uninitialized" ); + GetImplementation(*this).AddSampler( GetImplementation( sampler ) ); +} + +std::size_t Material::GetNumberOfSamplers() const +{ + return GetImplementation(*this).GetNumberOfSamplers(); +} + +void Material::RemoveSampler( std::size_t index ) +{ + GetImplementation(*this).RemoveSampler( index ); +} + +Sampler Material::GetSamplerAt( unsigned int index ) const +{ + Internal::Sampler* samplerPtr( GetImplementation(*this).GetSamplerAt(index) ); + return Dali::Sampler( samplerPtr ); +} + +void Material::SetFaceCullingMode( FaceCullingMode cullingMode ) +{ + GetImplementation(*this).SetFaceCullingMode( cullingMode ); +} + +void Material::SetBlendMode( BlendingMode::Type mode ) +{ + GetImplementation(*this).SetBlendMode( mode ); +} + +BlendingMode::Type Material::GetBlendMode() const +{ + return GetImplementation(*this).GetBlendMode(); +} + +void Material::SetBlendFunc( BlendingFactor::Type srcFactorRgba, + BlendingFactor::Type destFactorRgba ) +{ + GetImplementation(*this).SetBlendFunc( srcFactorRgba, destFactorRgba ); +} + +void Material::SetBlendFunc( BlendingFactor::Type srcFactorRgb, + BlendingFactor::Type destFactorRgb, + BlendingFactor::Type srcFactorAlpha, + BlendingFactor::Type destFactorAlpha ) +{ + GetImplementation(*this).SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha ); +} + +void Material::GetBlendFunc( BlendingFactor::Type& srcFactorRgb, + BlendingFactor::Type& destFactorRgb, + BlendingFactor::Type& srcFactorAlpha, + BlendingFactor::Type& destFactorAlpha ) const +{ + GetImplementation(*this).GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha ); +} + +void Material::SetBlendEquation( BlendingEquation::Type equationRgba ) +{ + GetImplementation(*this).SetBlendEquation( equationRgba ); +} + +void Material::SetBlendEquation( BlendingEquation::Type equationRgb, + BlendingEquation::Type equationAlpha ) +{ + GetImplementation(*this).SetBlendEquation( equationRgb, equationAlpha ); +} + +void Material::GetBlendEquation( BlendingEquation::Type& equationRgb, + BlendingEquation::Type& equationAlpha ) const +{ + GetImplementation(*this).GetBlendEquation( equationRgb, equationAlpha ); +} + +void Material::SetBlendColor( const Vector4& color ) +{ + GetImplementation(*this).SetBlendColor( color ); +} + +const Vector4& Material::GetBlendColor() const +{ + return GetImplementation(*this).GetBlendColor(); +} + +Material::Material( Internal::Material* pointer ) +: Handle( pointer ) +{ +} + +} //namespace Dali diff --git a/dali/devel-api/rendering/material.h b/dali/devel-api/rendering/material.h new file mode 100644 index 0000000..5751fff --- /dev/null +++ b/dali/devel-api/rendering/material.h @@ -0,0 +1,307 @@ +#ifndef DALI_MATERIAL_H +#define DALI_MATERIAL_H + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include // std::size_t +#include // std::string + +// INTERNAL INCLUDES +#include // Dali::BlendingMode, Dali::BlendingEquation, Dali::BlendingFactor +#include // Dali::Image +#include // Dali::Handle +#include // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX +#include // Dali::Sampler +#include // Dali::Shader + +namespace Dali +{ + +namespace Internal DALI_INTERNAL +{ +class Material; +} + +/** + * @brief Material is a handle to an object that specifies the visual properties of the renderer. + */ +class DALI_IMPORT_API Material : public Handle +{ +public: + + /** + * @brief Set face culling mode. + */ + enum FaceCullingMode + { + NONE, ///< None of the faces should be culled + CULL_BACK, ///< Cull back face, back face should never be shown + CULL_BACK_HINT, ///< Cull back face hinting, will still display correctly if no culling is done + CULL_FRONT, ///< Cull front face, back face should never be shown + CULL_FRONT_HINT, ///< Cull front face hinting, will still display correctly if no culling is done + CULL_BACK_AND_FRONT, ///< Cull back and front faces, if the geometry is composed of triangles none of the faces will be shown + CULL_BACK_AND_FRONT_HINT, ///< Cull back and front hint, will still display correctly if no culling is done + }; + + /** + * @brief An enumeration of properties belonging to the Material class. + */ + struct Property + { + enum + { + COLOR = DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "color", type VECTOR4 + FACE_CULLING_MODE, ///< name "face-culling-mode", type STRING + BLENDING_MODE, ///< name "blending-mode", type STRING + BLEND_EQUATION_RGB, ///< name "blend-equation-rgb", type STRING + BLEND_EQUATION_ALPHA, ///< name "blend-equation-alpha", type STRING + BLENDING_SRC_FACTOR_RGB, ///< name "source-blend-factor-rgb", type STRING + BLENDING_DEST_FACTOR_RGB, ///< name "destination-blend-factor-rgb", type STRING + BLENDING_SRC_FACTOR_ALPHA, ///< name "source-blend-factor-alpha", type STRING + BLENDING_DEST_FACTOR_ALPHA, ///< name "destination-blend-factor-alpha", type STRING + BLEND_COLOR, ///< name "blend-color", type VECTOR4 + }; + }; + + /// @name Uniform Mapping + /** @{ */ + ///< property "COLOR", uniform "uMaterialColor" + /** @} */ + + /** + * @brief Creates a new Material object + * + * @return A handle to a newly allocated Material + */ + static Material New( Shader shader ); + + /** + * @brief Default constructor, creates an empty handle + */ + Material(); + + /** + * @brief Destructor + */ + ~Material(); + + /** + * @brief Copy constructor, creates a new handle to the same object + * + * @param[in] handle Handle to an object + */ + Material( const Material& handle ); + + /** + * @brief Downcast to a material handle. + * + * If handle is not a material, the returned handle is left uninitialized. + * @param[in] handle to an object + * @return material handle or an uninitialized handle + */ + static Material DownCast( BaseHandle handle ); + + /** + * @brief Assignment operator, changes this handle to point at the same object + * + * @param[in] handle Handle to an object + */ + Material& operator=( const Material& handle ); + + /** + * @brief Sets the Shader used by this material + * + * @param[in] shader Handle to a shader + */ + void SetShader( Shader& shader ); + + /** + * @brief Gets the shader used by this material + * + * @return The shader used by the material + */ + Shader GetShader() const; + + /** + * @brief Add a sampler to this material + * + * param[in] sampler The sampler to add to this material + */ + void AddSampler( Sampler& sampler ); + + /** + * @brief Get the number of samplers + * + * @return The number of samplers + */ + std::size_t GetNumberOfSamplers() const; + + /** + * @brief Remove a sampler + * + * The index must be between 0 and GetNumberOfSamplers()-1 + * + * @param[in] index The index of the sampler to remove + */ + void RemoveSampler( std::size_t index ); + + /** + * @brief Get the sampler at the given index for this material + * + * The index must be between 0 and GetNumberOfSamplers()-1 + * + * @param[in] index The index of the sampler + * @return The sampler at that index + */ + Sampler GetSamplerAt( unsigned int index ) const; + + /** + * @brief Set the culling mode for this material + * + * Calling this function sets the properties CULLING_MODE + * + * @param[in] cullingMode The culling mode for this material + */ + void SetFaceCullingMode( FaceCullingMode cullingMode ); + + /** + * @brief Sets the blending mode. + * + * Possible values are: BlendingMode::OFF, BlendingMode::AUTO and BlendingMode::ON. Default is BlendingMode::AUTO. + * + * If blending is disabled (BlendingMode::OFF) fade in and fade out animations do not work. + * + *
    + *
  • \e OFF Blending is disabled. + *
  • \e AUTO Blending is enabled only if the renderable actor has alpha channel. + *
  • \e ON Blending is enabled. + *
+ * + * @param[in] mode The blending mode. + */ + void SetBlendMode( BlendingMode::Type mode ); + + /** + * @brief Retrieves the blending mode. + * + * @return The blending mode, one of BlendingMode::OFF, BlendingMode::AUTO or BlendingMode::ON. + */ + BlendingMode::Type GetBlendMode() const; + + /** + * @brief Specify the pixel arithmetic used when the actor is blended. + * + * @param[in] srcFactorRgba Specifies how the red, green, blue, and alpha source blending factors are computed. + * The options are BlendingFactor::ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR, + * SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR, + * GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, and GL_SRC_ALPHA_SATURATE. + * + * @param[in] destFactorRgba Specifies how the red, green, blue, and alpha destination blending factors are computed. + * The options are BlendingFactor::ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR, + * SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR, + * GL_CONSTANT_ALPHA, and GL_ONE_MINUS_CONSTANT_ALPHA. + */ + void SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba ); + + /** + * @brief Specify the pixel arithmetic used when the actor is blended. + * + * @param[in] srcFactorRgb Specifies how the red, green, and blue source blending factors are computed. + * The options are BlendingFactor::ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR, + * SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR, + * GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, and GL_SRC_ALPHA_SATURATE. + * + * @param[in] destFactorRgb Specifies how the red, green, blue, and alpha destination blending factors are computed. + * The options are BlendingFactor::ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR, + * SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR, + * GL_CONSTANT_ALPHA, and GL_ONE_MINUS_CONSTANT_ALPHA. + * + * @param[in] srcFactorAlpha Specifies how the alpha source blending factor is computed. + * The options are the same as for srcFactorRgb. + * + * @param[in] destFactorAlpha Specifies how the alpha source blending factor is computed. + * The options are the same as for destFactorRgb. + */ + void SetBlendFunc( BlendingFactor::Type srcFactorRgb, BlendingFactor::Type destFactorRgb, + BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha ); + + /** + * @brief Query the pixel arithmetic used when the actor is blended. + * + * @param[out] srcFactorRgb Specifies how the red, green, blue, and alpha source blending factors are computed. + * @param[out] destFactorRgb Specifies how the red, green, blue, and alpha destination blending factors are computed. + * @param[out] srcFactorAlpha Specifies how the red, green, blue, and alpha source blending factors are computed. + * @param[out] destFactorAlpha Specifies how the red, green, blue, and alpha destination blending factors are computed. + */ + void GetBlendFunc( BlendingFactor::Type& srcFactorRgb, BlendingFactor::Type& destFactorRgb, + BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const; + + /** + * @brief Specify the equation used when the actor is blended. + * + * The options are BlendingEquation::ADD, SUBTRACT, or REVERSE_SUBTRACT. + * @param[in] equationRgba The equation used for combining red, green, blue, and alpha components. + */ + void SetBlendEquation( BlendingEquation::Type equationRgba ); + + /** + * @brief Specify the equation used when the actor is blended. + * + * @param[in] equationRgb The equation used for combining red, green, and blue components. + * @param[in] equationAlpha The equation used for combining the alpha component. + * The options are BlendingEquation::ADD, SUBTRACT, or REVERSE_SUBTRACT. + */ + void SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha ); + + /** + * @brief Query the equation used when the actor is blended. + * + * @param[out] equationRgb The equation used for combining red, green, and blue components. + * @param[out] equationAlpha The equation used for combining the alpha component. + */ + void GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const; + + /** + * @brief Specify the color used when the actor is blended; the default is Vector4::ZERO. + * + * @param[in] color The blend color. + */ + void SetBlendColor( const Vector4& color ); + + /** + * @brief Query the color used when the actor is blended. + * + * @return The blend color. + */ + const Vector4& GetBlendColor() const; + +public: + /** + * @brief The constructor + * + * @param [in] pointer A pointer to a newly allocated Material + */ + explicit DALI_INTERNAL Material( Internal::Material* pointer ); +}; + +} //namespace Dali + + + +#endif // DALI_MATERIAL_H diff --git a/dali/devel-api/rendering/renderer.cpp b/dali/devel-api/rendering/renderer.cpp new file mode 100644 index 0000000..a3080e9 --- /dev/null +++ b/dali/devel-api/rendering/renderer.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include // Dali::Renderer + +// INTERNAL INCLUDES +#include // Dali::Internal::Renderer + +namespace Dali +{ + +Renderer Renderer::New( Geometry& geometry, Material& material ) +{ + Internal::RendererPtr renderer = Internal::Renderer::New( ); + renderer->SetGeometry( GetImplementation(geometry) ); + renderer->SetMaterial( GetImplementation(material) ); + return Renderer( renderer.Get() ); +} + +Renderer::Renderer() +{ +} + +Renderer::~Renderer() +{ +} + +Renderer::Renderer( const Renderer& handle ) +: Handle( handle ) +{ +} + +Renderer Renderer::DownCast( BaseHandle handle ) +{ + return Renderer( dynamic_cast(handle.GetObjectPtr())); +} + +Renderer& Renderer::operator=( const Renderer& handle ) +{ + BaseHandle::operator=( handle ); + return *this; +} + +void Renderer::SetGeometry( Geometry& geometry ) +{ + DALI_ASSERT_ALWAYS( geometry && "Geometry handle not initialized" ); + GetImplementation(*this).SetGeometry( GetImplementation(geometry) ); +} + +Geometry Renderer::GetGeometry() const +{ + Internal::Geometry* geometryPtr( GetImplementation(*this).GetGeometry() ); + return Dali::Geometry( geometryPtr ); +} + +void Renderer::SetMaterial( Material& material ) +{ + DALI_ASSERT_ALWAYS( material && "Material handle not initialized" ); + GetImplementation(*this).SetMaterial( GetImplementation(material) ); +} + +Material Renderer::GetMaterial() const +{ + Internal::Material* materialPtr( GetImplementation(*this).GetMaterial() ); + return Dali::Material( materialPtr ); +} + +void Renderer::SetDepthIndex( int depthIndex ) +{ + GetImplementation(*this).SetDepthIndex( depthIndex ); +} + +int Renderer::GetDepthIndex() +{ + return GetImplementation(*this).GetDepthIndex(); +} + +Renderer::Renderer( Internal::Renderer* pointer ) +: Handle( pointer ) +{ +} + +} //namespace Dali diff --git a/dali/devel-api/rendering/renderer.h b/dali/devel-api/rendering/renderer.h new file mode 100644 index 0000000..42d541d --- /dev/null +++ b/dali/devel-api/rendering/renderer.h @@ -0,0 +1,157 @@ +#ifndef DALI_RENDERER_H +#define DALI_RENDERER_H + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include // std::string + +// INTERNAL INCLUDES +#include // Dali::Handle +#include // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX +#include // Dali::Geometry +#include // Dali::Material + +namespace Dali +{ + +namespace Internal DALI_INTERNAL +{ +class Renderer; +} + +/** + * @brief Renderer is a handle to an object that can be used to provide an image to a material. + */ +class DALI_IMPORT_API Renderer : public Handle +{ +public: + + /** + * @brief An enumeration of properties belonging to the Renderer class. + */ + struct Property + { + enum + { + DEPTH_INDEX = DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "depth-index", type INTEGER + }; + }; + + /** + * @brief Creates a new Renderer object + * + * @param[in] geometry Geometry to be used by this renderer + * @param[in] material Material to be used by this renderer + */ + static Renderer New( Geometry& geometry, Material& material ); + + /** + * @brief Default constructor, creates an empty handle + */ + Renderer(); + + /** + * @brief Destructor + */ + ~Renderer(); + + /** + * @brief Copy constructor, creates a new handle to the same object + * + * @param[in] handle Handle to an object + */ + Renderer( const Renderer& handle ); + + /** + * @brief Downcast to a renderer handle. + * + * If not a renderer the returned renderer handle is left uninitialized. + * @param[in] handle to an object + * @return renderer handle or an uninitialized handle + */ + static Renderer DownCast( BaseHandle handle ); + + /** + * @brief Assignment operator, changes this handle to point at the same object + * + * @param[in] handle Handle to an object + * @return Reference to the assigned object + */ + Renderer& operator=( const Renderer& handle ); + + /** + * @brief Sets the geometry to be used by this renderer + * + * @param[in] geometry The geometry to be used by this renderer + */ + void SetGeometry( Geometry& geometry ); + + /** + * @brief Gets the geometry used by this renderer + * + * @return The geometry used by the renderer + */ + Geometry GetGeometry() const; + + /** + * @brief Sets the material to be used by this renderer + * + * @param[in] material The material to be used by this renderer + */ + void SetMaterial( Material& material ); + + /** + * @brief Gets the material used by this renderer + * + * @return The material used by the renderer + */ + Material GetMaterial() const; + + /** + * @brief Set the depth index of this renderer + * + * Renderer with higher depth indices are rendered in front of other renderers with smaller values + * + * @param[in] depthIndex The depth index of this renderer + */ + void SetDepthIndex( int depthIndex ); + + //@todo No interface to remove geometry / material? I guess you have to throw away + // this renderer if you don't want it to work any more... + + /** + * @brief Get the depth index of this renderer + * + * @sa SetDepthIndex() + * @return the depth index + */ + int GetDepthIndex(); + +public: + /** + * @brief The constructor + * + * @param [in] pointer A pointer to a newly allocated Renderer + */ + explicit DALI_INTERNAL Renderer( Internal::Renderer* pointer ); +}; + +} //namespace Dali + +#endif // DALI_RENDERER_H diff --git a/dali/devel-api/rendering/sampler.cpp b/dali/devel-api/rendering/sampler.cpp new file mode 100644 index 0000000..d56ed24 --- /dev/null +++ b/dali/devel-api/rendering/sampler.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include // Dali::Sampler + +// INTERNAL INCLUDES +#include // Dali::Internal::Sampler + +namespace Dali +{ + +Sampler Sampler::New( Image& image, const std::string& textureUnitUniformName ) +{ + Internal::SamplerPtr sampler = Internal::Sampler::New(textureUnitUniformName); + Internal::ImagePtr imagePtr = &GetImplementation( image ); + sampler->SetImage( imagePtr ); + return Sampler( sampler.Get() ); +} + +Sampler::Sampler() +{ +} + +Sampler::~Sampler() +{ +} + +Sampler::Sampler( const Sampler& handle ) +: Handle( handle ) +{ +} + +Sampler Sampler::DownCast( BaseHandle handle ) +{ + return Sampler( dynamic_cast(handle.GetObjectPtr())); +} + +Sampler& Sampler::operator=( const Sampler& handle ) +{ + BaseHandle::operator=( handle ); + return *this; +} + +void Sampler::SetUniformName( const std::string& name ) +{ + GetImplementation(*this).SetTextureUnitUniformName( name ); +} + +void Sampler::SetImage( Image& image ) +{ + Internal::ImagePtr imagePtr = &GetImplementation( image ); + GetImplementation(*this).SetImage( imagePtr ); +} + +Image Sampler::GetImage() const +{ + Internal::ImagePtr imagePtr( GetImplementation(*this).GetImage() ); + return Dali::Image( imagePtr.Get() ); +} + +void Sampler::SetFilterMode( FilterMode minFilter, FilterMode magFilter ) +{ + GetImplementation(*this).SetFilterMode( minFilter, magFilter ); +} + +void Sampler::SetWrapMode( WrapMode uWrap, WrapMode vWrap ) +{ + GetImplementation(*this).SetWrapMode( uWrap, vWrap ); +} + +void Sampler::SetAffectsTransparency( bool affectsTransparency ) +{ + GetImplementation(*this).SetAffectsTransparency( affectsTransparency ); +} + +Sampler::Sampler(Internal::Sampler* pointer) +: Handle( pointer ) +{ +} + +} //namespace Dali diff --git a/dali/devel-api/rendering/sampler.h b/dali/devel-api/rendering/sampler.h new file mode 100644 index 0000000..b5d53d7 --- /dev/null +++ b/dali/devel-api/rendering/sampler.h @@ -0,0 +1,187 @@ +#ifndef DALI_SAMPLER_H +#define DALI_SAMPLER_H + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include // std::size_t +#include // std::string + +// INTERNAL INCLUDES +#include // Dali::Handle +#include // Dali::Image +#include // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX + +namespace Dali +{ + +namespace Internal DALI_INTERNAL +{ +class Sampler; +} + +/** + * @brief Sampler is a handle to an object that can be used to provide an image to a material. + */ +class DALI_IMPORT_API Sampler : public Handle +{ +public: + + /** + * @brief Texture filter mode. + */ + enum FilterMode + { + NONE, ///< Use GL system defaults (minification NEAREST_MIPMAP_LINEAR, magnification LINEAR) + DEFAULT, ///< Use dali defaults (minification LINEAR, magnification LINEAR) + NEAREST, ///< Filter nearest + LINEAR ///< Filter linear + }; + + /** + * @brief Texture wrap mode. + */ + enum WrapMode + { + CLAMP_TO_EDGE, ///< The texture coordinates get clamped to the range [0, 1] + REPEAT, ///< Only the fractional part of the texture coordinates is used + MIRRORED_REPEAT, ///< If the integer part of the texture coordinate is odd then it uses + ///< the fractional part, if it's even it uses 1 - the fractional part + }; + + /** + * @brief An enumeration of properties belonging to the Sampler class. + */ + struct Property + { + enum + { + MINIFICATION_FILTER = DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "minification-filter", type STRING + MAGNIGICATION_FILTER, ///< name "magnification-filter", type STRING + U_WRAP, ///< name "u-wrap", type STRING + V_WRAP, ///< name "v-wrap", type STRING + AFFECTS_TRANSPARENCY, ///< name "affects-transparency", type BOOLEAN + }; + }; + + /** + * @brief Creates a new Sampler object + * + * @param[in] image Image used by this sampler + * @param[in] uniformName String with the name of the uniform + */ + static Sampler New( Image& image, const std::string& uniformName ); + + /** + * @brief Default constructor, creates an empty handle + */ + Sampler(); + + /** + * @brief Destructor + */ + ~Sampler(); + + /** + * @brief Copy constructor, creates a new handle to the same object + * + * @param[in] handle Handle to an object + */ + Sampler( const Sampler& handle ); + + /** + * @brief Downcast to a sampler handle. + * + * If not the returned handle is left uninitialized. + * @param[in] handle to An object + * @return handle or an uninitialized handle + */ + static Sampler DownCast( BaseHandle handle ); + + /** + * @brief Assignment operator, changes this handle to point at the same object + * + * @param[in] handle Handle to an object + * @return Reference to the assigned object + */ + Sampler& operator=( const Sampler& handle ); + + /** + * @brief Sets the name of the shader uniform that will use this sampler + * + * @param[in] name String with the name of the uniform + */ + void SetUniformName( const std::string& name ); + + /** + * @brief Set the image used by this sampler + * + * @param[in] image Image used by this sampler + */ + void SetImage( Image& image ); + + /** + * @brief Retrieve the image used by this sampler + * + * If no image is assigned, an empty handle is returned + * @return The image. + */ + Image GetImage() const; + + /** + * @brief Set the filter modes for this sampler + * + * Calling this function sets the properties MINIFICATION_FILTER + * and MAGNIFICATION_FILTER + * + * @param[in] minFilter The minification filter that will be used + * @param[in] magFilter The magnification filter that will be used + */ + void SetFilterMode( FilterMode minFilter, FilterMode magFilter ); + + /** + * @brief Set the wrap modes for this sampler + * + * Calling this function sets the properties U_WRAP and V_WRAP + * + * param[in] uWrap Wrap mode for u coordinates + * param[in] vWrap Wrap mode for v coordinates + */ + void SetWrapMode( WrapMode uWrap, WrapMode vWrap ); + + /** + * @brief Set if this sampler should be considered for opacity hinting + * + * Calling this function sets the property AFFECTS_TRANSPARENCY + * + * param[in] affectsTransparency Specifies if this sampler should be considered for opacity hinting + */ + void SetAffectsTransparency( bool affectsTransparency ); + +public: + /** + * @brief The constructor + * + * @param [in] pointer A pointer to a newly allocated Sampler + */ + explicit DALI_INTERNAL Sampler( Internal::Sampler* pointer ); +}; + +} //namespace Dali + +#endif // DALI_SAMPLER_H diff --git a/dali/devel-api/rendering/shader.cpp b/dali/devel-api/rendering/shader.cpp new file mode 100644 index 0000000..6be2e63 --- /dev/null +++ b/dali/devel-api/rendering/shader.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include // Dali::Shader + +// INTERNAL INCLUDES +#include // Dali::Internal::Shader + +namespace Dali +{ + +Shader Shader::New( const std::string& vertexShader, + const std::string& fragmentShader, + ShaderHints hints ) +{ + Internal::ShaderPtr renderer = Internal::Shader::New( vertexShader, fragmentShader, hints ); + return Shader( renderer.Get() ); +} + +Shader::Shader() +{ +} + +Shader::~Shader() +{ +} + +Shader::Shader( const Shader& handle ) +: Handle( handle ) +{ +} + +Shader Shader::DownCast( BaseHandle handle ) +{ + return Shader( dynamic_cast(handle.GetObjectPtr())); +} + +Shader& Shader::operator=( const Shader& handle ) +{ + BaseHandle::operator=( handle ); + return *this; +} + +Shader::Shader( Internal::Shader* pointer ) +: Handle( pointer ) +{ +} + +} // namespace Dali diff --git a/dali/devel-api/rendering/shader.h b/dali/devel-api/rendering/shader.h new file mode 100644 index 0000000..05d01f3 --- /dev/null +++ b/dali/devel-api/rendering/shader.h @@ -0,0 +1,153 @@ +#ifndef DALI_SHADER_H +#define DALI_SHADER_H + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include // std::string + +// INTERNAL INCLUDES +#include // Dali::Handle +#include // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX + +/** + * @brief DALI_COMPOSE_SHADER macro provides a convenient way to write shader source code. + * + * We normally use double quotation marks to write a string such as "Hello World". + * However many symbols are needed to add multiple lines of string. + * We don't need to write quotation marks using this macro at every line. + * + * [An example of double quotation marks usage] + *
+ * const string FRAGMENT_SHADER_SOURCE = \
+ * "  void main()\n"
+ * "  {\n"
+ * "    gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n"
+ * "  }\n";
+ * 

+ * [An example of DALI_COMPOSE_SHADER usage] + *
+ * const string VERTEX_SHADER_SOURCE = DALI_COMPOSE_SHADER (
+ *   void main()
+ *   {
+ *     gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);
+ *     vTexCoord = aTexCoord;
+ *   }
+ * );
+ * 
+ */ +#define DALI_COMPOSE_SHADER(STR) #STR + +namespace Dali +{ + +namespace Internal DALI_INTERNAL +{ +class Shader; +} + +/** + * @brief Shaders allows custom vertex and color transformations in the GPU + */ +class DALI_IMPORT_API Shader : public Handle +{ +public: + /** + * @brief Hints for rendering/subdividing geometry. + */ + enum ShaderHints + { + HINT_NONE = 0x00, ///< no hints + HINT_REQUIRES_SELF_DEPTH_TEST = 0x01, ///< Expects depth testing enabled + HINT_OUTPUT_IS_TRANSPARENT = 0x02, ///< Might generate transparent alpha from opaque inputs + HINT_OUTPUT_IS_OPAQUE = 0x04, ///< Outputs opaque colors even if the inputs are transparent + HINT_MODIFIES_GEOMETRY = 0x08, ///< Might change position of vertices, + ///< this option disables any culling optimizations + }; + + /** + * @brief An enumeration of properties belonging to the Shader class. + */ + struct Property + { + enum + { + PROGRAM = DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "program", type MAP; {"vertex-prefix":"","fragment-prefix":"","vertex":"","fragment":""} + SHADER_HINTS, ///< name "shader-hints", type INTEGER; (bitfield) values from enum Shader::Hints + }; + }; + + /** + * @brief Create Shader. + * + * @param vertexShader code for the effect. If you pass in an empty string, the default version will be used + * @param fragmentShader code for the effect. If you pass in an empty string, the default version will be used + * @param hints GeometryHints to define the geometry of the rendered object + * @return A handle to a shader effect + */ + static Shader New( const std::string& vertexShader, + const std::string& fragmentShader, + ShaderHints hints = ShaderHints(HINT_NONE) ); + + /** + * @brief Default constructor, creates an empty handle + */ + Shader(); + + /** + * @brief Destructor + * + * This is non-virtual since derived Handle types must not contain data or virtual methods. + */ + ~Shader(); + + /** + * @brief Copy constructor + * + * @param handle A handle to a Shader object + */ + Shader( const Shader& handle ); + + /** + * @brief Downcast to a shader handle. + * + * If not a shader the returned shader handle is left uninitialized. + * @param[in] handle to an object + * @return shader handle or an uninitialized handle + */ + static Shader DownCast( BaseHandle handle ); + + /** + * @brief Assignment operator, changes this handle to point at the same object + * + * @param[in] handle Handle to an object + * @return Reference to the assigned object + */ + Shader& operator=( const Shader& handle ); + +public: // Not intended for application developers + /** + * @brief This constructor is used by Dali New() methods. + * @param [in] effect A pointer to a newly allocated Dali resource. + */ + explicit DALI_INTERNAL Shader( Internal::Shader* effect ); +}; + +} // namespace Dali + +#endif // DALI_SHADER_H diff --git a/dali/devel-api/scripting/scripting.cpp b/dali/devel-api/scripting/scripting.cpp new file mode 100644 index 0000000..98483c5 --- /dev/null +++ b/dali/devel-api/scripting/scripting.cpp @@ -0,0 +1,681 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Scripting +{ + +namespace +{ + +// Tables used here for converting strings to the enumerations and vice versa +struct AnchorValue +{ + const char* name; + const Vector3 value; +}; +const AnchorValue ANCHOR_CONSTANT_TABLE[] = +{ + { "TOP_LEFT", ParentOrigin::TOP_LEFT }, + { "TOP_CENTER", ParentOrigin::TOP_CENTER }, + { "TOP_RIGHT", ParentOrigin::TOP_RIGHT }, + { "CENTER_LEFT", ParentOrigin::CENTER_LEFT }, + { "CENTER", ParentOrigin::CENTER }, + { "CENTER_RIGHT", ParentOrigin::CENTER_RIGHT }, + { "BOTTOM_LEFT", ParentOrigin::BOTTOM_LEFT }, + { "BOTTOM_CENTER", ParentOrigin::BOTTOM_CENTER }, + { "BOTTOM_RIGHT", ParentOrigin::BOTTOM_RIGHT }, +}; +const unsigned int ANCHOR_CONSTANT_TABLE_COUNT = sizeof( ANCHOR_CONSTANT_TABLE ) / sizeof( ANCHOR_CONSTANT_TABLE[0] ); + +const StringEnum COLOR_MODE_TABLE[] = +{ + { "USE_OWN_COLOR", USE_OWN_COLOR }, + { "USE_PARENT_COLOR", USE_PARENT_COLOR }, + { "USE_OWN_MULTIPLY_PARENT_COLOR", USE_OWN_MULTIPLY_PARENT_COLOR }, + { "USE_OWN_MULTIPLY_PARENT_ALPHA", USE_OWN_MULTIPLY_PARENT_ALPHA }, +}; +const unsigned int COLOR_MODE_TABLE_COUNT = sizeof( COLOR_MODE_TABLE ) / sizeof( COLOR_MODE_TABLE[0] ); + +const StringEnum POSITION_INHERITANCE_MODE_TABLE[] = +{ + { "INHERIT_PARENT_POSITION", INHERIT_PARENT_POSITION }, + { "USE_PARENT_POSITION", USE_PARENT_POSITION }, + { "USE_PARENT_POSITION_PLUS_LOCAL_POSITION", USE_PARENT_POSITION_PLUS_LOCAL_POSITION }, + { "DONT_INHERIT_POSITION", DONT_INHERIT_POSITION }, +}; +const unsigned int POSITION_INHERITANCE_MODE_TABLE_COUNT = sizeof( POSITION_INHERITANCE_MODE_TABLE ) / sizeof( POSITION_INHERITANCE_MODE_TABLE[0] ); + +const StringEnum DRAW_MODE_TABLE[] = +{ + { "NORMAL", DrawMode::NORMAL }, + { "OVERLAY_2D", DrawMode::OVERLAY_2D }, + { "STENCIL", DrawMode::STENCIL }, +}; +const unsigned int DRAW_MODE_TABLE_COUNT = sizeof( DRAW_MODE_TABLE ) / sizeof( DRAW_MODE_TABLE[0] ); + +const StringEnum IMAGE_LOAD_POLICY_TABLE[] = +{ + { "IMMEDIATE", ResourceImage::IMMEDIATE }, + { "ON_DEMAND", ResourceImage::ON_DEMAND }, +}; +const unsigned int IMAGE_LOAD_POLICY_TABLE_COUNT = sizeof( IMAGE_LOAD_POLICY_TABLE ) / sizeof( IMAGE_LOAD_POLICY_TABLE[0] ); + +const StringEnum IMAGE_RELEASE_POLICY_TABLE[] = +{ + { "UNUSED", Image::UNUSED }, + { "NEVER", Image::NEVER }, +}; +const unsigned int IMAGE_RELEASE_POLICY_TABLE_COUNT = sizeof( IMAGE_RELEASE_POLICY_TABLE ) / sizeof( IMAGE_RELEASE_POLICY_TABLE[0] ); + +const StringEnum PIXEL_FORMAT_TABLE[] = +{ + { "A8", Pixel::A8 }, + { "L8", Pixel::L8 }, + { "LA88", Pixel::LA88 }, + { "RGB565", Pixel::RGB565 }, + { "BGR565", Pixel::BGR565 }, + { "RGBA4444", Pixel::RGBA4444 }, + { "BGRA4444", Pixel::BGRA4444 }, + { "RGBA5551", Pixel::RGBA5551 }, + { "BGRA5551", Pixel::BGRA5551 }, + { "RGB888", Pixel::RGB888 }, + { "RGB8888", Pixel::RGB8888 }, + { "BGR8888", Pixel::BGR8888 }, + { "RGBA8888", Pixel::RGBA8888 }, + { "BGRA8888", Pixel::BGRA8888 }, + { "COMPRESSED_R11_EAC", Pixel::COMPRESSED_R11_EAC }, + { "COMPRESSED_SIGNED_R11_EAC", Pixel::COMPRESSED_SIGNED_R11_EAC }, + { "COMPRESSED_SIGNED_RG11_EAC", Pixel::COMPRESSED_SIGNED_RG11_EAC }, + { "COMPRESSED_RG11_EAC", Pixel::COMPRESSED_RG11_EAC }, + { "COMPRESSED_RGB8_ETC2", Pixel::COMPRESSED_RGB8_ETC2 }, + { "COMPRESSED_SRGB8_ETC2", Pixel::COMPRESSED_SRGB8_ETC2 }, + { "COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2", Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 }, + { "COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2", Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 }, + { "COMPRESSED_RGBA8_ETC2_EAC", Pixel::COMPRESSED_RGBA8_ETC2_EAC }, + { "COMPRESSED_SRGB8_ALPHA8_ETC2_EAC", Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC }, + { "COMPRESSED_RGB8_ETC1", Pixel::COMPRESSED_RGB8_ETC1 }, + { "COMPRESSED_RGB_PVRTC_4BPPV1", Pixel::COMPRESSED_RGB_PVRTC_4BPPV1 }, +}; +const unsigned int PIXEL_FORMAT_TABLE_COUNT = sizeof( PIXEL_FORMAT_TABLE ) / sizeof( PIXEL_FORMAT_TABLE[0] ); + +const StringEnum IMAGE_FITTING_MODE_TABLE[] = +{ + { "SHRINK_TO_FIT", FittingMode::SHRINK_TO_FIT }, + { "SCALE_TO_FILL", FittingMode::SCALE_TO_FILL }, + { "FIT_WIDTH", FittingMode::FIT_WIDTH }, + { "FIT_HEIGHT", FittingMode::FIT_HEIGHT }, +}; +const unsigned int IMAGE_FITTING_MODE_TABLE_COUNT = sizeof( IMAGE_FITTING_MODE_TABLE ) / sizeof( IMAGE_FITTING_MODE_TABLE[0] ); + +const StringEnum IMAGE_SAMPLING_MODE_TABLE[] = +{ + { "BOX", SamplingMode::BOX }, + { "NEAREST", SamplingMode::NEAREST }, + { "LINEAR", SamplingMode::LINEAR }, + { "BOX_THEN_NEAREST", SamplingMode::BOX_THEN_NEAREST }, + { "BOX_THEN_LINEAR", SamplingMode::BOX_THEN_LINEAR }, + { "NO_FILTER", SamplingMode::NO_FILTER }, + { "DONT_CARE", SamplingMode::DONT_CARE }, +}; +const unsigned int IMAGE_SAMPLING_MODE_TABLE_COUNT = sizeof( IMAGE_SAMPLING_MODE_TABLE ) / sizeof( IMAGE_SAMPLING_MODE_TABLE[0] ); + +const char* ImageTypeName[] = { "ResourceImage", "FrameBufferImage", "BufferImage" }; +enum ImageType { RESOURCE_IMAGE, FRAME_BUFFER_IMAGE, BUFFER_IMAGE }; +const unsigned int imageTypeCount = sizeof( ImageTypeName ) / sizeof( const char* ); + +bool CompareEnums( const char * a, const char * b ) +{ + while( ( *a != '\0' ) && ( *b != '\0' ) ) + { + char ca = *a; + char cb = *b; + + if( ( ( ca == '-' ) || ( ca == '_') ) && + ( ( cb == '-' ) || ( cb == '_') ) ) + { + ++a; + ++b; + continue; + } + + if( ( 'A' <= ca ) && ( ca <= 'Z') ) + { + ca = ca + ( 'a' - 'A' ); + } + + if( ( 'A' <= cb ) && ( cb <= 'Z') ) + { + cb = cb + ( 'a' - 'A' ); + } + + if( ca != cb ) + { + return false; + } + + ++a; + ++b; + } + + if( ( *a == '\0' ) && ( *b == '\0' ) ) + { + return true; + } + + return false; +} + +} // unnamed namespace + +unsigned int FindEnumIndex( const char* value, const StringEnum* table, unsigned int tableCount ) +{ + unsigned int index = 0; + bool found = false; + for ( unsigned int i = 0; i < tableCount; ++i, ++index ) + { + if( CompareEnums( value, table->string ) ) + { + found = true; + break; + } + ++table; + } + if ( !found ) + { + DALI_LOG_ERROR( "Unknown enumeration string %s\n", value ); + } + return index; +} + +ColorMode GetColorMode( const std::string& value ) +{ + // return default on error + ColorMode mode( USE_OWN_MULTIPLY_PARENT_ALPHA ); + GetEnumeration< ColorMode >( value.c_str(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode ); + return mode; +} + + +std::string GetColorMode( ColorMode value ) +{ + const char* name = GetEnumerationName< ColorMode >( value, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT ); + if( name ) + { + return std::string( name ); + } + return std::string(); +} + +PositionInheritanceMode GetPositionInheritanceMode( const std::string& value ) +{ + // return default on error + PositionInheritanceMode mode( INHERIT_PARENT_POSITION ); + GetEnumeration< PositionInheritanceMode >( value.c_str(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode ); + return mode; +} + + +std::string GetPositionInheritanceMode( PositionInheritanceMode value ) +{ + const char* name = GetEnumerationName< PositionInheritanceMode >( value, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT ); + if( name ) + { + return std::string( name ); + } + return std::string(); +} + + +DrawMode::Type GetDrawMode( const std::string& value ) +{ + // return default on error + DrawMode::Type mode( DrawMode::NORMAL ); + GetEnumeration< DrawMode::Type >( value.c_str(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode ); + return mode; +} + + +std::string GetDrawMode( DrawMode::Type value ) +{ + const char* name = GetEnumerationName< DrawMode::Type >( value, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT ); + if( name ) + { + return std::string( name ); + } + return std::string(); +} + + +Vector3 GetAnchorConstant( const std::string& value ) +{ + for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i ) + { + if( CompareEnums( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name ) ) + { + return ANCHOR_CONSTANT_TABLE[ i ].value; + } + } + return Vector3(); +} + + +Image NewImage( const Property::Value& property ) +{ + Image ret; + + std::string filename; + ResourceImage::LoadPolicy loadPolicy = Dali::Internal::IMAGE_LOAD_POLICY_DEFAULT; + Image::ReleasePolicy releasePolicy = Dali::Internal::IMAGE_RELEASE_POLICY_DEFAULT; + Internal::ImageAttributes attributes = Internal::ImageAttributes::New(); + + const Property::Map* map = property.GetMap(); + ImageType imageType = RESOURCE_IMAGE; // default to resource image + if( map ) + { + // first check the type as it determines, which other parameters are needed + const Property::Value* value = map->Find( "type" ); + if( value ) + { + std::string type; + value->Get( type ); + for( unsigned int i = 0; i < imageTypeCount; ++i ) + { + if( 0 == type.compare( ImageTypeName[ i ] ) ) + { + imageType = static_cast( i ); + break; + } + } + } + + // filename is only needed for resource images + if( RESOURCE_IMAGE == imageType ) + { + const Property::Value* value = map->Find( "filename" ); + if( value ) + { + value->Get( filename ); + } + // if empty file, no need to go further + if( filename.size() == 0 ) + { + DALI_LOG_ERROR( "No filename\n" ); + return Image(); + } + } + + value = map->Find( "load-policy" ); + if( value ) + { + std::string policy; + value->Get( policy ); + // keep default value on error + GetEnumeration< ResourceImage::LoadPolicy >( policy.c_str(), IMAGE_LOAD_POLICY_TABLE, IMAGE_LOAD_POLICY_TABLE_COUNT, loadPolicy ); + } + + value = map->Find( "release-policy" ); + if( value ) + { + std::string policy; + value->Get( policy ); + // keep default value on error + GetEnumeration< Image::ReleasePolicy >( policy.c_str(), IMAGE_RELEASE_POLICY_TABLE, IMAGE_RELEASE_POLICY_TABLE_COUNT, releasePolicy ); + } + + // Width and height can be set individually. Dali derives the unspecified + // dimension from the aspect ratio of the raw image. + int width = 0, height = 0; + + value = map->Find( "width" ); + if( value ) + { + // handle floats and integer the same for json script + if( value->GetType() == Property::FLOAT ) + { + width = static_cast( value->Get() ); + } + else + { + value->Get( width ); + } + } + value = map->Find( "height" ); + if( value ) + { + if( value->GetType() == Property::FLOAT ) + { + height = static_cast( value->Get() ); + } + else + { + value->Get( height ); + } + } + attributes.SetSize( width, height ); + + Pixel::Format pixelFormat = Pixel::RGBA8888; + value = map->Find( "pixel-format" ); + if( value ) + { + std::string format; + value->Get( format ); + GetEnumeration< Pixel::Format >( format.c_str(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT, pixelFormat ); + } + + value = map->Find( "fitting-mode" ); + if( value ) + { + std::string fitting; + value->Get( fitting ); + FittingMode::Type mode; + if( GetEnumeration< FittingMode::Type >( fitting.c_str(), IMAGE_FITTING_MODE_TABLE, IMAGE_FITTING_MODE_TABLE_COUNT, mode ) ) + { + attributes.SetScalingMode( mode ); + } + } + + value = map->Find( "sampling-mode" ); + if( value ) + { + std::string sampling; + value->Get( sampling ); + SamplingMode::Type mode; + if( GetEnumeration< SamplingMode::Type >( sampling.c_str(), IMAGE_SAMPLING_MODE_TABLE, IMAGE_SAMPLING_MODE_TABLE_COUNT, mode ) ) + { + attributes.SetFilterMode( mode ); + } + } + + value = map->Find( "orientation" ); + if( value ) + { + bool b = value->Get(); + attributes.SetOrientationCorrection( b ); + } + + switch( imageType ) + { + case RESOURCE_IMAGE : + { + ret = ResourceImage::New( filename, loadPolicy, releasePolicy, + ImageDimensions( attributes.GetSize().x, attributes.GetSize().y ), + attributes.GetScalingMode(), attributes.GetFilterMode(), attributes.GetOrientationCorrection() ); + break; + } + case BUFFER_IMAGE : + { + ret = BufferImage::New( attributes.GetWidth(), + attributes.GetHeight(), + pixelFormat, + releasePolicy ); + break; + } + case FRAME_BUFFER_IMAGE : + { + ret = FrameBufferImage::New( attributes.GetWidth(), + attributes.GetHeight(), + pixelFormat, + releasePolicy ); + break; + } + } + } + + return ret; + +} // Image NewImage( Property::Value map ) + + +ShaderEffect NewShaderEffect( const Property::Value& property ) +{ + Internal::ShaderEffectPtr ret; + + const Property::Map* map = property.GetMap(); + if( map ) + { + ret = Internal::ShaderEffect::New( Dali::ShaderEffect::HINT_NONE ); // hint can be reset if in map + + const Property::Value* value = map->Find( "program" ); + if( value ) + { + Property::Index index = ret->GetPropertyIndex( "program" ); + ret->SetProperty( index, *value ); + } + + for( unsigned int i = 0; i < map->Count(); ++i ) + { + const std::string& key = map->GetKey( i ); + if( key != "program" ) + { + Property::Index index = ret->GetPropertyIndex( key ); + + const Property::Value& value = map->GetValue( i ); + if( Property::INVALID_INDEX != index ) + { + ret->SetProperty( index, value ); + } + else + { + // if its not a property then register it as a uniform (making a custom property) + if( value.GetType() == Property::INTEGER ) + { + // valid uniforms are floats, vec3's etc so we recast if the user accidentally + // set as integer. Note the map could have come from json script. + Property::Value asFloat( static_cast( value.Get() ) ); + ret->SetUniform( key, asFloat, Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT ); + } + else + { + ret->SetUniform( key, value, Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT ); + } + } + } + } + } + + return Dali::ShaderEffect(ret.Get()); +} + + +Actor NewActor( const Property::Map& map ) +{ + BaseHandle handle; + + // First find type and create Actor + Property::Value* typeValue = map.Find( "type" ); + if ( typeValue ) + { + TypeInfo type = TypeRegistry::Get().GetTypeInfo( typeValue->Get< std::string >() ); + if ( type ) + { + handle = type.CreateInstance(); + } + } + + if ( !handle ) + { + DALI_LOG_ERROR( "Actor type not provided\n" ); + return Actor(); + } + + Actor actor( Actor::DownCast( handle ) ); + + if ( actor ) + { + // Now set the properties, or create children + for ( unsigned int i = 0, mapCount = map.Count(); i < mapCount; ++i ) + { + const StringValuePair& pair( map.GetPair( i ) ); + const std::string& key( pair.first ); + if ( key == "type" ) + { + continue; + } + + const Property::Value& value( pair.second ); + + if ( key == "actors" ) + { + // Create children + Property::Array actorArray = value.Get< Property::Array >(); + for ( Property::Array::SizeType i = 0; i < actorArray.Size(); ++i) + { + actor.Add( NewActor( actorArray[i].Get< Property::Map >() ) ); + } + } + else if( key == "parent-origin" ) + { + // Parent Origin can be a string constant as well as a Vector3 + + const Property::Type type( value.GetType() ); + if ( type == Property::VECTOR3 ) + { + actor.SetParentOrigin( value.Get< Vector3 >() ); + } + else if( type == Property::STRING ) + { + actor.SetParentOrigin( GetAnchorConstant( value.Get< std::string >() ) ); + } + } + else if( key == "anchor-point" ) + { + // Anchor Point can be a string constant as well as a Vector3 + + const Property::Type type( value.GetType() ); + if ( type == Property::VECTOR3 ) + { + actor.SetAnchorPoint( value.Get< Vector3 >() ); + } + else if( type == Property::STRING ) + { + actor.SetAnchorPoint( GetAnchorConstant( value.Get< std::string >() ) ); + } + } + else + { + Property::Index index( actor.GetPropertyIndex( key ) ); + + if ( index != Property::INVALID_INDEX ) + { + actor.SetProperty( index, value ); + } + } + } + } + + return actor; +} + +void CreatePropertyMap( Actor actor, Property::Map& map ) +{ + map.Clear(); + + if ( actor ) + { + map[ "type" ] = actor.GetTypeName(); + + // Default properties + Property::IndexContainer indices; + actor.GetPropertyIndices( indices ); + const Property::IndexContainer::ConstIterator endIter = indices.End(); + + for ( Property::IndexContainer::Iterator iter = indices.Begin(); iter != endIter; ++iter ) + { + map[ actor.GetPropertyName( *iter ) ] = actor.GetProperty( *iter ); + } + + // Children + unsigned int childCount( actor.GetChildCount() ); + if ( childCount ) + { + Property::Array childArray; + for ( unsigned int child = 0; child < childCount; ++child ) + { + Property::Map childMap; + CreatePropertyMap( actor.GetChildAt( child ), childMap ); + childArray.PushBack( childMap ); + } + map[ "actors" ] = childArray; + } + } +} + +void CreatePropertyMap( Image image, Property::Map& map ) +{ + map.Clear(); + + if ( image ) + { + std::string imageType( "ResourceImage" ); + + // Get Type - cannot use TypeRegistry as Image is not an Object and thus, not registered + BufferImage bufferImage = BufferImage::DownCast( image ); + if ( bufferImage ) + { + imageType = "BufferImage"; + map[ "pixel-format" ] = GetEnumerationName< Pixel::Format >( bufferImage.GetPixelFormat(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT ); + } + else if ( FrameBufferImage::DownCast( image ) ) + { + imageType = "FrameBufferImage"; + } + + map[ "type" ] = imageType; + map[ "release-policy" ] = GetEnumerationName< Image::ReleasePolicy >( image.GetReleasePolicy(), IMAGE_RELEASE_POLICY_TABLE, IMAGE_RELEASE_POLICY_TABLE_COUNT ); + + ResourceImage resourceImage = ResourceImage::DownCast( image ); + if( resourceImage ) + { + map[ "filename" ] = resourceImage.GetUrl(); + map[ "load-policy" ] = GetEnumerationName< ResourceImage::LoadPolicy >( resourceImage.GetLoadPolicy(), IMAGE_LOAD_POLICY_TABLE, IMAGE_LOAD_POLICY_TABLE_COUNT ); + } + + int width( image.GetWidth() ); + int height( image.GetHeight() ); + + if ( width && height ) + { + map[ "width" ] = width; + map[ "height" ] = height; + } + } +} + +} // namespace scripting + +} // namespace Dali + + + + diff --git a/dali/devel-api/scripting/scripting.h b/dali/devel-api/scripting/scripting.h new file mode 100644 index 0000000..40787de --- /dev/null +++ b/dali/devel-api/scripting/scripting.h @@ -0,0 +1,292 @@ +#ifndef __DALI_SCRIPTING_H__ +#define __DALI_SCRIPTING_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +class Actor; + +/** + * @brief Utilities for scripting support. + */ +namespace Scripting +{ + +/** + * @brief Template structure which stores an enumeration and its string equivalent. + */ +struct StringEnum +{ + const char* string; ///< The string representation + const int value; ///< The enumeration value wrapped in int +}; + +/** + * @brief Find the given enum index from the table + * + * @param[in] value The string equivalent (case-insensitive). + * @param[in] table A pointer to an array with the enumeration to string equivalents. + * @param[in] tableCount Number of items in the array. + * @return The index of the enumeration. If enumeration is not found, logs an error and returns tableCount. + */ +DALI_IMPORT_API unsigned int FindEnumIndex( const char* value, const StringEnum* table, unsigned int tableCount ); + +/** + * @brief Chooses the appropriate enumeration for the provided string from the given table. + * + * @param[in] value The string equivalent (case-insensitive). + * @param[in] table A pointer to an array with the enumeration to string equivalents. + * @param[in] tableCount Number of items in the array. + * @param[out] result The enum value + * + * @return True if the value was found from the table + */ +template< typename T > +bool GetEnumeration( const char* value, const StringEnum* table, unsigned int tableCount, T& result ) +{ + bool retVal( false ); + if( table ) + { + unsigned int index = FindEnumIndex( value, table, tableCount ); + // check to avoid crash, not asserting on purpose, error is logged instead + if( index < tableCount ) + { + result = static_cast( table[ index ].value ); + retVal = true; + } + } + return retVal; +} + +/** + * @brief Chooses the appropriate string for the provided enumeration from the given table. + * + * @param[in] value The enumeration. + * @param[in] table A pointer to an array with the enumeration to string equivalents. + * @param[in] tableCount Number of items in the array. + * + * @return The equivalent enumeration for the given string. Will return NULL if the value does not exist + * + * @note The caller is NOT responsible for cleaning up the returned pointer as it is statically allocated. + */ +template< typename T > +const char* GetEnumerationName( T value, const StringEnum* table, unsigned int tableCount ) +{ + if( table ) + { + for ( unsigned int i = 0; i < tableCount; ++i ) + { + if ( value == T(table[ i ].value) ) + { + return table[ i ].string; + } + } + } + return NULL; +} + +/** + * @brief Chooses the appropriate string for the provided enumeration from the given table. + * This is an optimised version that handles enumerations that start at 0 and are linear only. + * + * @param[in] value The enumeration. + * @param[in] table A pointer to an array with the enumeration to string equivalents. + * @param[in] tableCount Number of items in the array. + * + * @return The equivalent enumeration for the given string. Will return NULL if the value does not exist + * + * @note The caller is NOT responsible for cleaning up the returned pointer as it is statically allocated. + */ +template< typename T > +const char * GetLinearEnumerationName( T value, const StringEnum* table, unsigned int tableCount ) +{ + if ( table && ( value > 0 || value <= (int)tableCount ) ) + { + return table[value].string; + } + return NULL; +} + +/** + * @brief Takes a string and returns the appropriate color mode. + * + * @param[in] value The input string + * @return The corresponding color-mode. + */ +DALI_IMPORT_API ColorMode GetColorMode( const std::string& value ); + +/** + * @brief Takes a color mode and returns the appropriate string equivalent. + * + * @param[in] value The color mode + * @return The corresponding string. + */ +DALI_IMPORT_API std::string GetColorMode( ColorMode value ); + +/** + * @brief Takes a string and returns the appropriate position inheritance mode. + * + * @param[in] value The input string + * @return The corresponding position-inheritance-mode. + */ +DALI_IMPORT_API PositionInheritanceMode GetPositionInheritanceMode( const std::string& value ); + +/** + * @brief Takes a position inheritance mode and returns the string equivalent. + * + * @param[in] value The position-inheritance-mode. + * @return The corresponding string. + */ +DALI_IMPORT_API std::string GetPositionInheritanceMode( PositionInheritanceMode value ); + +/** + * @brief Takes a string and returns the appropriate draw mode. + * + * @param[in] value The input string + * @return The corresponding draw-mode. + */ +DALI_IMPORT_API DrawMode::Type GetDrawMode( const std::string& value ); + +/** + * @brief Takes a draw-mode and returns the string equivalent. + * + * @param[in] value The draw-mode. + * @return The corresponding string. + */ +DALI_IMPORT_API std::string GetDrawMode( DrawMode::Type value ); + +/** + * @brief Takes a string and returns the appropriate anchor-point or parent-origin constant. + * + * @param[in] value The input string + * @return The corresponding anchor-point or parent-origin constant. + */ +DALI_IMPORT_API Vector3 GetAnchorConstant( const std::string& value ); + +/** + * @brief Creates object with data from the property value map. + * + * @param[in] property The property value map with the following valid fields: + * @code + * "filename": type std::string + * "load-policy" type std::string (enum) + * "release-policy" type std::string (enum) + * "width" type float + * "height" type float + * "pixel-format" type std::string (enum) + * "fitting-mode" type std::string (enum) + * "sampling-mode" type std::string (enum) + * "orientation" type bool + * "type" type std::string (FrameBufferImage|BufferImage|ResourceImage(default)) + * @endcode + * Some fields are optional and some only pertain to a specific type. + * + * @return a pointer to a newly created object. + */ +DALI_IMPORT_API Image NewImage( const Property::Value& property ); + +/** + * @brief Creates object with data from the property value map. + * + * @param[in] property The property value map with the following valid fields: + * @code + * // a program can be specified as string or a filename. + * // some fields may be ignored depending on the geometry-type + * "program": type Map + * { + * "vertex": type std::string + * "fragment": type std::string + * "vertex-prefix": type std::string + * "fragment-prefix": type std::string + * "text-vertex": type std::string + * "text-fragment": type std::string + * "vertex-filename": type std::string + * "fragment-filename": type std::string + * "vertex-prefix-filename": type std::string + * "fragment-prefix-filename": type std::string + * "text-vertex-filename": type std::string + * "text-fragment-filename": type std::string + * "geometry-type": type std::string (enum) + * "geometry-hints": type std::string (enum) + * } + * // uniforms must be specified to be registered + * "uUniform1": type float, + * "uUniform2": type float, etc + * @endcode + * + * @return a pointer to a newly created object. + */ +DALI_IMPORT_API ShaderEffect NewShaderEffect( const Property::Value& property ); + +/** + * @brief Creates an actor with the date from the property value map. + * + * @param[in] map The property value map with the properties (and hierarchy) of the actor required + * For example: + * @code + * { + * "type": "ImageActor", + * "image": + * { + * "filename":"my-image-path.png" + * }, + * "actors": + * [ + * { + * "type":"Actor", + * "position":[0,0,0] + * } + * ] + * } + * @endcode + * + * @return Handle to the newly created actor. + */ +DALI_IMPORT_API Actor NewActor( const Property::Map& map ); + +/** + * @brief Creates a Property::Map from the actor provided. + * + * @param[in] actor The base-actor from which a Property::Map should be created + * @param[out] map This map is cleared and a property map of actor and its children is filled in + */ +DALI_IMPORT_API void CreatePropertyMap( Actor actor, Property::Map& map ); + +/** + * @brief Creates a Property::Map from the image provided. + * + * @param[in] image The image from which a Property::Map should be created + * @param[out] map This map is cleared and a property map of the image is filled in + */ +DALI_IMPORT_API void CreatePropertyMap( Image image, Property::Map& map ); + +} + +} // namespace Dali + +#endif // __DALI_SCRIPTING_H__ diff --git a/dali/integration-api/bitmap.cpp b/dali/integration-api/bitmap.cpp new file mode 100644 index 0000000..bfff2d5 --- /dev/null +++ b/dali/integration-api/bitmap.cpp @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Integration +{ +using namespace Dali::Pixel; + +void ConvertToGlFormat( Format pixelformat, unsigned& pixelDataType, unsigned& internalFormat ) +{ + // Compressed textures have no pixelDataType, so init to an invalid value: + pixelDataType = -1; + + switch( pixelformat ) + { + case A8: + { + pixelDataType = GL_UNSIGNED_BYTE; + internalFormat= GL_ALPHA; + break; + } + + case L8: + { + pixelDataType = GL_UNSIGNED_BYTE; + internalFormat= GL_LUMINANCE; + break; + } + + case LA88: + { + pixelDataType = GL_UNSIGNED_BYTE; + internalFormat= GL_LUMINANCE_ALPHA; + break; + } + + case RGB565: + { + pixelDataType = GL_UNSIGNED_SHORT_5_6_5; + internalFormat= GL_RGB; + break; + } + + case BGR565: + { + DALI_LOG_ERROR("Pixel format BGR565 is not supported by GLES.\n"); + pixelDataType = GL_UNSIGNED_SHORT_5_6_5; +#ifdef _ARCH_ARM_ + internalFormat= GL_BGRA_EXT; // alpha is reserved but not used +#else + internalFormat= GL_RGBA; // alpha is reserved but not used +#endif + break; + } + + case RGBA4444: + { + pixelDataType = GL_UNSIGNED_SHORT_4_4_4_4; + internalFormat= GL_RGBA; + break; + } + + case BGRA4444: + { + DALI_LOG_ERROR("Pixel format BGRA4444 is not supported by GLES.\n"); + pixelDataType = GL_UNSIGNED_SHORT_4_4_4_4; +#ifdef _ARCH_ARM_ + internalFormat= GL_BGRA_EXT; // alpha is reserved but not used +#else + internalFormat= GL_RGBA; // alpha is reserved but not used +#endif + break; + } + + case RGBA5551: + { + pixelDataType = GL_UNSIGNED_SHORT_5_5_5_1; + internalFormat= GL_RGBA; + break; + } + + case BGRA5551: + { + DALI_LOG_ERROR("Pixel format BGRA5551 is not supported by GLES.\n"); + pixelDataType = GL_UNSIGNED_SHORT_5_5_5_1; +#ifdef _ARCH_ARM_ + internalFormat= GL_BGRA_EXT; // alpha is reserved but not used +#else + internalFormat= GL_RGBA; // alpha is reserved but not used +#endif + break; + } + + case RGB888: + { + pixelDataType = GL_UNSIGNED_BYTE; + internalFormat= GL_RGB; + break; + } + + case RGB8888: + { + pixelDataType = GL_UNSIGNED_BYTE; + internalFormat= GL_RGBA; // alpha is reserved but not used + break; + } + + case BGR8888: + { + pixelDataType = GL_UNSIGNED_BYTE; +#ifdef GL_BGRA_EXT + internalFormat= GL_BGRA_EXT; // alpha is reserved but not used +#else + internalFormat= GL_RGBA; // alpha is reserved but not used +#endif + break; + } + + case RGBA8888: + { + pixelDataType = GL_UNSIGNED_BYTE; + internalFormat= GL_RGBA; + break; + } + + case BGRA8888: + { + pixelDataType = GL_UNSIGNED_BYTE; +#ifdef GL_BGRA_EXT + internalFormat= GL_BGRA_EXT; // alpha is reserved but not used +#else + internalFormat= GL_RGBA; // alpha is reserved but not used +#endif + break; + } + + // GLES 3.0 standard compressed formats: + case COMPRESSED_R11_EAC: + { + DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_R11_EAC.\n"); + internalFormat = 0x9270; ///! < Hardcoded until we move to GLES 3.0 or greater. + break; + } + case COMPRESSED_SIGNED_R11_EAC: + { + DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SIGNED_R11_EAC.\n" ); + internalFormat = 0x9271; ///! < Hardcoded until we move to GLES 3.0 or greater. + ; + break; + } + case COMPRESSED_RG11_EAC: + { + DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RG11_EAC.\n" ); + internalFormat = 0x9272; ///! < Hardcoded until we move to GLES 3.0 or greater. + break; + } + case COMPRESSED_SIGNED_RG11_EAC: + { + DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SIGNED_RG11_EAC.\n" ); + internalFormat = 0x9273; ///! < Hardcoded until we move to GLES 3.0 or greater. + break; + } + case COMPRESSED_RGB8_ETC2: + { + DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGB8_ETC2.\n" ); + internalFormat = 0x9274; ///! < Hardcoded until we move to GLES 3.0 or greater. + break; + } + case COMPRESSED_SRGB8_ETC2: + { + DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_ETC2.\n" ); + internalFormat = 0x9275; ///! < Hardcoded until we move to GLES 3.0 or greater. + break; + } + case COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + { + DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2.\n" ); + internalFormat = 0x9276; ///! < Hardcoded until we move to GLES 3.0 or greater. + break; + } + case COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + { + DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2.\n" ); + internalFormat = 0x9277; ///! < Hardcoded until we move to GLES 3.0 or greater. + break; + } + case COMPRESSED_RGBA8_ETC2_EAC: + { + DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGBA8_ETC2_EAC.\n" ); + internalFormat = 0x9278; ///! < Hardcoded until we move to GLES 3.0 or greater. + break; + } + case COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + { + DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ETC2_EAC.\n" ); + internalFormat = 0x9279; ///! < Hardcoded until we move to GLES 3.0 or greater. + break; + } + + // GLES 2 extension compressed formats: + case COMPRESSED_RGB8_ETC1: + { + DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using non-standard GLES 2.0 extension compressed pixel format COMPRESSED_RGB8_ETC1.\n" ); + internalFormat = 0x8D64; ///! < Hardcoded so we can test before we move to GLES 3.0 or greater. + break; + } + case COMPRESSED_RGB_PVRTC_4BPPV1: + { + DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using non-standard GLES 2.0 extension compressed pixel format COMPRESSED_RGB_PVRTC_4BPPV1.\n" ); + internalFormat = 0x8C00; ///! < Hardcoded so we can test before we move to GLES 3.0 or greater. + break; + } + } +} + +Bitmap* Bitmap::New( const Profile profile = BITMAP_2D_PACKED_PIXELS, + ResourcePolicy::Discardable discardable = ResourcePolicy::OWNED_DISCARD ) +{ + DALI_ASSERT_DEBUG(profile == BITMAP_2D_PACKED_PIXELS || profile == BITMAP_COMPRESSED); + + switch( profile ) + { + /** A 2D array of pixels where each pixel is a whole number of bytes + * and each scanline of the backing memory buffer may have additional + * bytes off the right edge if requested, and there may be additional + * scanlines past the bottom of the image in the buffer if requested.*/ + case BITMAP_2D_PACKED_PIXELS: + { + Bitmap * const bitmap = new Dali::Internal::BitmapPackedPixel( discardable ); + return bitmap; + } + + /** The data for the bitmap is buffered in an opaque form.*/ + case BITMAP_COMPRESSED: + { + return new Dali::Internal::BitmapCompressed( discardable ); + } + } + return 0; +} + + +Bitmap::Bitmap( ResourcePolicy::Discardable discardable, Dali::Integration::PixelBuffer* pixBuf) +: mImageWidth(0), + mImageHeight(0), + mPixelFormat(Pixel::RGBA8888), + mHasAlphaChannel(true), + mAlphaChannelUsed(true), + mData(pixBuf), + mDiscardable(discardable) +{ +} + +void Bitmap::DiscardBuffer() +{ + if( mDiscardable == ResourcePolicy::OWNED_DISCARD ) + { + DeletePixelBuffer(); + } +} + +Bitmap::~Bitmap() +{ + DALI_LOG_TRACE_METHOD(Debug::Filter::gImage); + + // If owned + if( mDiscardable == ResourcePolicy::OWNED_DISCARD || + mDiscardable == ResourcePolicy::OWNED_RETAIN ) + { + DeletePixelBuffer(); + } +} + +/** + * */ +void Bitmap::DeletePixelBuffer() +{ + if( !mData ) + { + return; + } + free ( mData ); + mData = NULL; +} + + +void Bitmap::Initialize( Pixel::Format pixelFormat, + unsigned int width, + unsigned int height) +{ + DALI_ASSERT_DEBUG(width * height < (32 * 1024) * (32 * 1024) && "The total area of the bitmap is too great.\n"); + mImageWidth = width; + mImageHeight = height; + mPixelFormat = pixelFormat; + + mHasAlphaChannel = Pixel::HasAlpha(pixelFormat); +} + +} //namespace Integration + +} //namespace Dali diff --git a/dali/integration-api/bitmap.h b/dali/integration-api/bitmap.h new file mode 100644 index 0000000..6319ae1 --- /dev/null +++ b/dali/integration-api/bitmap.h @@ -0,0 +1,348 @@ +#ifndef __DALI_INTEGRATION_BITMAP_H__ +#define __DALI_INTEGRATION_BITMAP_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Integration +{ + +/** + * Returns GL data type and internal format for specified pixel format + * @param[in] pixelformat pixel format (eg. Pixel::RGBA32) + * @param[out] pixelDataType pixel data type (eg. GL_UNSIGNED_BYTE) + * @param[out] internalFormat pixel internal format (eg. GL_RGBA) + */ +DALI_IMPORT_API void ConvertToGlFormat(Pixel::Format pixelformat, unsigned& pixelDataType, unsigned& internalFormat); + +class Bitmap; +typedef IntrusivePtr BitmapPtr; +typedef unsigned char PixelBuffer; ///< Pixel data buffers are composed of these + +/** + * Bitmap class. + * An abstract container for image data. + * \sa{BitmapPackedPixel BitmapCompressed BitmapExternal} for concrete + * subclasses. + */ +class DALI_IMPORT_API Bitmap : public Dali::RefObject +{ +protected: + + /** + * Constructor + * Use the static function Bitmap::New() to create instances. + * @param[in] discardable Flag to tell the bitmap if it can delete the buffer with the pixel data. + * @param[in] pixBuf External buffer of pixel data or null. + */ + Bitmap( ResourcePolicy::Discardable discardable = ResourcePolicy::OWNED_RETAIN, Dali::Integration::PixelBuffer* pixBuf = 0 ); + + /** + * Initializes internal class members + * @param[in] pixelFormat pixel format + * @param[in] width Image width in pixels + * @param[in] height Image height in pixels + */ + void Initialize(Pixel::Format pixelFormat, + unsigned int width, + unsigned int height); + + +public: + /** Defines the characteristics of the Bitmap returned from the factory + * function. */ + enum Profile + { + /** A 2D array of pixels where each pixel is a whole number of bytes + * and each scanline of the backing memory buffer may have additional + * bytes off the right edge if requested, and there may be additional + * scanlines past the bottom of the image in the buffer if requested.*/ + BITMAP_2D_PACKED_PIXELS, + /** The data for the bitmap is buffered in an opaque form.*/ + BITMAP_COMPRESSED + }; + + /** + * Create a new instance of a Bitmap with the required profile. + * @return Pointer to created Bitmap subclass. Clients should immediately + * wrap this in a reference-counting smart pointer or store it in a similarly + * automatic owning collection. + * @param[in] profile Defines required features of the bitmap (\sa Profile). + * @param[in] discardable OWNED_DISCARD means that the data is owned by bitmap, + * and may released away after uploading to GPU. + * OWNED_RETAIN means that the data is owned and must be kept in CPU memory + * e.g. for an image that cannot be reloaded from disk. + * NOT_OWNED means that the data is managed by an external component and is + * guaranteed to remain dereferenceable at least as long as the Bitmap remains alive. + */ + static Bitmap* New( Profile profile, ResourcePolicy::Discardable discardable ); + + /** \name GeneralFeatures + * Features that are generic between profiles. */ + /**@{*/ + + /** + * Get the width of the image + * @return The width of the image + */ + unsigned int GetImageWidth() const + { + return mImageWidth; + } + + /** + * Get the height of the image + * @return The height of the image + */ + unsigned int GetImageHeight() const + { + return mImageHeight; + } + + /** + * Get the pixel format + * @return The pixel format + */ + Pixel::Format GetPixelFormat() const + { + return mPixelFormat; + } + + /** + * Get the pixel buffer if it's present. + * @return The buffer if present, or NULL if there is no pixel buffer. + * You can modify its contents. + * @sa ReserveBuffer GetBufferSize + */ + virtual PixelBuffer* GetBuffer() + { + return mData; + } + + /** + * Get the pixel buffer size in bytes + * @return The buffer size in bytes. + * @sa ReserveBuffer GetBuffer + */ + virtual size_t GetBufferSize() const = 0; + + /** + * Queries if the bitmap has an alpha channel + * @return true if there is an alpha channel + */ + bool HasAlphaChannel() const + { + return mHasAlphaChannel; + } + + /** + * Queries if the bitmap has any transparent data + * @return true if the bitmap has alpha data + */ + bool IsFullyOpaque() const + { + // check pixel format for alpha channel + return !(HasAlphaChannel() && mAlphaChannelUsed); + } + + /**@}*/ ///< End of generic features + + + /** \name PackedPixelsProfile + * Features that are active only if the Bitmap was created with a + * BITMAP_2D_PACKED_PIXELS profile. */ + /**@{*/ + + class PackedPixelsProfile + { + public: + + /** + * (Re-)Allocate pixel buffer for the Bitmap. Any previously allocated pixel buffer is deleted. + * Dali has ownership of the buffer, but its contents can be modified. + * Bitmap stores given size information about the image. + * @pre bufferWidth, bufferHeight have to be power of two + * @param[in] pixelFormat pixel format + * @param[in] width Image width in pixels + * @param[in] height Image height in pixels + * @param[in] bufferWidth Buffer width (stride) in pixels + * @param[in] bufferHeight Buffer height in pixels + * @return pixel buffer pointer + */ + virtual PixelBuffer* ReserveBuffer(Pixel::Format pixelFormat, + unsigned int width, + unsigned int height, + unsigned int bufferWidth = 0, + unsigned int bufferHeight = 0) = 0; + + /** + * Assign a pixel buffer. Any previously allocated pixel buffer is deleted. + * Dali has ownership of the buffer, but it iss allowable to modify its + * contents after it is assigned, but before it is used. + * Bitmap stores the provided size information about the image. + * + * The buffer must have been allocated with the C++ array new operator, not + * with malloc or as a local or static object. The precise form is as follows: + * + * PixelBuffer * buffer = new PixelBuffer[bufSize]; + * + * @pre bufferWidth, bufferHeight have to be power of two + * @param[in] pixelFormat pixel format + * @param[in] buffer the pixel buffer + * @param[in] bufferSize size of the pixel buffer + * @param[in] width Image width in pixels + * @param[in] height Image height in pixels + * @param[in] bufferWidth Buffer width (stride) in pixels + * @param[in] bufferHeight Buffer height in pixels + */ + virtual void AssignBuffer(Pixel::Format pixelFormat, + PixelBuffer* buffer, + std::size_t bufferSize, + unsigned int width, + unsigned int height, + unsigned int bufferWidth = 0, + unsigned int bufferHeight = 0) = 0; + /** + * Get the width of the buffer (stride) + * @return The width of the buffer in pixels + */ + virtual unsigned int GetBufferWidth() const = 0; + + /** + * Get the height of the buffer + * @return The height of the buffer in pixels + */ + virtual unsigned int GetBufferHeight() const = 0; + + /** + * Get the pixel buffer stride. + * @return The buffer stride (in bytes) if this is bitmap of non-compressed + * packed pixels for which a stride is meaningful or 0 otherwise. + */ + virtual unsigned int GetBufferStride() const = 0; + + /** + * Check the bitmap data and test whether it has any transparent pixels. + * This property can then be tested for with IsFullyOpaque(). + */ + virtual void TestForTransparency() = 0; + }; + + /** + * Get interface to features that are active only if the Bitmap was created + * with a BITMAP_2D_PACKED_PIXELS profile. */ + virtual const PackedPixelsProfile* GetPackedPixelsProfile() const { return 0; } + /** + * Get interface to features that are active only if the Bitmap was created + * with a BITMAP_2D_PACKED_PIXELS profile. */ + virtual PackedPixelsProfile* GetPackedPixelsProfile() { return 0; } + + /**@}*/ ///< End of packed pixel features. + + + /** \name CompressedProfile + * Features that only apply to opaque/compressed formats. */ + /**@{*/ + + class CompressedProfile + { + public: + /** + * (Re-)Allocate pixel buffer for the Bitmap. Any previously allocated pixel buffer + * is deleted. + * Dali has ownership of the buffer, and contents are opaque and immutable. + * Bitmap stores given size information about the image which the client is assumed + * to have retrieved from out-of-band image metadata. + * @param[in] pixelFormat pixel format + * @param[in] width Image width in pixels + * @param[in] height Image height in pixels + * @param[in] bufferSize Buffer size in bytes + * @return pixel buffer pointer + */ + virtual PixelBuffer* ReserveBufferOfSize( Pixel::Format pixelFormat, + const unsigned width, + const unsigned height, + const size_t numBytes ) = 0; + }; + + virtual const CompressedProfile* GetCompressedProfile() const { return 0; } + virtual CompressedProfile* GetCompressedProfile() { return 0; } + /**@}*/ + + + /** + * Inform the bitmap that its pixel buffer is no longer required and can be + * deleted to free up memory if the bitmap owns the buffer. + */ + void DiscardBuffer(); + + /** + * Check if the pixel buffer can be discarded + * @return true if the pixel buffer can be discarded + */ + bool IsDiscardable() const + { + return mDiscardable == ResourcePolicy::OWNED_DISCARD; + } + + /** + * Delete the pixel buffer data + */ + void DeletePixelBuffer(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~Bitmap(); + +protected: + + unsigned int mImageWidth; ///< Image width in pixels + unsigned int mImageHeight; ///< Image height in pixels + Pixel::Format mPixelFormat; ///< Pixel format + bool mHasAlphaChannel; ///< Whether the image has an alpha channel + bool mAlphaChannelUsed; ///< Whether the alpha channel is used in case the image owns one. + PixelBuffer* mData; ///< Raw pixel data + +private: + + ResourcePolicy::Discardable mDiscardable; ///< Should delete the buffer when discard buffer is called. + + Bitmap(const Bitmap& other); ///< defined private to prevent use + Bitmap& operator = (const Bitmap& other); ///< defined private to prevent use + + // Changes scope, should be at end of class + DALI_LOG_OBJECT_STRING_DECLARATION; +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_BITMAP_H__ diff --git a/dali/integration-api/context-notifier.h b/dali/integration-api/context-notifier.h new file mode 100644 index 0000000..348f292 --- /dev/null +++ b/dali/integration-api/context-notifier.h @@ -0,0 +1,55 @@ +#ifndef __DALI_INTEGRATION_CONTEXT_NOTIFIER_H__ +#define __DALI_INTEGRATION_CONTEXT_NOTIFIER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Dali +{ +namespace Integration +{ + +/** + * Interface to inform dali core of context loss and regain + */ +class ContextNotifierInterface +{ +public: + /** + * Notify that the GL context has been lost, e.g. during ReplaceSurface + * or Pause. + * + * Multi-threading note: this method should be called from the main thread + */ + virtual void NotifyContextLost() = 0; + + /** + * Notify that the GL context has been re-created, e.g. after ReplaceSurface + * or Context loss. + * + * In the case of ReplaceSurface, both ContextDestroyed() and ContextCreated() will have + * been called on the render thread before this is called on the event thread. + * + * Multi-threading note: this method should be called from the main thread + */ + virtual void NotifyContextRegained() = 0; +}; + +} // namespace Integration +} // namespace Dali + + +#endif // __DALI_INTEGRATION_CONTEXT_NOTIFICATION_H__ diff --git a/dali/integration-api/core.cpp b/dali/integration-api/core.cpp new file mode 100644 index 0000000..2648940 --- /dev/null +++ b/dali/integration-api/core.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Integration +{ + +Core* Core::New(RenderController& renderController, PlatformAbstraction& platformAbstraction, + GlAbstraction& glAbstraction, GlSyncAbstraction& glSyncAbstraction, GestureManager& gestureManager, ResourcePolicy::DataRetention policy ) +{ + Core* instance = new Core; + instance->mImpl = new Internal::Core( renderController, platformAbstraction, glAbstraction, glSyncAbstraction, gestureManager, policy ); + + return instance; +} + +Core::~Core() +{ + delete mImpl; +} + +ContextNotifierInterface* Core::GetContextNotifier() +{ + return mImpl->GetContextNotifier(); +} + +// @todo Rename to ResetGlContext +void Core::ContextCreated() +{ + mImpl->ContextCreated(); +} + +// @todo Replace with StopRendering that prevents RenderManager from rendering +// until we get ResetGLContext again, change ContextCreated to reset gpu buffer cache, +// gl texture id's +void Core::ContextDestroyed() +{ + mImpl->ContextDestroyed(); +} + +void Core::RecoverFromContextLoss() +{ + mImpl->RecoverFromContextLoss(); +} + +void Core::SurfaceResized(unsigned int width, unsigned int height) +{ + mImpl->SurfaceResized(width, height); +} + +void Core::SetDpi(unsigned int dpiHorizontal, unsigned int dpiVertical) +{ + mImpl->SetDpi(dpiHorizontal, dpiVertical); +} + +void Core::Suspend() +{ + mImpl->Suspend(); +} + +void Core::Resume() +{ + mImpl->Resume(); +} + +void Core::SceneCreated() +{ + mImpl->SceneCreated(); +} + +void Core::QueueEvent(const Event& event) +{ + mImpl->QueueEvent(event); +} + +void Core::ProcessEvents() +{ + mImpl->ProcessEvents(); +} + +void Core::UpdateTouchData(const TouchData& touch) +{ + mImpl->UpdateTouchData(touch); +} + +unsigned int Core::GetMaximumUpdateCount() const +{ + return mImpl->GetMaximumUpdateCount(); +} + +void Core::Update( float elapsedSeconds, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds, UpdateStatus& status ) +{ + mImpl->Update( elapsedSeconds, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds, status ); +} + +void Core::Render( RenderStatus& status ) +{ + mImpl->Render( status ); +} + +SystemOverlay& Core::GetSystemOverlay() +{ + return mImpl->GetSystemOverlay(); +} + +void Core::SetViewMode( ViewMode viewMode ) +{ + mImpl->SetViewMode( viewMode ); +} + +ViewMode Core::GetViewMode() const +{ + return mImpl->GetViewMode(); +} + +void Core::SetStereoBase( float stereoBase ) +{ + mImpl->SetStereoBase( stereoBase ); +} + +float Core::GetStereoBase() const +{ + return mImpl->GetStereoBase(); +} + +void Core::SetPixmapYInverted( bool yInverted ) +{ + mImpl->SetPixmapYInverted( yInverted ); +} + +Core::Core() +: mImpl( NULL ) +{ +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/core.h b/dali/integration-api/core.h new file mode 100644 index 0000000..018e3e9 --- /dev/null +++ b/dali/integration-api/core.h @@ -0,0 +1,437 @@ +#ifndef __DALI_INTEGRATION_CORE_H__ +#define __DALI_INTEGRATION_CORE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ +class Core; +} + +namespace Integration +{ + +class Core; +class GestureManager; +class GlAbstraction; +class GlSyncAbstraction; +class PlatformAbstraction; +class RenderController; +class SystemOverlay; +struct Event; +struct TouchData; + + +/** + * The reasons why further updates are required. + */ +namespace KeepUpdating +{ +enum Reasons +{ + NOT_REQUESTED = 0, ///< Zero means that no further updates are required + STAGE_KEEP_RENDERING = 1<<1, ///< - Stage::KeepRendering() is being used + ANIMATIONS_RUNNING = 1<<2, ///< - Animations are ongoing + LOADING_RESOURCES = 1<<3, ///< - Resources are being loaded + MONITORING_PERFORMANCE = 1<<4, ///< - The --enable-performance-monitor option is being used + RENDER_TASK_SYNC = 1<<5 ///< - A render task is waiting for render sync +}; +} + +/** + * The status of the Core::Update operation. + */ +class UpdateStatus +{ +public: + + /** + * Constructor + */ + UpdateStatus() + : keepUpdating(false), + needsNotification(false), + secondsFromLastFrame( 0.0f ) + { + } + +public: + + /** + * Query whether the Core has further frames to update & render e.g. when animations are ongoing. + * @return A bitmask of KeepUpdating values + */ + unsigned int KeepUpdating() { return keepUpdating; } + + /** + * Query whether the Core requires an Notification event. + * This should be sent through the same mechanism (e.g. event loop) as input events. + * @return True if an Notification event should be sent. + */ + bool NeedsNotification() { return needsNotification; } + + /** + * This method is provided so that FPS can be easily calculated with a release version + * of Core. + * @return the seconds from last frame as float + */ + float SecondsFromLastFrame() { return secondsFromLastFrame; } + +public: + + unsigned int keepUpdating; ///< A bitmask of KeepUpdating values + bool needsNotification; + float secondsFromLastFrame; +}; + +/** + * The status of the Core::Render operation. + */ +class RenderStatus +{ +public: + + /** + * Constructor + */ + RenderStatus() + : needsUpdate(false), + hasRendered(false) + { + } + + /** + * Set whether update needs to run following a render. + * This might be because render has sent messages to update, or it has + * some textures to upload over several frames. + */ + void SetNeedsUpdate(bool updateRequired) { needsUpdate = updateRequired; } + + /** + * Query the update status following rendering of a frame. + * @return true if update should run. + */ + bool NeedsUpdate() { return needsUpdate; } + + /** + * Set whether there were new render instructions. + */ + void SetHasRendered(bool rendered) { hasRendered = rendered; } + + /** + * Query whether there were new render instructions. + * @return true if there were render instructions + */ + bool HasRendered() { return hasRendered; } + +private: + + bool needsUpdate; + bool hasRendered; +}; + +/** + * Integration::Core is used for integration with the native windowing system. + * The following integration tasks must be completed: + * + * 1) Handle GL context creation, and notify the Core when this occurs. + * + * 2) Provide suspend/resume behaviour (see below for more details). + * + * 3) Run an event loop, for passing events to the Core e.g. multi-touch input events. + * Notification events should be sent after a frame is updated (see UpdateStatus). + * + * 4) Run a rendering loop, instructing the Core to render each frame. + * A separate rendering thread is recommended; see multi-threading options below. + * + * 5) Provide an implementation of the PlatformAbstraction interface, used to access platform specific services. + * + * 6) Provide an implementation of the GlAbstraction interface, used to access OpenGL services. + * + * 7) Provide an implementation of the GestureManager interface, used to register gestures provided by the platform. + * + * Suspend/Resume behaviour: + * + * The Core has no knowledge of the application lifecycle, but can be suspended. + * In the suspended state, input events will not be processed, and animations will not progress any further. + * The Core can still render in the suspended state; the same frame will be produced each time. + * + * Multi-threading notes: + * + * The Dali API methods are not reentrant. If you access the API from multiple threads simultaneously, then the results + * are undefined. This means that your application might segfault, or behave unpredictably. + * + * Rendering strategies: + * + * 1) Single-threaded. Call every Core method from the same thread. Event handling and rendering will occur in the same thread. + * This is not recommended, since processing input (slowly) can affect the smooth flow of animations. + * + * 2) Multi-threaded. The Core update & render operations can be processed in separate threads. + * See the method descriptions in Core to see which thread they should be called from. + * This is the recommended option, so that input processing will not affect the smoothness of animations. + * Note that the rendering thread must be halted, before destroying the GL context. + */ +class DALI_IMPORT_API Core +{ +public: + + /** + * Create a new Core. + * This object is used for integration with the native windowing system. + * @param[in] renderController The interface to an object which controls rendering. + * @param[in] platformAbstraction The interface providing platform specific services. + * @param[in] glAbstraction The interface providing OpenGL services. + * @param[in] glSyncAbstraction The interface providing OpenGL sync objects. + * @param[in] gestureManager The interface providing gesture manager services. + * @param[in] policy The data retention policy. This depends on application setting + * and platform support. Dali should honour this policy when deciding to discard + * intermediate resource data. + * @return A newly allocated Core. + */ + static Core* New(RenderController& renderController, + PlatformAbstraction& platformAbstraction, + GlAbstraction& glAbstraction, + GlSyncAbstraction& glSyncAbstraction, + GestureManager& gestureManager, + ResourcePolicy::DataRetention policy); + + /** + * Non-virtual destructor. Core is not intended as a base class. + */ + ~Core(); + + // GL Context Lifecycle + + /** + * Get the object that will notify the application/toolkit when context is lost/regained + */ + ContextNotifierInterface* GetContextNotifier(); + + /** + * Notify the Core that the GL context has been created. + * The context must be created before the Core can render. + * Multi-threading note: this method should be called from the rendering thread only + * @post The Core is aware of the GL context. + */ + void ContextCreated(); + + /** + * Notify the Core that that GL context is about to be destroyed. + * The Core will free any previously allocated GL resources. + * Multi-threading note: this method should be called from the rendering thread only + * @post The Core is unaware of any GL context. + */ + void ContextDestroyed(); + + /** + * Notify the Core that the GL context has been re-created, e.g. after ReplaceSurface + * or Context loss. + * + * In the case of ReplaceSurface, both ContextToBeDestroyed() and ContextCreated() will have + * been called on the render thread before this is called on the event thread. + * + * Multi-threading note: this method should be called from the main thread + */ + void RecoverFromContextLoss(); + + /** + * Notify the Core that the GL surface has been resized. + * This should be done at least once i.e. after the first call to ContextCreated(). + * The Core will use the surface size for camera calculations, and to set the GL viewport. + * Multi-threading note: this method should be called from the main thread + * @param[in] width The new surface width. + * @param[in] height The new surface height. + */ + void SurfaceResized(unsigned int width, unsigned int height); + + // Core setters + + /** + * Notify the Core about the display's DPI values. + * This should be done after the display is initialized and a Core instance is created. + * The Core will use the DPI values for font rendering. + * Multi-threading note: this method should be called from the main thread + * @param[in] dpiHorizontal Horizontal DPI value. + * @param[in] dpiVertical Vertical DPI value. + */ + void SetDpi(unsigned int dpiHorizontal, unsigned int dpiVertical); + + // Core Lifecycle + + /** + * Put Core into the suspended state. + * Any ongoing event processing will be cancelled, for example multi-touch sequences. + * The core expects the system has suspended us. Animation time will continue during the suspended + * state. + * Multi-threading note: this method should be called from the main thread + * @post The Core is in the suspended state. + */ + void Suspend(); + + /** + * Resume the Core from the suspended state. + * At the first update, the elapsed time passed to the animations will be equal to the time spent + * suspended. + * Multi-threading note: this method should be called from the main thread + * @post The Core is not in the suspended state. + */ + void Resume(); + + /** + * Notify Core that the scene has been created. + */ + void SceneCreated(); + + /** + * Queue an event with Core. + * Pre-processing of events may be beneficial e.g. a series of motion events could be throttled, so that only the last event is queued. + * Multi-threading note: this method should be called from the main thread. + * @param[in] event The new event. + */ + void QueueEvent(const Event& event); + + /** + * Process the events queued with QueueEvent(). + * Multi-threading note: this method should be called from the main thread. + * @pre ProcessEvents should not be called during ProcessEvents. + */ + void ProcessEvents(); + + /** + * Update external raw touch data in core. + * The core will use the touch data to generate Dali Touch/Gesture events for applications to use + * in the update thread. + * @param[in] touch The raw touch data. + * @note This can be called from either the event thread OR a dedicated touch thread. + */ + void UpdateTouchData(const TouchData& touch); + + /** + * The Core::Update() method prepares a frame for rendering. This method determines how many frames + * may be prepared, ahead of the rendering. + * For example if the maximum update count is 2, then Core::Update() for frame N+1 may be processed + * whilst frame N is being rendered. However the Core::Update() for frame N+2 may not be called, until + * the Core::Render() method for frame N has returned. + * @return The maximum update count (>= 1). + */ + unsigned int GetMaximumUpdateCount() const; + + /** + * Update the scene for the next frame. This method must be called before each frame is rendered. + * Multi-threading notes: this method should be called from a dedicated update-thread. + * The update for frame N+1 may be processed whilst frame N is being rendered. + * However the update-thread must wait until frame N has been rendered, before processing frame N+2. + * After this method returns, messages may be queued internally for the main thread. + * In order to process these messages, a notification is sent via the main thread's event loop. + * @param[in] elapsedSeconds Number of seconds since the last call + * @param[in] lastVSyncTimeMilliseconds The last vsync time in milliseconds + * @param[in] nextVSyncTimeMilliseconds The time of the next predicted VSync in milliseconds + * @param[out] status showing whether further updates are required. This also shows + * whether a Notification event should be sent, regardless of whether the multi-threading is used. + */ + void Update( float elapsedSeconds, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds, UpdateStatus& status ); + + /** + * Render the next frame. This method should be preceded by a call up Update. + * Multi-threading note: this method should be called from a dedicated rendering thread. + * @pre The GL context must have been created, and made current. + * @param[out] status showing whether update is required to run. + */ + void Render( RenderStatus& status ); + + // System-level overlay + + /** + * Use the SystemOverlay to draw content for system-level indicators, dialogs etc. + * @return The SystemOverlay. + */ + SystemOverlay& GetSystemOverlay(); + + /** + * Set the stereoscopic 3D view mode + * @param[in] viewMode The new view mode + */ + void SetViewMode( ViewMode viewMode ); + + /** + * Get the current view mode + * @return The current view mode + * @see SetViewMode. + */ + ViewMode GetViewMode() const; + + /** + * Set the stereo base (eye seperation) for stereoscopic 3D + * @param[in] stereoBase The stereo base (eye seperation) for stereoscopic 3D (mm) + */ + void SetStereoBase( float stereoBase ); + + /** + * Get the stereo base (eye seperation) for stereoscopic 3D + * @return The stereo base (eye seperation) for stereoscopic 3D (mm) + */ + float GetStereoBase() const; + + // Pixmap + + /** + * Set true if an pixmap image is y-inverted + */ + void SetPixmapYInverted( bool yInverted ); + +private: + + /** + * Private constructor; see also Core::New() + */ + Core(); + + /** + * Undefined copy-constructor. + * This avoids accidental calls to a default copy-constructor. + * @param[in] core A reference to the object to copy. + */ + Core(const Core& core); + + /** + * Undefined assignment operator. + * This avoids accidental calls to a default assignment operator. + * @param[in] rhs A reference to the object to copy. + */ + Core& operator=(const Core& rhs); + +private: + + Internal::Core* mImpl; + +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_CORE_H__ diff --git a/dali/integration-api/debug.cpp b/dali/integration-api/debug.cpp new file mode 100644 index 0000000..dd62a17 --- /dev/null +++ b/dali/integration-api/debug.cpp @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace // unnamed namespace +{ + +/** + * Generic function to print out any 2-Dimensional array + * @param[in] data pointer to the source data stored as float[rows][cols] + * @param[in] rows number of rows in 2D array + * @param[in] cols number of columns in 2D array + * @param[in] precision - the precision to write the float data. + * @param[in] indent - the indent level to use. + * @return string - the text representation of the 2D array + */ +std::string Array2DToString(const float *data, unsigned int rows, unsigned int cols, size_t precision, size_t indent) +{ + std::ostringstream oss; + + std::ios_base::fmtflags mask = oss.flags(); + mask &= ~std::ios_base::scientific; + mask |= std::ios_base::fixed; + + for(unsigned int rowIdx = 0; rowIdx < rows; rowIdx++) + { + oss << std::setw(indent) << std::setfill(' ') << ' ' << "[ "; + oss << std::setfill(' ') << std::setprecision(precision) << std::right << std::setiosflags(mask); + + for(unsigned int colIdx = 0; colIdx < cols; colIdx++) + { + oss << std::setw(precision + 6) << (*data++) << ' '; + } + + oss << ']' << std::endl; + } + + return oss.str(); +} + +} + +namespace Integration +{ + +namespace Log +{ + +__thread LogFunction gthreadLocalLogFunction = NULL; + +/* Forward declarations */ +std::string FormatToString(const char *format, ...); +std::string ArgListToString(const char *format, va_list args); + +void LogMessage(DebugPriority priority, const char* format, ...) +{ + if ( !gthreadLocalLogFunction ) + { + return; + } + + va_list arg; + va_start(arg, format); + std::string message = ArgListToString(format, arg); + va_end(arg); + + gthreadLocalLogFunction(priority,message); +} + +void InstallLogFunction(const LogFunction& logFunction) +{ + // TLS stores a pointer to an object. + // It needs to be allocated on the heap, because TLS will destroy it when the thread exits. + + gthreadLocalLogFunction = logFunction; +} + +void UninstallLogFunction() +{ + gthreadLocalLogFunction = NULL; +} + +#ifdef DEBUG_ENABLED + +/*Change false to true if trace is needed but don't commit to codeline*/ +Filter* Filter::gRender = Filter::New(Debug::Concise, false, "LOG_RENDER"); +Filter* Filter::gResource = Filter::New(Debug::Concise, false, "LOG_RESOURCE"); +Filter* Filter::gGLResource = Filter::New(Debug::Concise, false, "LOG_GL_RESOURCE"); +Filter* Filter::gObject = NULL; +Filter* Filter::gImage = Filter::New(Debug::Concise, false, "LOG_IMAGE"); +Filter* Filter::gModel = Filter::New(Debug::Concise, false, "LOG_MODEL"); +Filter* Filter::gNode = NULL; +Filter* Filter::gElement = NULL; +Filter* Filter::gActor = Filter::New(Debug::Concise, false, "LOG_ACTOR"); +Filter* Filter::gShader = Filter::New(Debug::Concise, false, "LOG_SHADER"); + +Filter::FilterList* Filter::GetActiveFilters() +{ + static Filter::FilterList* activeFilters = new FilterList; + return activeFilters; +} + +Filter* Filter::New( LogLevel level, bool trace, const char * environmentVariableName ) +{ + char * environmentVariableValue = getenv( environmentVariableName ); + if ( environmentVariableValue ) + { + unsigned int envLevel(0); + char envTraceString(0); + sscanf( environmentVariableValue, "%u,%c", &envLevel, &envTraceString ); + + if ( envLevel > Verbose ) + { + envLevel = Verbose; + } + level = LogLevel( envLevel ); + + // Just use 'f' and 't' as it's faster than doing full string comparisons + if ( envTraceString == 't' ) + { + trace = true; + } + else if ( envTraceString == 'f' ) + { + trace = false; + } + } + + Filter* filter = new Filter(level, trace); + filter->mNesting++; + GetActiveFilters()->push_back(filter); + return filter; +} + +/** + * Enable trace on all filters. + */ +void Filter::EnableGlobalTrace() +{ + for(FilterIter iter = GetActiveFilters()->begin(); iter != GetActiveFilters()->end(); iter++) + { + (*iter)->EnableTrace(); + } +} + +/** + * Disable trace on all filters. + */ +void Filter::DisableGlobalTrace() +{ + for(FilterIter iter = GetActiveFilters()->begin(); iter != GetActiveFilters()->end(); iter++) + { + (*iter)->DisableTrace(); + } +} + + +void Filter::Log(LogLevel level, const char* format, ...) +{ + if(level <= mLoggingLevel) + { + va_list arg; + va_start(arg, format); + + char *buffer = NULL; + int numChars = asprintf(&buffer, "%-*c %s", mNesting, ':', format); + if(numChars >= 0) // No error + { + std::string message = ArgListToString(buffer, arg); + LogMessage(DebugInfo, message.c_str()); + free(buffer); + } + va_end(arg); + } +} + + +TraceObj::TraceObj(Filter* filter, const char*format, ...) : mFilter(filter) +{ + if(mFilter && mFilter->IsTraceEnabled()) + { + va_list arg; + va_start(arg, format); + mMessage = ArgListToString(format, arg); + va_end(arg); + + LogMessage(DebugInfo, "Entr%-*c %s\n", mFilter->mNesting, ':', mMessage.c_str()); + ++mFilter->mNesting; + } +} + +TraceObj::~TraceObj() +{ + if(mFilter && mFilter->IsTraceEnabled()) + { + if (mFilter->mNesting) + { + --mFilter->mNesting; + } + LogMessage(DebugInfo, "Exit%-*c %s\n", mFilter->mNesting, ':', mMessage.c_str()); + } +} + +#endif // DEBUG_ENABLED + + +std::string ArgListToString(const char *format, va_list args) +{ + std::string str; // empty string + if(format != NULL) + { + char* buffer = NULL; + int err = vasprintf(&buffer, format, args); + if(err >= 0) // No error + { + str = buffer; + free(buffer); + } + } + return str; +} + +std::string FormatToString(const char *format, ...) +{ + va_list arg; + va_start(arg, format); + std::string s = ArgListToString(format, arg); + va_end(arg); + return s; +} + +std::string ColorToString(const Vector4& color) +{ + std::ostringstream oss; + oss << ""; + return oss.str(); +} + +std::string Vector4ToString(const Vector4& v, size_t precision, size_t indent) +{ + std::ostringstream oss; + oss << std::setw(indent+3) << std::setfill(' ') << std::setprecision(precision) << std::right; + oss << ""; + return oss.str(); +} + +std::string Vector3ToString(const Vector3& v, size_t precision, size_t indent) +{ + std::ostringstream oss; + oss << std::setw(indent+3) << std::setfill(' ') << std::setprecision(precision) << std::right << std::setiosflags(std::ios_base::fixed); + oss << ""; + return oss.str(); +} + +std::string QuaternionToString(const Quaternion& q, size_t precision, size_t indent) +{ + std::ostringstream oss; + + Vector3 axis; + Radian angle; + q.ToAxisAngle(axis, angle); + + oss << std::setw(indent+3) << std::setfill(' ') << std::setprecision(precision) << std::right; + oss << ""; + + return oss.str(); +} + +std::string Matrix3ToString(const Matrix3& m, size_t precision, size_t indent) +{ + return Array2DToString(m.AsFloat(), 3, 3, precision, indent); +} + +std::string MatrixToString(const Matrix& m, size_t precision, size_t indent) +{ + return Array2DToString(m.AsFloat(), 4, 4, precision, indent); +} + +} // namespace Log + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/debug.h b/dali/integration-api/debug.h new file mode 100644 index 0000000..8b17e38 --- /dev/null +++ b/dali/integration-api/debug.h @@ -0,0 +1,489 @@ +#ifndef __DALI_INTEGRATION_DEBUG_H__ +#define __DALI_INTEGRATION_DEBUG_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES +#include + +// Using Debug namespace alias shortens the log usage significantly +namespace Dali{namespace Integration{namespace Log{}}} +namespace Debug = Dali::Integration::Log; + +namespace Dali +{ + +struct Vector2; +struct Vector3; +struct Vector4; +class Matrix3; +class Matrix; +class Quaternion; + +namespace Integration +{ +namespace Log +{ + +enum DebugPriority +{ + DebugInfo, + DebugWarning, + DebugError +}; + +/** + * Used by logging macros to log a message along with function/class name + * @param level debug level + * @param format string format + */ +DALI_IMPORT_API void LogMessage(enum DebugPriority level,const char *format, ...); + +/** + * typedef for the logging function. + */ +typedef void (*LogFunction)(DebugPriority priority, std::string& message); + +/** + * A log function has to be installed for every thread that wants to use logging. + * This should be done by the adaptor. + * The log function can be different for each thread. + * @param logFunction the log function to install + * @param logOpts the log options to save in thread + */ +DALI_IMPORT_API void InstallLogFunction(const LogFunction& logFunction); + +/** + * A log function has to be uninstalled for every thread that wants to use logging. + * The log function can be different for each thread. + */ +DALI_IMPORT_API void UninstallLogFunction(); + +/******************************************************************************** + * Error/Warning macros. * + ********************************************************************************/ + +/** + * Provides unfiltered logging for global error level messages + */ +#define DALI_LOG_ERROR(format, args...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugError, "%s " format, __PRETTY_FUNCTION__, ## args) + +#define DALI_LOG_ERROR_NOFN(format, args...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugError, format, ## args) + +/** + * Provides unfiltered logging for fps monitor + */ +#define DALI_LOG_FPS(format, args...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ## args) + +/** + * Provides unfiltered logging for update status + */ +#define DALI_LOG_UPDATE_STATUS(format, args...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ## args) + +/** + * Provides unfiltered logging for render information + */ +#define DALI_LOG_RENDER_INFO(format, args...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ## args) + +#ifdef DEBUG_ENABLED + +/** + * Provides unfiltered logging for global warning level messages + */ +#define DALI_LOG_WARNING(format, args...) Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugWarning, "%s " format, __PRETTY_FUNCTION__, ## args) + + +#else // DEBUG_ENABLED + +// Don't warn on release build +#define DALI_LOG_WARNING(format, args...) + +#endif + +/******************************************************************************** + * Filter * + ********************************************************************************/ + +#ifdef DEBUG_ENABLED + +/** + * Enumeration of logging levels. + * Used by the filters to provide multiple log levels. + * In general, the higher the value, the more debug is available for that filter. + */ +enum LogLevel +{ + NoLogging = 0, + Concise = 1, + General = 2, + Verbose = 3 +}; + + +/** + * The Filter object is used by the DALI_LOG_INFO macro and others to determine if the logging + * should take place, and routes the logging via the platform abstraction's LogMessage. + * + * It provides a logging level. If this is set to zero, then DALI_LOG_INFO won't log anything. + * It provides the ability to turn tracing on or off. + * + */ +class DALI_IMPORT_API Filter +{ +public: + typedef std::list FilterList; + typedef std::list::iterator FilterIter; + +public: + + /** + * Test if the filter is enabled for the given logging level + * @param[in] level - the level to test. + * @return true if this level of logging is enabled. + */ + bool IsEnabledFor(LogLevel level) { return level != Debug::NoLogging && level <= mLoggingLevel;} + + /** + * Test if trace is enabled for this filter. + * @return true if trace is enabled; + */ + bool IsTraceEnabled() { return mTraceEnabled; } + + /** + * Enable tracing on this filter. + */ + void EnableTrace() { mTraceEnabled = true; } + + /** + * Disable tracing on this filter. + */ + void DisableTrace() { mTraceEnabled = false; } + + /** + * Set the log level for this filter. Setting to a higher value than Debug::General also + * enables General; + */ + void SetLogLevel(LogLevel level) { mLoggingLevel = level; } + + /** + * Perform the logging for this filter. + */ + void Log(LogLevel level, const char* format, ...); + + /** + * Create a new filter whose debug level and trace can be modified through the use of an + * environment variable. + * + * @param[in] level The default log level + * @param[in] trace The default trace level. If true, function tracing is on. + * @param[in] environmentVariableName The environment variable name used in order to change the + * log level or trace. + * + * @info To modify logg level/trace at runtime, you can should define your filter as shown below: + * + * @code + * Debug::Filter* filter = Debug::Filter::New( Debug::NoLogging, false, "FILTER_ENV" ); + * @endcode + * + * And to use it when running an executable: + * @code + * FILTER_ENV=3 dali-demo // LogLevel Verbose, Trace using default + * FILTER_ENV=1,true dali-demo // LogLevel Concise, Trace ON + * FILTER_ENV=2,false dali-demo // LogLevel General, Trace OFF + * FILTER_ENV=0,true dali-demo // LogLevel NoLogging, Trace ON + * @endcode + */ + static Filter* New(LogLevel level, bool trace, const char * environmentVariableName ); + + /** + * Enable trace on all filters. + */ + void EnableGlobalTrace(); + + /** + * Disable trace on all filters. + */ + void DisableGlobalTrace(); + +private: + + /** + * Constructor. + * @param[in] level - the highest log level. + * @param[in] trace - whether this filter allows tracing. + */ + Filter(LogLevel level, bool trace) : mLoggingLevel(level), mTraceEnabled(trace), mNesting(0) {} + + static FilterList* GetActiveFilters(); + +public: + // High level filters. If these filters are too broad for your current requirement, then + // you can add a filter to your own class or source file. If you do, use Filter::New() + // to tell this class about it. + + static Filter *gRender; + static Filter *gResource; + static Filter *gGLResource; + static Filter *gObject; + static Filter *gImage; + static Filter *gModel; + static Filter *gNode; + static Filter *gElement; + static Filter *gActor; + static Filter *gShader; + +private: + LogLevel mLoggingLevel; + bool mTraceEnabled; +public: + int mNesting; + +}; + + +#define DALI_LOG_FILTER_SET_LEVEL(filter, level) filter->SetLogLevel(level) +#define DALI_LOG_FILTER_ENABLE_TRACE(filter) filter->EnableTrace() +#define DALI_LOG_FILTER_DISABLE_TRACE(filter) filter->DisableTrace() + +#else + +#define DALI_LOG_FILTER_SET_LEVEL(filter, level) +#define DALI_LOG_FILTER_ENABLE_TRACE(filter) +#define DALI_LOG_FILTER_DISABLE_TRACE(filter) + +#endif + +/******************************************************************************** + * General Logging macros * + ********************************************************************************/ + +#ifdef DEBUG_ENABLED + +#define DALI_LOG_INFO(filter, level, format, args...) \ + if(filter && filter->IsEnabledFor(level)) { filter->Log(level, format, ## args); } + +#else // DEBUG_ENABLED + +#define DALI_LOG_INFO(filter, level, format, args...) + +#endif // DEBUG_ENABLED + + +/******************************************************************************** + * Trace Macros * + ********************************************************************************/ + +/* + * These macros allow the instrumentation of methods. These translate into calls + * to LogMessage(DebugInfo). + */ + +#ifdef DEBUG_ENABLED + +class DALI_IMPORT_API TraceObj +{ +public: + TraceObj(Filter* filter, const char* fmt, ...); + ~TraceObj(); + +public: + std::string mMessage; + Filter* mFilter; +}; + + +#define DALI_LOG_TRACE_METHOD_FMT(filter, format, args...) \ + Dali::Integration::Log::TraceObj debugTraceObj(filter, "%s: " format, __PRETTY_FUNCTION__, ## args) + +#define DALI_LOG_TRACE_METHOD(filter) \ + Dali::Integration::Log::TraceObj debugTraceObj(filter, __PRETTY_FUNCTION__) + + +#else // DEBUG_ENABLED + +#define DALI_LOG_TRACE_METHOD_FMT(filter, format, args...) +#define DALI_LOG_TRACE_METHOD(filter) + + +#endif + +/******************************************************************************** + * Extra object debug * + ********************************************************************************/ + +#ifdef DEBUG_ENABLED + +/** + * Warning, this macro changes the current scope, so should usually be put at the + * end of the class definition. + * + * Suggest that the value is usually set to the object's name. + * Warning - this will increase the size of the object for a debug build. + */ +#define DALI_LOG_OBJECT_STRING_DECLARATION \ +public: \ + std::string mDebugString; + +/** + * Print all the actor tree names + **/ +#define DALI_LOG_ACTOR_TREE( node ) { \ + std::stringstream branch; \ + Node* tempNode = node; \ + while( tempNode ) { \ + branch << "<" << tempNode->mDebugString << ">::"; \ + tempNode = tempNode->GetParent(); \ + } \ + DALI_LOG_ERROR_NOFN("Actor tree: %s\n", branch.str().c_str()); \ +} + +/** + * Allows one object to set another object's debug string + */ +#define DALI_LOG_SET_OBJECT_STRING(object, string) (object->mDebugString = string) + +/** + * Allows one object to set another object's std::string easily + */ +#define DALI_LOG_FMT_OBJECT_STRING(object, fmt, args...) (object->mDebugString = FormatToString(fmt, ## args)) + +/** + * Allows one object to get another object's debug string + */ +#define DALI_LOG_GET_OBJECT_STRING(object) (object->mDebugString) + +/** + * Get the C string (for use in formatted logging) + */ +#define DALI_LOG_GET_OBJECT_C_STR(object) (object->mDebugString.c_str()) + +/** + * Filtered logging of the object's debug string + */ +#define DALI_LOG_OBJECT(filter, object) DALI_LOG_INFO(filter, Debug::General, object->mDebugString) + + +#else // DEBUG_ENABLED + +#define DALI_LOG_OBJECT_STRING_DECLARATION +#define DALI_LOG_ACTOR_TREE(node) +#define DALI_LOG_SET_OBJECT_STRING(object, string) +#define DALI_LOG_FMT_OBJECT_STRING(object, fmt, args...) +#define DALI_LOG_GET_OBJECT_STRING(object) +#define DALI_LOG_GET_OBJECT_C_STR(object) "" +#define DALI_LOG_OBJECT(filter, object) + +#endif + +/******************************************************************************** + * Helper writers * + ********************************************************************************/ + +/** + * Helper method to translate a color to a string. + * @param[in] color - the color to translate + * @return string - the text representation of the color. + */ +DALI_IMPORT_API std::string ColorToString(const Vector4& color); + +/** + * Helper method to translate a vector4 to a string. + * @param[in] v - the vector + * @param[in] precision - the precision to write the float data. + * @param[in] indent - the indent level to use. + * @return string - the text representation of the vector. + */ +DALI_IMPORT_API std::string Vector4ToString(const Vector4& v, size_t precision=3, size_t indent=0); + +/** + * Helper method to translate a vector4 to a string. + * @param[in] v - the vector + * @param[in] precision - the precision to write the float data. + * @param[in] indent - the indent level to use. + * @return string - the text representation of the vector. + */ +DALI_IMPORT_API std::string Vector3ToString(const Vector3& v, size_t precision=3, size_t indent=0); + +/** + * Helper method to translate a quaternion to a string. + * @param[in] q the quaternion + * @param[in] precision - the precision to write the float data. + * @param[in] indent - the indent level to use. + * @return string - the text representation of the quaternion. + */ +DALI_IMPORT_API std::string QuaternionToString(const Quaternion& q, size_t precision=3, size_t indent=0); + +/** + * Helper method to translate a 3x3 matrix to a string. + * @param[in] m - the matrix + * @param[in] precision - the precision to write the float data. + * @param[in] indent - the indent level to use. + * @return string - the text representation of the vector. + */ +DALI_IMPORT_API std::string Matrix3ToString(const Matrix3& m, size_t precision=3, size_t indent=0); + +/** + * Helper method to translate a 4x4 matrix to a string. + * @param[in] m - the matrix + * @param[in] precision - the precision to write the float data. + * @param[in] indent - the indent level to use. + * @return string - the text representation of the vector. + */ +DALI_IMPORT_API std::string MatrixToString(const Matrix& m, size_t precision=3, size_t indent=0); + +#ifdef DEBUG_ENABLED + + +/** + * Filtered write of a matrix + */ +#define DALI_LOG_MATRIX(filter, matrix) DALI_LOG_INFO(filter, Debug::General, MatrixToString(matrix)) + +/** + * Filtered write of a vector + */ +#define DALI_LOG_VECTOR4(filter, vector) DALI_LOG_INFO(filter, Debug::General, Vector4ToString(vector)) + +/** + * Filtered write of a vector + */ +#define DALI_LOG_VECTOR3(filter, vector) DALI_LOG_INFO(filter, Debug::General, Vector3ToString(vector)) + +/** + * Filtered write of a color + */ +#define DALI_LOG_COLOR(filter, color) DALI_LOG_INFO(filter, Debug::General, ColorToString(color)) + +#else + +#define DALI_LOG_MATRIX(filter, matrix) +#define DALI_LOG_VECTOR4(filter,vector) +#define DALI_LOG_VECTOR3(filter,vector) +#define DALI_LOG_COLOR(filter, color) + +#endif + +}}} // Dali/Integration/Debug namespaces + + +#endif // __DALI_INTEGRATION_DEBUG_H__ diff --git a/dali/integration-api/events/event.cpp b/dali/integration-api/events/event.cpp new file mode 100644 index 0000000..381de18 --- /dev/null +++ b/dali/integration-api/events/event.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Integration +{ + +Event::~Event() +{ +} + +Event::Event(Type eventType) +: type(eventType) +{ +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/events/event.h b/dali/integration-api/events/event.h new file mode 100644 index 0000000..66bd92d --- /dev/null +++ b/dali/integration-api/events/event.h @@ -0,0 +1,74 @@ +#ifndef __DALI_INTEGRATION_EVENT_H__ +#define __DALI_INTEGRATION_EVENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +/** + * Base structure for events passed to Dali::Integration::Core::QueueEvent() + * An instance of this class cannot be created. + */ +struct Event +{ + // Destruction + + /** + * Virtual destructor. + */ + virtual ~Event(); + + // Enumerations + + enum Type + { + Touch, ///< A touch event, when the user interacts with the screen. + Key, ///< A key pressed event, from the virtual or external keyboard. + Gesture, ///< A Gesture event has been detected. + Wheel, ///< A wheel event, when the wheel is being rolled from an external mouse. + Hover ///< A hover event, when the user hovers above the screen. + }; + + // Data + + /** + * The event type. + */ + Type type; + +protected: // Constructors only to be used by derived structures. + + /** + * This constructor is only used by derived classes. + * @param[in] eventType The type of event. + */ + Event(Type eventType); +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_EVENT_H__ diff --git a/dali/integration-api/events/gesture-event.cpp b/dali/integration-api/events/gesture-event.cpp new file mode 100644 index 0000000..e3c2c50 --- /dev/null +++ b/dali/integration-api/events/gesture-event.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Integration +{ + +GestureEvent::~GestureEvent() +{ +} + +GestureEvent::GestureEvent(Gesture::Type gesture, Gesture::State gestureState) +: Event(Gesture), + gestureType(gesture), + state(gestureState), + time(0) +{ +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/events/gesture-event.h b/dali/integration-api/events/gesture-event.h new file mode 100644 index 0000000..8924474 --- /dev/null +++ b/dali/integration-api/events/gesture-event.h @@ -0,0 +1,75 @@ +#ifndef __DALI_INTEGRATION_GESTURE_EVENT_H__ +#define __DALI_INTEGRATION_GESTURE_EVENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +/** + * This is the abstract base structure for any gestures that the adaptor detects and wishes to send + * to the Core. + */ +struct GestureEvent : public Event +{ + // Destruction + + /** + * Virtual destructor. + */ + virtual ~GestureEvent(); + + // Data + + /** + * Gesture Type. + */ + Gesture::Type gestureType; + + /** + * The state of the gesture. + */ + Gesture::State state; + + /** + * The time the gesture took place. + */ + unsigned int time; + +protected: // Constructors only to be used by derived structures. + + /** + * This constructor is only used by derived classes. + * @param[in] gesture The type of gesture event. + * @param[in] gestureState The state of the gesture event. + */ + GestureEvent(Gesture::Type gesture, Gesture::State gestureState); +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_GESTURE_EVENT_H__ diff --git a/dali/integration-api/events/gesture-requests.h b/dali/integration-api/events/gesture-requests.h new file mode 100644 index 0000000..21b4490 --- /dev/null +++ b/dali/integration-api/events/gesture-requests.h @@ -0,0 +1,178 @@ +#ifndef __DALI_INTEGRATION_GESTURE_REQUESTS_H__ +#define __DALI_INTEGRATION_GESTURE_REQUESTS_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +/** + * This structure specifies the gesture type required (or no longer required) by Core. + */ +struct GestureRequest +{ + // Creation & Destruction + + /** + * Default Constructor + * @param[in] typeRequired The gesture type required + */ + GestureRequest(Gesture::Type typeRequired) : type(typeRequired) + { + } + + /** + * Virtual destructor + */ + virtual ~GestureRequest() + { + } + + // Data Members + + Gesture::Type type; ///< The type of gesture required. +}; + +/** + * This is used by Core when a pan gesture is required. + */ +struct PanGestureRequest : public GestureRequest +{ + // Creation & Destruction + + /** + * Default Constructor + */ + PanGestureRequest() + : GestureRequest(Gesture::Pan), + minTouches(1), + maxTouches(1) + { + } + + /** + * Virtual destructor + */ + virtual ~PanGestureRequest() + { + } + + // Data Members + + unsigned int minTouches; ///< The minimum number of touch points required for a pan gesture. + unsigned int maxTouches; ///< The maximum number of touch points required for a pan gesture. +}; + +/** + * This is used by Core when a pinch gesture is required. + */ +struct PinchGestureRequest : public GestureRequest +{ + // Creation & Destruction + + /** + * Default Constructor + */ + PinchGestureRequest() + : GestureRequest(Gesture::Pinch) + { + } + + /** + * Virtual destructor + */ + virtual ~PinchGestureRequest() + { + } +}; + +/** + * This is used by Core when a tap gesture is required. + */ +struct TapGestureRequest : public GestureRequest +{ + // Creation & Destruction + + /** + * Default Constructor + */ + TapGestureRequest() + : GestureRequest(Gesture::Tap), + minTaps(1), + maxTaps(1), + minTouches(1), + maxTouches(1) + { + } + + /** + * Virtual destructor + */ + virtual ~TapGestureRequest() + { + } + + // Data Members + + unsigned int minTaps; ///< The minimum number of taps required. + unsigned int maxTaps; ///< The maximum number of taps required. + unsigned int minTouches; ///< The minimum number of touch points required for our tap gesture. + unsigned int maxTouches; ///< The maximum number of touch points required for our tap gesture. +}; + +/** + * This is used by Core when a long press gesture is required. + */ +struct LongPressGestureRequest : public GestureRequest +{ + // Creation & Destruction + + /** + * Default Constructor + */ + LongPressGestureRequest() + : GestureRequest(Gesture::LongPress), + minTouches(1), + maxTouches(1) + { + } + + /** + * Virtual destructor + */ + virtual ~LongPressGestureRequest() + { + } + + // Data Members + + unsigned int minTouches; ///< The minimum number of touch points required for a long press gesture. + unsigned int maxTouches; ///< The maximum number of touch points required for a long press gesture. +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_GESTURE_REQUESTS_H__ diff --git a/dali/integration-api/events/hover-event-integ.cpp b/dali/integration-api/events/hover-event-integ.cpp new file mode 100644 index 0000000..4b846a8 --- /dev/null +++ b/dali/integration-api/events/hover-event-integ.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Integration +{ + +HoverEvent::HoverEvent() +: MultiPointEvent( Hover ) +{ +} + +HoverEvent::HoverEvent( unsigned long time ) +: MultiPointEvent( Hover, time ) +{ +} + +HoverEvent::~HoverEvent() +{ +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/events/hover-event-integ.h b/dali/integration-api/events/hover-event-integ.h new file mode 100644 index 0000000..7d7bffd --- /dev/null +++ b/dali/integration-api/events/hover-event-integ.h @@ -0,0 +1,62 @@ +#ifndef __DALI_INTEGRATION_HOVER_EVENT_H__ +#define __DALI_INTEGRATION_HOVER_EVENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +/** + * An instance of this structure should be used by the adaptor to send a hover event to Dali core. + * + * This class can contain one or many touch points. It also contains the time at which the + * event occurred. + */ +struct HoverEvent : public MultiPointEvent +{ + // Construction & Destruction + + /** + * Default Constructor + */ + HoverEvent(); + + /** + * Constructor + * @param[in] time The time the event occurred. + */ + HoverEvent(unsigned long time); + + /** + * Virtual destructor + */ + virtual ~HoverEvent(); +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_HOVER_EVENT_H__ diff --git a/dali/integration-api/events/key-event-integ.cpp b/dali/integration-api/events/key-event-integ.cpp new file mode 100644 index 0000000..80dc7cc --- /dev/null +++ b/dali/integration-api/events/key-event-integ.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Integration +{ + +KeyEvent::KeyEvent() +: Event(Key), + keyName(), + keyString(), + keyCode(-1), + keyModifier(0), + time(0), + state(KeyEvent::Down) +{ +} + +KeyEvent::KeyEvent(const std::string& keyName, const std::string& keyString, int keyCode, int keyModifier, unsigned long timeStamp, const State& keyState) +: Event(Key), + keyName(keyName), + keyString(keyString), + keyCode(keyCode), + keyModifier(keyModifier), + time(timeStamp), + state(keyState) +{ +} + +KeyEvent::~KeyEvent() +{ +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/events/key-event-integ.h b/dali/integration-api/events/key-event-integ.h new file mode 100644 index 0000000..26762ed --- /dev/null +++ b/dali/integration-api/events/key-event-integ.h @@ -0,0 +1,115 @@ +#ifndef __DALI_INTEGRATION_KEY_EVENT_H__ +#define __DALI_INTEGRATION_KEY_EVENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +/** + * An instance of this class should be used by the adaptor to send a key event to + * the Dali core. + * + */ +struct KeyEvent : public Event +{ + // Enumerations + // Specifies the state of the key event. + enum State + { + Down, /**< Key down */ + Up, /**< Key up */ + + Last + }; + + /** + * Default Constructor + */ + KeyEvent(); + + /** + * Constructor + * @param[in] keyName The name of the key pressed or command from the IMF, if later then the some following parameters will be needed. + * @param[in] keyString A string of input characters or key pressed + * @param[in] keyCode The unique key code for the key pressed. + * @param[in] keyModifier The key modifier for special keys like shift and alt + * @param[in] timeStamp The time (in ms) that the key event occurred. + * @param[in] keyState The state of the key event. + */ + KeyEvent(const std::string& keyName, + const std::string& keyString, + int keyCode, + int keyModifier, + unsigned long timeStamp, + const State& keyState); + + /** + * Virtual destructor + */ + virtual ~KeyEvent(); + + // Data + + /** + *@copydoc Dali::KeyEvent::keyPressedName + */ + std::string keyName; + + /** + *@copydoc Dali::KeyEvent::keyPressed + */ + std::string keyString; + + /** + * @copydoc Dali::KeyEvent::keyCode + */ + int keyCode; + + /** + *@copydoc Dali::KeyEvent::keyModifier + */ + int keyModifier; + + /** + *@copydoc Dali::KeyEvent::time + */ + unsigned long time; + + /** + * State of the key event. + * @see State + */ + State state; + +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_KEY_EVENT_H__ diff --git a/dali/integration-api/events/long-press-gesture-event.cpp b/dali/integration-api/events/long-press-gesture-event.cpp new file mode 100644 index 0000000..878276b --- /dev/null +++ b/dali/integration-api/events/long-press-gesture-event.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include "long-press-gesture-event.h" + +namespace Dali +{ + +namespace Integration +{ + +LongPressGestureEvent::LongPressGestureEvent( Gesture::State state ) +: GestureEvent( Gesture::LongPress, state ), + numberOfTouches(1) +{ +} + +LongPressGestureEvent::~LongPressGestureEvent() +{ +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/events/long-press-gesture-event.h b/dali/integration-api/events/long-press-gesture-event.h new file mode 100644 index 0000000..828896f --- /dev/null +++ b/dali/integration-api/events/long-press-gesture-event.h @@ -0,0 +1,75 @@ +#ifndef __DALI_INTEGRATION_LONG_PRESS_GESTURE_H__ +#define __DALI_INTEGRATION_LONG_PRESS_GESTURE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +/** + * If the adaptor detects a long press gesture, then it should create an instance of this structure and + * send it to the Core. + * + * This gesture can be in four states: + * - Possible: When the user first puts their finger down - Core needs to hit test the down point. + * - Started: When the long-press gesture is actually detected. + * - Finished: When the user finally lifts all touches. + * - Cancelled: If, after a down event, no long press is detected, or a system interruption. + */ +struct LongPressGestureEvent : public GestureEvent +{ + // Construction & Destruction + + /** + * Default Constructor + * @param[in] state Started, when we detect a long press. + * Finished, when all touches are finished. + */ + LongPressGestureEvent( Gesture::State state ); + + /** + * Virtual destructor + */ + virtual ~LongPressGestureEvent(); + + // Data + + /** + * @copydoc Dali::LongPressGesture::numberOfTouches + */ + unsigned int numberOfTouches; + + /** + * This is the point, in screen coordinates, where the long press occurred. + * If a multi-touch tap, then this should be the centroid of all the touch points. + */ + Vector2 point; +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_LONG_PRESS_GESTURE_H__ diff --git a/dali/integration-api/events/multi-point-event-integ.cpp b/dali/integration-api/events/multi-point-event-integ.cpp new file mode 100644 index 0000000..9320a45 --- /dev/null +++ b/dali/integration-api/events/multi-point-event-integ.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Integration +{ + +MultiPointEvent::MultiPointEvent( Type eventType ) +: Event( eventType ), + time( 0 ) +{ +} + +MultiPointEvent::MultiPointEvent( Type eventType, unsigned long time ) +: Event( eventType ), + time( time ) +{ +} + +MultiPointEvent::~MultiPointEvent() +{ +} + +void MultiPointEvent::AddPoint(const TouchPoint& point) +{ + points.push_back(point); +} + +TouchPoint& MultiPointEvent::GetPoint(unsigned int point) +{ + DALI_ASSERT_ALWAYS(point < points.size() && "MultiPointEvent: Point index out of bounds"); + return points[point]; +} + +const TouchPoint& MultiPointEvent::GetPoint(unsigned int point) const +{ + DALI_ASSERT_ALWAYS(point < points.size() && "MultiPointEvent: Point index out of bounds"); + return points[point]; +} + +unsigned int MultiPointEvent::GetPointCount() const +{ + return points.size(); +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/events/multi-point-event-integ.h b/dali/integration-api/events/multi-point-event-integ.h new file mode 100644 index 0000000..b5dd601 --- /dev/null +++ b/dali/integration-api/events/multi-point-event-integ.h @@ -0,0 +1,101 @@ +#ifndef __DALI_INTEGRATION_MULTI_POINT_EVENT_H__ +#define __DALI_INTEGRATION_MULTI_POINT_EVENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +/** + * An instance of this structure should be used by the adaptor to send a multi-point event to Dali core. + * + * This class can contain one or multiple touch points. It also contains the time at which the + * event occurred. + */ +struct MultiPointEvent : public Event +{ + // Construction & Destruction + +public: + /** + * Virtual destructor + */ + virtual ~MultiPointEvent(); + +protected: + /** + * Default Constructor + */ + MultiPointEvent(Type eventType); + + /** + * Constructor + * @param[in] time The time the event occurred. + */ + MultiPointEvent(Type eventType, unsigned long time); + +public: + // Data + + /** + * @copydoc Dali::MultiPointEvent::points + */ + std::vector points; + + /** + * @copydoc Dali::MultiPointEvent::time + */ + unsigned long time; + + // Convenience Methods + + /** + * Adds a point to the MultiPointEvent. + * @param[in] point The point to add. + */ + void AddPoint(const TouchPoint& point); + + /** + * @copydoc Dali::MultiPointEvent::GetPoint() + */ + TouchPoint& GetPoint(unsigned int point); + + /** + * @copydoc Dali::MultiPointEvent::GetPoint() + */ + const TouchPoint& GetPoint(unsigned int point) const; + + /** + * @copydoc Dali::MultiPointEvent::GetPointCount() const + */ + unsigned int GetPointCount() const; +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_MULTI_POINT_EVENT_H__ diff --git a/dali/integration-api/events/pan-gesture-event.cpp b/dali/integration-api/events/pan-gesture-event.cpp new file mode 100644 index 0000000..712a448 --- /dev/null +++ b/dali/integration-api/events/pan-gesture-event.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Integration +{ + + +PanGestureEvent::PanGestureEvent(Gesture::State state) +: GestureEvent(Gesture::Pan, state), + timeDelta(0), + numberOfTouches(1) +{ +} + +PanGestureEvent::~PanGestureEvent() +{ +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/events/pan-gesture-event.h b/dali/integration-api/events/pan-gesture-event.h new file mode 100644 index 0000000..401cf43 --- /dev/null +++ b/dali/integration-api/events/pan-gesture-event.h @@ -0,0 +1,87 @@ +#ifndef __DALI_INTEGRATION_PAN_GESTURE_EVENT_H__ +#define __DALI_INTEGRATION_PAN_GESTURE_EVENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +/** + * If the adaptor detects a pan gesture, then it should create an instance of this structure and + * send it to the Core. + * + * A Pan Gesture event should be in one of five states: + * - Possible: When the user first puts their finger down - Core needs to hit test the down point. + * - Started: If a pan is detected. + * - Continuing: If after a pan is detected, it continues. + * - Finished: If after a pan, the user lifts their finger(s). + * - Cancelled: If, after a down event, no pan is detected or a system interruption. + * + * A Started state will be ignored if a Possible state does not precede it. + * Likewise, a Continuing or Finished state will be ignored if a Started state does not precede it. + */ +struct PanGestureEvent: public GestureEvent +{ + // Construction & Destruction + + /** + * Default Constructor + * @param[in] state The state of the gesture + */ + PanGestureEvent(Gesture::State state); + + /** + * Virtual destructor + */ + virtual ~PanGestureEvent(); + + // Data + + /** + * The previous touch position of the primary touch point in screen coordinates. + */ + Vector2 previousPosition; + + /** + * This current touch position of the primary touch point in screen coordinates. + */ + Vector2 currentPosition; + + /** + * The time difference between the previous and latest touch motion events (in ms). + */ + unsigned long timeDelta; + + /** + * The total number of fingers touching the screen in a pan gesture. + */ + unsigned int numberOfTouches; +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_PAN_GESTURE_EVENT_H__ diff --git a/dali/integration-api/events/pinch-gesture-event.cpp b/dali/integration-api/events/pinch-gesture-event.cpp new file mode 100644 index 0000000..6129d41 --- /dev/null +++ b/dali/integration-api/events/pinch-gesture-event.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Integration +{ + +PinchGestureEvent::PinchGestureEvent(Gesture::State state) +: GestureEvent(Gesture::Pinch, state), + scale(0.0f), + speed(0.0f), + centerPoint() +{ +} + +PinchGestureEvent::~PinchGestureEvent() +{ +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/events/pinch-gesture-event.h b/dali/integration-api/events/pinch-gesture-event.h new file mode 100644 index 0000000..e05cd01 --- /dev/null +++ b/dali/integration-api/events/pinch-gesture-event.h @@ -0,0 +1,79 @@ +#ifndef __DALI_INTEGRATION_PINCH_GESTURE_EVENT_H__ +#define __DALI_INTEGRATION_PINCH_GESTURE_EVENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +/** + * If the adaptor detects a pinch gesture, then it should create an instance of this structure and + * send it to the Core. + * + * A Pinch Gesture event should be in one of four states: + * - Started: If a pinch is detected. + * - Continuing: If after a pinch is detected, it continues. + * - Finished: If after a pinch, the user lifts their finger(s). + * - Cancelled: If there is a system interruption. + */ +struct PinchGestureEvent : public GestureEvent +{ + // Construction & Destruction + + /** + * Default Constructor + * @param[in] state The state of the gesture + */ + PinchGestureEvent(Gesture::State state); + + /** + * Virtual destructor + */ + virtual ~PinchGestureEvent(); + + // Data + + /** + * @copydoc Dali::PinchGesture::scale + */ + float scale; + + /** + * @copydoc Dali::PinchGesture::speed + */ + float speed; + + /** + * The center point between the two touch points of the last touch event in the series of touch motion + * event producing this gesture. + */ + Vector2 centerPoint; +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_PINCH_GESTURE_EVENT_H__ diff --git a/dali/integration-api/events/tap-gesture-event.cpp b/dali/integration-api/events/tap-gesture-event.cpp new file mode 100644 index 0000000..09a1caa --- /dev/null +++ b/dali/integration-api/events/tap-gesture-event.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Integration +{ + +TapGestureEvent::TapGestureEvent( Gesture::State state ) +: GestureEvent(Gesture::Tap, state), + numberOfTaps(1), + numberOfTouches(1) +{ +} + +TapGestureEvent::~TapGestureEvent() +{ +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/events/tap-gesture-event.h b/dali/integration-api/events/tap-gesture-event.h new file mode 100644 index 0000000..b70fc94 --- /dev/null +++ b/dali/integration-api/events/tap-gesture-event.h @@ -0,0 +1,83 @@ +#ifndef __DALI_INTEGRATION_TAP_GESTURE_H__ +#define __DALI_INTEGRATION_TAP_GESTURE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +/** + * If the adaptor detects a tap gesture, then it should create an instance of this structure and + * send it to the Core. + * + * A Tap Gesture event should be in one of three states: + * - Possible: When the user first puts their finger down - Core needs to hit test the down point so + * that a tap (down and up quickly) is also on the same actor. + * - Started: If a tap is detected (No Finished state is expected). + * - Cancelled: If, after a down event, no tap is detected, or a system interruption. + * + * A Started state will be ignored if a Possible state does not precede it. + */ +struct TapGestureEvent : public GestureEvent +{ + // Construction & Destruction + + /** + * Default Constructor + * @param[in] state Possible, denotes down press; + * Started, of a tap occurs; and + * Cancelled, when tap does not occur. + */ + TapGestureEvent( Gesture::State state ); + + /** + * Virtual destructor + */ + virtual ~TapGestureEvent(); + + // Data + + /** + * @copydoc Dali::TapGesture::numberOfTaps + */ + unsigned int numberOfTaps; + + /** + * @copydoc Dali::TapGesture::numberOfTouches + */ + unsigned int numberOfTouches; + + /** + * This is the point, in screen coordinates, where the tap occurred. + * If a multi-touch tap, then this should be the centroid of all the touch points. + */ + Vector2 point; +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_TAP_GESTURE_H__ diff --git a/dali/integration-api/events/touch-data.h b/dali/integration-api/events/touch-data.h new file mode 100644 index 0000000..c19dc34 --- /dev/null +++ b/dali/integration-api/events/touch-data.h @@ -0,0 +1,105 @@ +#ifndef __DALI_INTEGRATION_TOUCH_DATA_H__ +#define __DALI_INTEGRATION_TOUCH_DATA_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include + +namespace Dali +{ + +namespace Integration +{ + +struct TouchData; + +typedef std::vector TouchDataContainer; +typedef TouchDataContainer::iterator TouchDataIter; + +/** + * TouchData structure + * represents the raw touch information from touch-screen for + * a single touch event e.g. + * + * "First finger touching down at pixel 123,456 on the screen (relative + * to top left corner of phone in portrait mode). at timestamp 125ms (from a reference + * timestamp e.g. phone boot being 0secs)." + * TouchData(Down, 125, 0, 123, 456) + * + * "Above finger moving to pixel 133,457, at timestamp 150ms" + * TouchData(Motion, 150, 0, 133, 457) + * + * "Additional finger touching down at pixel 50, 75, at timestamp 175ms" + * TouchData(Down, 175, 1, 50, 75) + * + * "First finger removing at pixel 143, 458, at timestamp 200ms" + * TouchData(Up, 200, 0, 143, 458) + * + * "Additional finger removing at pixel 51, 77, at timestamp 225ms" + * TouchData(Up, 225, 1, 51, 77) + * + * Note: Multiple incidents of touch data can be present at the same timestamp. + */ +struct TouchData +{ + + /** + * The Touch Type for this data. + */ + enum TouchType + { + Down, // Touch started + Up, // Touch ended + Motion // Touch is continuing + }; + + TouchData() + : type(Motion), + timestamp(0u), + index(0u), + x(0), + y(0) + { + + } + + TouchData(TouchType type, + unsigned int timestamp, + unsigned int index, + int x, + int y) + : type(type), + timestamp(timestamp), + index(index), + x(x), + y(y) + { + } + + TouchType type; + unsigned int timestamp; + unsigned int index; + int x; + int y; + +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_TOUCH_DATA_H__ diff --git a/dali/integration-api/events/touch-event-combiner.cpp b/dali/integration-api/events/touch-event-combiner.cpp new file mode 100644 index 0000000..b864e43 --- /dev/null +++ b/dali/integration-api/events/touch-event-combiner.cpp @@ -0,0 +1,384 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Integration +{ + +namespace +{ +const unsigned long DEFAULT_MINIMUM_MOTION_TIME( 1u ); +const Vector2 DEFAULT_MINIMUM_MOTION_DISTANCE( 1.0f, 1.0f ); +} // unnamed namespace + +struct TouchEventCombiner::PointInfo +{ + // Construction + + /** + * Constructor + * @param[in] touchPoint The point to add. + * @param[in] pointTime The time of the point event. + */ + PointInfo( const TouchPoint& touchPoint, unsigned long pointTime ) + : point( touchPoint ), + time( pointTime ) + { + } + + // Data + + TouchPoint point; ///< The point. + unsigned long time; ///< The time the point event took place. +}; + +TouchEventCombiner::TouchEventCombiner() +: mMinMotionTime( DEFAULT_MINIMUM_MOTION_TIME ), + mMinMotionDistance( DEFAULT_MINIMUM_MOTION_DISTANCE ) +{ +} + +TouchEventCombiner::TouchEventCombiner( unsigned long minMotionTime, float minMotionXDistance, float minMotionYDistance ) +: mMinMotionTime( minMotionTime ), + mMinMotionDistance( minMotionXDistance, minMotionYDistance ) +{ + DALI_ASSERT_ALWAYS( minMotionXDistance >= 0.0f && minMotionYDistance >= 0.0f && "Negative values not allowed\n" ); +} + +TouchEventCombiner::TouchEventCombiner( unsigned long minMotionTime, Vector2 minMotionDistance ) +: mMinMotionTime( minMotionTime ), + mMinMotionDistance( minMotionDistance ) +{ + DALI_ASSERT_ALWAYS( minMotionDistance.x >= 0.0f && minMotionDistance.y >= 0.0f && "Negative values not allowed\n" ); +} + +TouchEventCombiner::~TouchEventCombiner() +{ +} + +TouchEventCombiner::EventDispatchType TouchEventCombiner::GetNextTouchEvent( const TouchPoint& point, unsigned long time, TouchEvent& touchEvent, HoverEvent& hoverEvent ) +{ + TouchEventCombiner::EventDispatchType dispatchEvent( TouchEventCombiner::DispatchNone ); + + switch ( point.state ) + { + case TouchPoint::Started: + { + touchEvent.time = time; + bool addToContainer( true ); + + // Iterate through already stored touch points and add to TouchEvent + for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter ) + { + if ( iter->point.deviceId != point.deviceId ) + { + iter->point.state = TouchPoint::Stationary; + } + else + { + // System has sent us two down points for the same point ID, update our stored data to latest. + // We do not want to emit another down event for this Point Device ID. + + addToContainer = false; + iter->point = point; + iter->time = time; + } + touchEvent.AddPoint( iter->point ); + } + + // Add new touch point to the list and to the TouchEvent + if (addToContainer) + { + mPressedPoints.push_back( PointInfo( point, time ) ); + touchEvent.AddPoint( point ); + dispatchEvent = TouchEventCombiner::DispatchTouch; // Only dispatch touch event if just added to container + + // Check whether hover event was dispatched previously + if ( !mHoveredPoints.empty() ) + { + hoverEvent.time = time; + + PointInfoContainer::iterator match( mHoveredPoints.end() ); + for ( PointInfoContainer::iterator iter = mHoveredPoints.begin(), endIter = mHoveredPoints.end(); iter != endIter; ++iter ) + { + if ( point.deviceId == iter->point.deviceId ) + { + match = iter; + // Add new point to the HoverEvent + iter->point.state = TouchPoint::Finished; + hoverEvent.AddPoint( iter->point ); + } + else + { + iter->point.state = TouchPoint::Stationary; + hoverEvent.AddPoint( iter->point ); + } + } + + if ( match != mHoveredPoints.end() ) + { + mHoveredPoints.erase( match ); + dispatchEvent = TouchEventCombiner::DispatchBoth; // We should only dispatch hover events if the point was actually hovered in this window + } + } + } + + break; + } + + case TouchPoint::Finished: + { + touchEvent.time = time; + + // Find pressed touch point in local list (while also adding the stored points to the touchEvent) + PointInfoContainer::iterator match( mPressedPoints.end() ); + for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter ) + { + if ( point.deviceId == iter->point.deviceId ) + { + match = iter; + + // Add new point to the TouchEvent + touchEvent.AddPoint( point ); + } + else + { + iter->point.state = TouchPoint::Stationary; + touchEvent.AddPoint( iter->point ); + } + } + + if ( match != mPressedPoints.end() ) + { + mPressedPoints.erase( match ); + dispatchEvent = TouchEventCombiner::DispatchTouch; // We should only dispatch touch events if the point was actually pressed in this window + + // Iterate through already stored touch points for HoverEvent and delete them + for ( PointInfoContainer::iterator iter = mHoveredPoints.begin(), endIter = mHoveredPoints.end(); iter != endIter; ++iter ) + { + if ( iter->point.deviceId == point.deviceId ) + { + iter = mHoveredPoints.erase( iter ); + } + } + } + break; + } + + case TouchPoint::Motion: + { + bool fromNewDeviceId = false; + + if ( !mPressedPoints.empty() ) + { + touchEvent.time = time; + + bool ignore = false; + PointInfoContainer::iterator match = mPressedPoints.end(); + for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter ) + { + if ( point.deviceId == iter->point.deviceId ) + { + unsigned long timeDiff( time - iter->time ); + + if ( timeDiff < mMinMotionTime ) + { + // Motion event sent too soon after previous event so ignore + ignore = true; + break; + } + + if ( ( abs( point.screen.x - iter->point.screen.x ) < mMinMotionDistance.x ) && + ( abs( point.screen.y - iter->point.screen.y ) < mMinMotionDistance.y ) ) + { + // Not enough positional change from last event so ignore + ignore = true; + break; + } + + match = iter; + + // Add new touch point to the TouchEvent + touchEvent.AddPoint( point ); + } + else + { + iter->point.state = TouchPoint::Stationary; + touchEvent.AddPoint( iter->point ); + } + } + + if ( match != mPressedPoints.end() ) + { + PointInfo matchedPoint( point, time ); + std::swap( *match, matchedPoint ); + + dispatchEvent = TouchEventCombiner::DispatchTouch; // Dispatch touch event + } + else if(!ignore) + { + fromNewDeviceId = true; + } + } + + // Dispatch hover event if no previous down event received or the motion event comes from a new device ID + if(mPressedPoints.empty() || fromNewDeviceId) + { + hoverEvent.time = time; + + // Iterate through already stored touch points and add to HoverEvent + bool ignore = false; + PointInfoContainer::iterator match = mHoveredPoints.end(); + for ( PointInfoContainer::iterator iter = mHoveredPoints.begin(), endIter = mHoveredPoints.end(); iter != endIter; ++iter ) + { + if ( iter->point.deviceId == point.deviceId ) + { + unsigned long timeDiff( time - iter->time ); + + if ( timeDiff < mMinMotionTime ) + { + // Motion event sent too soon after previous event so ignore + ignore = true; + break; + } + + if ( ( abs( point.screen.x - iter->point.screen.x ) < mMinMotionDistance.x ) && + ( abs( point.screen.y - iter->point.screen.y ) < mMinMotionDistance.y ) ) + { + // Not enough positional change from last event so ignore + ignore = true; + break; + } + + match = iter; + + // Add new touch point to the HoverEvent + hoverEvent.AddPoint( point ); + } + else + { + iter->point.state = TouchPoint::Stationary; + hoverEvent.AddPoint( iter->point ); + } + } + + // Add new hover point to the list and to the HoverEvent + if ( !ignore ) // Only dispatch hover event when it should not be ignored + { + if( match == mHoveredPoints.end() ) + { + TouchPoint hoverPoint(point); + hoverPoint.state = TouchPoint::Started; // The first hover event received + mHoveredPoints.push_back( PointInfo( hoverPoint, time ) ); + hoverEvent.AddPoint( hoverPoint ); + } + else + { + PointInfo matchedPoint( point, time ); + std::swap( *match, matchedPoint ); + } + + if(dispatchEvent == TouchEventCombiner::DispatchTouch) + { + dispatchEvent = TouchEventCombiner::DispatchBoth; + } + else + { + dispatchEvent = TouchEventCombiner::DispatchHover; + } + } + } + break; + } + + case TouchPoint::Interrupted: + { + Reset(); + + // We should still tell core about the interruption. + touchEvent.AddPoint( point ); + hoverEvent.AddPoint( point ); + dispatchEvent = TouchEventCombiner::DispatchBoth; + break; + } + + default: + break; + } + + return dispatchEvent; +} + +void TouchEventCombiner::SetMinimumMotionTimeThreshold( unsigned long minTime ) +{ + mMinMotionTime = minTime; +} + +void TouchEventCombiner::SetMinimumMotionDistanceThreshold( float minDistance ) +{ + DALI_ASSERT_ALWAYS( minDistance >= 0.0f && "Negative values not allowed\n" ); + + mMinMotionDistance.x = mMinMotionDistance.y = minDistance; +} + +void TouchEventCombiner::SetMinimumMotionDistanceThreshold( float minXDistance, float minYDistance ) +{ + DALI_ASSERT_ALWAYS( minXDistance >= 0.0f && minYDistance >= 0.0f && "Negative values not allowed\n" ); + + mMinMotionDistance.x = minXDistance; + mMinMotionDistance.y = minYDistance; +} + +void TouchEventCombiner::SetMinimumMotionDistanceThreshold( Vector2 minDistance ) +{ + DALI_ASSERT_ALWAYS( minDistance.x >= 0.0f && minDistance.y >= 0.0f && "Negative values not allowed\n" ); + + mMinMotionDistance = minDistance; +} + +unsigned long TouchEventCombiner::GetMinimumMotionTimeThreshold() const +{ + return mMinMotionTime; +} + +Vector2 TouchEventCombiner::GetMinimumMotionDistanceThreshold() const +{ + return mMinMotionDistance; +} + +void TouchEventCombiner::Reset() +{ + mPressedPoints.clear(); + mHoveredPoints.clear(); +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/events/touch-event-combiner.h b/dali/integration-api/events/touch-event-combiner.h new file mode 100644 index 0000000..1c3b351 --- /dev/null +++ b/dali/integration-api/events/touch-event-combiner.h @@ -0,0 +1,174 @@ +#ifndef __DALI_INTEGRATION_TOUCH_EVENT_COMBINER_H__ +#define __DALI_INTEGRATION_TOUCH_EVENT_COMBINER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +struct TouchEvent; +struct HoverEvent; + +/** + * Dali::Integration::TouchEventCombiner is a utility class, an instance of which, should be created + * upon initialisation. It accepts single Point(s) containing information about a touch area and + * creates a TouchEvent and/or HoverEvent combining the latest event's information with previous TouchPoint(s). + * + * The created TouchEvent and/or HoverEvent can then be sent to the Dali Core as indicated by the GetNextTouchEvent() + * method. + * + * The TouchEventCombiner ensures that the following rules are also adhered to: + * - If two Down events are accidentally received, then the second one is ignored. + * - Motion events are not processed if a Down event does not precede it. + * - Motion event throttling is carried out to satisfy the minimum distance and time delta required. + * - If an interrupted event is received, then any stored Point history is cleared. + */ +class TouchEventCombiner +{ +public: + + // Enumerations + + enum EventDispatchType + { + DispatchTouch, ///< The touch event should be dispatched. + DispatchHover, ///< The hover event should be dispatched. + DispatchBoth, ///< Both touch event and hover event should be dispatched. + DispatchNone ///< Neither touch event nor hover event should be dispatched. + }; + + /** + * Default Constructor. + * @note The default minimum motion time is 1 ms between motion events and the default behaviour + * is to throttle X and Y movement by 1. + */ + TouchEventCombiner(); + + /** + * Construction with parameters. + * @param[in] minMotionTime The minimum time (in ms) that should occur between motion events. + * @param[in] minMotionXDistance The minimum distance a finger has to be moved between horizontal motion events. + * @param[in] minMotionYDistance The minimum distance a finger has to be moved between vertical motion events. + * @note Will assert if any of the parameters is negative. + */ + TouchEventCombiner( unsigned long minMotionTime, float minMotionXDistance, float minMotionYDistance ); + + /** + * Construction with parameters. + * @param[in] minMotionTime The minimum time (in ms) that should occur between motion events. + * @param[in] minMotionDistance A Vector2 representing the minimum distance a finger has to be moved between horizontal and vertical motion events. + * @note Will assert if any of the parameters is negative. + */ + TouchEventCombiner( unsigned long minMotionTime, Vector2 minMotionDistance ); + + /** + * Non virtual destructor + */ + ~TouchEventCombiner(); + +public: + + /** + * Allows the caller to pass in a point which is processed and the TouchEvent and/or HoverEvent is appropriately filled with the new, + * and previously stored Point information. + * + * @note If the thresholds set have not been passed, then false is returned and the TouchEvent and/or HoverEvent should not be sent + * to Dali Core. + * + * @param[in] point The new Point. + * @param[in] time The time the event occurred. + * @param[out] touchEvent This is populated with the correct Point(s) and time information. + * @param[out] hoverEvent This is populated with the correct Point(s) and time information. + * + * @return true if the point is beyond the different thresholds set thus, should be sent to core, false otherwise. + */ + EventDispatchType GetNextTouchEvent( const TouchPoint& point, unsigned long time, TouchEvent& touchEvent, HoverEvent& hoverEvent ); + + /** + * Sets the minimum time (in ms) that should occur between motion events. + * @param[in] minTime Minimum time between motion events. + */ + void SetMinimumMotionTimeThreshold( unsigned long minTime ); + + /** + * Sets the minimum distance a finger has to be moved (both X and Y) between motion events. + * @param[in] minDistance The minimum distance between motion events. + * @note Will assert if parameter is negative. + */ + void SetMinimumMotionDistanceThreshold( float minDistance ); + + /** + * Sets the minimum distance a finger has to be moved between motion events. + * @param[in] minXDistance The minimum X distance between motion events. + * @param[in] minYDistance The minimum Y distance between motion events. + * @note Use this method if the X and Y threshold required is different. + * @note Will assert if any of the parameters is negative. + */ + void SetMinimumMotionDistanceThreshold( float minXDistance, float minYDistance ); + + /** + * Sets the minimum distance a finger has to be moved between motion events. + * @param[in] minDistance A Vector2 representing the minimum X and Y thresholds. + * @note Use this method if the X and Y threshold required is different. + * @note Will assert if any of the parameters is negative. + */ + void SetMinimumMotionDistanceThreshold( Vector2 minDistance ); + + /** + * Retrieves the minimum motion time threshold. + * @return the minimum time threshold. + */ + unsigned long GetMinimumMotionTimeThreshold() const; + + /** + * Gets the minimum distance a finger has to be moved (both X and Y) between motion events. + * @return A Vector2 representing the x and y thresholds. + */ + Vector2 GetMinimumMotionDistanceThreshold() const; + + /** + * This resets any information contained by the TouchEventCombiner. + * This may be required if some platform event has occurred which makes it necessary to reset any + * TouchPoint information that the combiner may store. + */ + void Reset(); + +private: + + struct PointInfo; + typedef std::vector< PointInfo > PointInfoContainer; + PointInfoContainer mPressedPoints; ///< A container of touched point and time. + PointInfoContainer mHoveredPoints; ///< A container of hovered point and time. + + unsigned long mMinMotionTime; ///< The minimum time that should elapse before considering a new motion event. + Vector2 mMinMotionDistance; ///< The minimum distance in the X and Y direction before considering a new motion event. +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_TOUCH_EVENT_COMBINER_H__ diff --git a/dali/integration-api/events/touch-event-integ.cpp b/dali/integration-api/events/touch-event-integ.cpp new file mode 100644 index 0000000..ac44731 --- /dev/null +++ b/dali/integration-api/events/touch-event-integ.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Integration +{ + +TouchEvent::TouchEvent() +: MultiPointEvent( Touch ) +{ +} + +TouchEvent::TouchEvent( unsigned long time ) +: MultiPointEvent( Touch, time ) +{ +} + +TouchEvent::~TouchEvent() +{ +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/events/touch-event-integ.h b/dali/integration-api/events/touch-event-integ.h new file mode 100644 index 0000000..86752aa --- /dev/null +++ b/dali/integration-api/events/touch-event-integ.h @@ -0,0 +1,62 @@ +#ifndef __DALI_INTEGRATION_TOUCH_EVENT_H__ +#define __DALI_INTEGRATION_TOUCH_EVENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +/** + * An instance of this structure should be used by the adaptor to send a touch event to Dali core. + * + * This class can contain one or many touch points. It also contains the time at which the + * event occurred. + */ +struct TouchEvent : public MultiPointEvent +{ + // Construction & Destruction + + /** + * Default Constructor + */ + TouchEvent(); + + /** + * Constructor + * @param[in] time The time the event occurred. + */ + TouchEvent(unsigned long time); + + /** + * Virtual destructor + */ + virtual ~TouchEvent(); +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_TOUCH_EVENT_H__ diff --git a/dali/integration-api/events/wheel-event-integ.cpp b/dali/integration-api/events/wheel-event-integ.cpp new file mode 100644 index 0000000..3f99995 --- /dev/null +++ b/dali/integration-api/events/wheel-event-integ.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Integration +{ + +WheelEvent::WheelEvent() +: Event( Wheel ), + type( MOUSE_WHEEL ), + direction( 0 ), + modifiers( 0 ), + point( Vector2::ZERO ), + z( 0 ), + timeStamp( 0 ) +{ +} + +WheelEvent::WheelEvent( Type type, int direction, unsigned int modifiers, Vector2 point, int z, unsigned int timeStamp ) +: Event( Wheel ), + type( type ), + direction( direction ), + modifiers( modifiers ), + point( point ), + z( z ), + timeStamp( timeStamp ) +{ +} + +WheelEvent::~WheelEvent() +{ +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/events/wheel-event-integ.h b/dali/integration-api/events/wheel-event-integ.h new file mode 100644 index 0000000..5b0e0b2 --- /dev/null +++ b/dali/integration-api/events/wheel-event-integ.h @@ -0,0 +1,111 @@ +#ifndef __DALI_INTEGRATION_WHEEL_EVENT_H__ +#define __DALI_INTEGRATION_WHEEL_EVENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali DALI_IMPORT_API +{ + +namespace Integration +{ + +/** + * An instance of this class should be used by the adaptor to send a wheel event to + * the Dali core. + * + */ +struct WheelEvent : public Event +{ + // Enumerations + + /** + * @brief Specifies the type of the wheel event. + */ + enum Type + { + MOUSE_WHEEL, ///< Mouse wheel event + CUSTOM_WHEEL ///< Custom wheel event + }; + + /** + * Default Constructor + */ + WheelEvent(); + + /** + * Constructor + * @param[in] type The type of the wheel event + * @param[in] direction The direction of wheel rolling (0 = default vertical wheel, 1 = horizontal wheel) + * @param[in] modifiers modifier keys pressed during the event (such as shift, alt and control) + * @param[in] point The co-ordinates of the cursor relative to the top-left of the screen. + * @param[in] z The offset of rolling (positive value means roll down, and negative value means roll up) + * @param[in] timeStamp The time the wheel is being rolled. + */ + WheelEvent( Type type, int direction, unsigned int modifiers, Vector2 point, int z, unsigned int timeStamp ); + + /** + * Virtual destructor + */ + virtual ~WheelEvent(); + + // Data + + /** + *@copydoc Dali::WheelEvent::type + */ + Type type; + + /** + *@copydoc Dali::WheelEvent::direction + */ + int direction; + + /** + *@copydoc Dali::WheelEvent::modifiers + */ + unsigned int modifiers; + + /** + *@copydoc Dali::WheelEvent::point + */ + Vector2 point; + + /** + *@copydoc Dali::WheelEvent::z + */ + int z; + + /** + *@copydoc Dali::WheelEvent::timeStamp + */ + unsigned int timeStamp; + +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_WHEEL_EVENT_H__ diff --git a/dali/integration-api/file.list b/dali/integration-api/file.list new file mode 100644 index 0000000..ec83f66 --- /dev/null +++ b/dali/integration-api/file.list @@ -0,0 +1,61 @@ +# Add platform abstraction headers here + +platform_abstraction_src_files = \ + $(platform_abstraction_src_dir)/bitmap.cpp \ + $(platform_abstraction_src_dir)/core.cpp \ + $(platform_abstraction_src_dir)/image-data.cpp \ + $(platform_abstraction_src_dir)/debug.cpp \ + $(platform_abstraction_src_dir)/profiling.cpp \ + $(platform_abstraction_src_dir)/input-options.cpp \ + $(platform_abstraction_src_dir)/system-overlay.cpp \ + $(platform_abstraction_src_dir)/lockless-buffer.cpp \ + $(platform_abstraction_src_dir)/events/event.cpp \ + $(platform_abstraction_src_dir)/events/gesture-event.cpp \ + $(platform_abstraction_src_dir)/events/hover-event-integ.cpp \ + $(platform_abstraction_src_dir)/events/key-event-integ.cpp \ + $(platform_abstraction_src_dir)/events/long-press-gesture-event.cpp \ + $(platform_abstraction_src_dir)/events/wheel-event-integ.cpp \ + $(platform_abstraction_src_dir)/events/multi-point-event-integ.cpp \ + $(platform_abstraction_src_dir)/events/pan-gesture-event.cpp \ + $(platform_abstraction_src_dir)/events/pinch-gesture-event.cpp \ + $(platform_abstraction_src_dir)/events/tap-gesture-event.cpp \ + $(platform_abstraction_src_dir)/events/touch-event-combiner.cpp \ + $(platform_abstraction_src_dir)/events/touch-event-integ.cpp + +platform_abstraction_header_files = \ + $(platform_abstraction_src_dir)/core.h \ + $(platform_abstraction_src_dir)/context-notifier.h \ + $(platform_abstraction_src_dir)/debug.h \ + $(platform_abstraction_src_dir)/profiling.h \ + $(platform_abstraction_src_dir)/input-options.h \ + $(platform_abstraction_src_dir)/bitmap.h \ + $(platform_abstraction_src_dir)/resource-policies.h \ + $(platform_abstraction_src_dir)/image-data.h \ + $(platform_abstraction_src_dir)/resource-types.h \ + $(platform_abstraction_src_dir)/resource-request.h \ + $(platform_abstraction_src_dir)/resource-cache.h \ + $(platform_abstraction_src_dir)/resource-declarations.h \ + $(platform_abstraction_src_dir)/gl-abstraction.h \ + $(platform_abstraction_src_dir)/gl-defines.h \ + $(platform_abstraction_src_dir)/gl-sync-abstraction.h \ + $(platform_abstraction_src_dir)/gesture-manager.h \ + $(platform_abstraction_src_dir)/render-controller.h \ + $(platform_abstraction_src_dir)/platform-abstraction.h \ + $(platform_abstraction_src_dir)/system-overlay.h \ + $(platform_abstraction_src_dir)/lockless-buffer.h + +platform_abstraction_events_header_files = \ + $(platform_abstraction_src_dir)/events/event.h \ + $(platform_abstraction_src_dir)/events/gesture-event.h \ + $(platform_abstraction_src_dir)/events/gesture-requests.h \ + $(platform_abstraction_src_dir)/events/hover-event-integ.h \ + $(platform_abstraction_src_dir)/events/key-event-integ.h \ + $(platform_abstraction_src_dir)/events/long-press-gesture-event.h \ + $(platform_abstraction_src_dir)/events/wheel-event-integ.h \ + $(platform_abstraction_src_dir)/events/multi-point-event-integ.h \ + $(platform_abstraction_src_dir)/events/pan-gesture-event.h \ + $(platform_abstraction_src_dir)/events/pinch-gesture-event.h \ + $(platform_abstraction_src_dir)/events/tap-gesture-event.h \ + $(platform_abstraction_src_dir)/events/touch-data.h \ + $(platform_abstraction_src_dir)/events/touch-event-combiner.h \ + $(platform_abstraction_src_dir)/events/touch-event-integ.h diff --git a/dali/integration-api/gesture-manager.h b/dali/integration-api/gesture-manager.h new file mode 100644 index 0000000..ba32f03 --- /dev/null +++ b/dali/integration-api/gesture-manager.h @@ -0,0 +1,66 @@ +#ifndef __DALI_INTEGRATION_GESTURE_MANAGER_H__ +#define __DALI_INTEGRATION_GESTURE_MANAGER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Integration +{ + +/** + * GestureManager is an abstract interface, used by Dali to register and unregister gestures provided + * by the adaptor. A concrete implementation must be created for each adaptor, and provided when creating + * the Dali::Integration::Core object. + */ +class DALI_IMPORT_API GestureManager +{ +public: + + /** + * Called by Dali to enable the adaptor to start detecting the required gesture type. + * @param[in] request The required gesture and details. + */ + virtual void Register(const GestureRequest& request) = 0; + + /** + * Called by Dali to inform the adaptor that it no longer requires a GestureEvent when the state + * gesture type is detected. + * @param[in] request The gesture that is no longer required. + */ + virtual void Unregister(const GestureRequest& request) = 0; + + /** + * Called by Dali to inform the adaptor that the detection parameters of a previously requested + * gesture have now changed. + * @param[in] request The gesture and updated details. + */ + virtual void Update(const GestureRequest& request) = 0; + +}; // class GestureManager + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_GESTURE_MANAGER_H__ diff --git a/dali/integration-api/gl-abstraction.h b/dali/integration-api/gl-abstraction.h new file mode 100644 index 0000000..a5d81f3 --- /dev/null +++ b/dali/integration-api/gl-abstraction.h @@ -0,0 +1,381 @@ +#ifndef __DALI_INTEGRATION_GL_ABSTRACTION_H__ +#define __DALI_INTEGRATION_GL_ABSTRACTION_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +/* + * This file is based on gl3.h, the following licence is included for conformance. + */ +/* +** Copyright (c) 2007-2012 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + + +/* OpenGL ES 3.0 */ +struct __GLsync; + +namespace Dali +{ + +/** + * These types are equivalent to those in the GLES2 API. + * Dali objects should only access GL indirectly, through the Context API. + */ + +/* OpenGL ES 2.0 */ + +typedef void GLvoid; +typedef char GLchar; +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef int8_t GLbyte; +typedef short GLshort; +typedef int GLint; +typedef int GLsizei; +typedef uint8_t GLubyte; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef float GLfloat; +typedef float GLclampf; +typedef int GLfixed; +typedef signed long int GLintptr; +typedef signed long int GLsizeiptr; + +/* OpenGL ES 3.0 */ + +typedef unsigned short GLhalf; +typedef int64_t GLint64; +typedef uint64_t GLuint64; +typedef __GLsync* GLsync; + +namespace Integration +{ + +/** + * GlAbstraction is an abstract interface, used to access OpenGL services. + * A concrete implementation must be created for each platform, and provided when creating the + * Dali::Integration::Core object. + */ +class GlAbstraction +{ +protected: + + /** + * Virtual protected destructor, no deletion through this interface + */ + virtual ~GlAbstraction() {} + +public: + /** + * Invoked by Render thread before Core::Render. + */ + virtual void PreRender() = 0; + + /** + * Invoked by Render thread after Core::Render + * Inform the gl implementation that the rendering in this frame has finished, + * and how much time was spent. + */ + virtual void PostRender() = 0; + + /** + * The number of texture units an implementation supports is implementation dependent, but must be at least 8. + */ + static const unsigned int MIN_TEXTURE_UNIT_LIMIT = 8; + + /* OpenGL ES 2.0 */ + + virtual void ActiveTexture (GLenum texture) = 0; + virtual void AttachShader (GLuint program, GLuint shader) = 0; + virtual void BindAttribLocation (GLuint program, GLuint index, const char* name) = 0; + virtual void BindBuffer (GLenum target, GLuint buffer) = 0; + virtual void BindFramebuffer (GLenum target, GLuint framebuffer) = 0; + virtual void BindRenderbuffer (GLenum target, GLuint renderbuffer) = 0; + virtual void BindTexture (GLenum target, GLuint texture) = 0; + virtual void BlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) = 0; + virtual void BlendEquation ( GLenum mode ) = 0; + virtual void BlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha) = 0; + virtual void BlendFunc (GLenum sfactor, GLenum dfactor) = 0; + virtual void BlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) = 0; + virtual void BufferData (GLenum target, GLsizeiptr size, const void* data, GLenum usage) = 0; + virtual void BufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void* data) = 0; + virtual GLenum CheckFramebufferStatus (GLenum target) = 0; + virtual void Clear (GLbitfield mask) = 0; + virtual void ClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) = 0; + virtual void ClearDepthf (GLclampf depth) = 0; + virtual void ClearStencil (GLint s) = 0; + virtual void ColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) = 0; + virtual void CompileShader (GLuint shader) = 0; + virtual void CompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) = 0; + virtual void CompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) = 0; + virtual void CopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) = 0; + virtual void CopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) = 0; + virtual GLuint CreateProgram (void) = 0; + virtual GLuint CreateShader (GLenum type) = 0; + virtual void CullFace (GLenum mode) = 0; + virtual void DeleteBuffers (GLsizei n, const GLuint* buffers) = 0; + virtual void DeleteFramebuffers (GLsizei n, const GLuint* framebuffers) = 0; + virtual void DeleteProgram (GLuint program) = 0; + virtual void DeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers) = 0; + virtual void DeleteShader (GLuint shader) = 0; + virtual void DeleteTextures (GLsizei n, const GLuint* textures) = 0; + virtual void DepthFunc (GLenum func) = 0; + virtual void DepthMask (GLboolean flag) = 0; + virtual void DepthRangef (GLclampf zNear, GLclampf zFar) = 0; + virtual void DetachShader (GLuint program, GLuint shader) = 0; + virtual void Disable (GLenum cap) = 0; + virtual void DisableVertexAttribArray (GLuint index) = 0; + virtual void DrawArrays (GLenum mode, GLint first, GLsizei count) = 0; + virtual void DrawElements (GLenum mode, GLsizei count, GLenum type, const void* indices) = 0; + virtual void Enable (GLenum cap) = 0; + virtual void EnableVertexAttribArray (GLuint index) = 0; + virtual void Finish (void) = 0; + virtual void Flush (void) = 0; + virtual void FramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) = 0; + virtual void FramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) = 0; + virtual void FrontFace (GLenum mode) = 0; + virtual void GenBuffers (GLsizei n, GLuint* buffers) = 0; + virtual void GenerateMipmap (GLenum target) = 0; + virtual void GenFramebuffers (GLsizei n, GLuint* framebuffers) = 0; + virtual void GenRenderbuffers (GLsizei n, GLuint* renderbuffers) = 0; + virtual void GenTextures (GLsizei n, GLuint* textures) = 0; + virtual void GetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) = 0; + virtual void GetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) = 0; + virtual void GetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) = 0; + virtual GLint GetAttribLocation (GLuint program, const char* name) = 0; + virtual void GetBooleanv (GLenum pname, GLboolean* params) = 0; + virtual void GetBufferParameteriv (GLenum target, GLenum pname, GLint* params) = 0; + virtual GLenum GetError (void) = 0; + virtual void GetFloatv (GLenum pname, GLfloat* params) = 0; + virtual void GetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params) = 0; + virtual void GetIntegerv (GLenum pname, GLint* params) = 0; + virtual void GetProgramiv (GLuint program, GLenum pname, GLint* params) = 0; + virtual void GetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) = 0; + virtual void GetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params) = 0; + virtual void GetShaderiv (GLuint shader, GLenum pname, GLint* params) = 0; + virtual void GetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) = 0; + virtual void GetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) = 0; + virtual void GetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, char* source) = 0; + virtual const GLubyte* GetString (GLenum name) = 0; + virtual void GetTexParameterfv (GLenum target, GLenum pname, GLfloat* params) = 0; + virtual void GetTexParameteriv (GLenum target, GLenum pname, GLint* params) = 0; + virtual void GetUniformfv (GLuint program, GLint location, GLfloat* params) = 0; + virtual void GetUniformiv (GLuint program, GLint location, GLint* params) = 0; + virtual GLint GetUniformLocation (GLuint program, const char* name) = 0; + virtual void GetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params) = 0; + virtual void GetVertexAttribiv (GLuint index, GLenum pname, GLint* params) = 0; + virtual void GetVertexAttribPointerv (GLuint index, GLenum pname, void** pointer) = 0; + virtual void Hint (GLenum target, GLenum mode) = 0; + virtual GLboolean IsBuffer (GLuint buffer) = 0; + virtual GLboolean IsEnabled (GLenum cap) = 0; + virtual GLboolean IsFramebuffer (GLuint framebuffer) = 0; + virtual GLboolean IsProgram (GLuint program) = 0; + virtual GLboolean IsRenderbuffer (GLuint renderbuffer) = 0; + virtual GLboolean IsShader (GLuint shader) = 0; + virtual GLboolean IsTexture (GLuint texture) = 0; + virtual void LineWidth (GLfloat width) = 0; + virtual void LinkProgram (GLuint program) = 0; + virtual void PixelStorei (GLenum pname, GLint param) = 0; + virtual void PolygonOffset (GLfloat factor, GLfloat units) = 0; + virtual void ReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) = 0; + virtual void ReleaseShaderCompiler (void) = 0; + virtual void RenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height) = 0; + virtual void SampleCoverage (GLclampf value, GLboolean invert) = 0; + virtual void Scissor (GLint x, GLint y, GLsizei width, GLsizei height) = 0; + virtual void ShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length) = 0; + virtual void ShaderSource (GLuint shader, GLsizei count, const char** string, const GLint* length) = 0; + virtual void StencilFunc (GLenum func, GLint ref, GLuint mask) = 0; + virtual void StencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask) = 0; + virtual void StencilMask (GLuint mask) = 0; + virtual void StencilMaskSeparate (GLenum face, GLuint mask) = 0; + virtual void StencilOp (GLenum fail, GLenum zfail, GLenum zpass) = 0; + virtual void StencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) = 0; + virtual void TexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) = 0; + virtual void TexParameterf (GLenum target, GLenum pname, GLfloat param) = 0; + virtual void TexParameterfv (GLenum target, GLenum pname, const GLfloat* params) = 0; + virtual void TexParameteri (GLenum target, GLenum pname, GLint param) = 0; + virtual void TexParameteriv (GLenum target, GLenum pname, const GLint* params) = 0; + virtual void TexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) = 0; + virtual void Uniform1f (GLint location, GLfloat x) = 0; + virtual void Uniform1fv (GLint location, GLsizei count, const GLfloat* v) = 0; + virtual void Uniform1i (GLint location, GLint x) = 0; + virtual void Uniform1iv (GLint location, GLsizei count, const GLint* v) = 0; + virtual void Uniform2f (GLint location, GLfloat x, GLfloat y) = 0; + virtual void Uniform2fv (GLint location, GLsizei count, const GLfloat* v) = 0; + virtual void Uniform2i (GLint location, GLint x, GLint y) = 0; + virtual void Uniform2iv (GLint location, GLsizei count, const GLint* v) = 0; + virtual void Uniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) = 0; + virtual void Uniform3fv (GLint location, GLsizei count, const GLfloat* v) = 0; + virtual void Uniform3i (GLint location, GLint x, GLint y, GLint z) = 0; + virtual void Uniform3iv (GLint location, GLsizei count, const GLint* v) = 0; + virtual void Uniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) = 0; + virtual void Uniform4fv (GLint location, GLsizei count, const GLfloat* v) = 0; + virtual void Uniform4i (GLint location, GLint x, GLint y, GLint z, GLint w) = 0; + virtual void Uniform4iv (GLint location, GLsizei count, const GLint* v) = 0; + virtual void UniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0; + virtual void UniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0; + virtual void UniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0; + virtual void UseProgram (GLuint program) = 0; + virtual void ValidateProgram (GLuint program) = 0; + virtual void VertexAttrib1f (GLuint indx, GLfloat x) = 0; + virtual void VertexAttrib1fv (GLuint indx, const GLfloat* values) = 0; + virtual void VertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) = 0; + virtual void VertexAttrib2fv (GLuint indx, const GLfloat* values) = 0; + virtual void VertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) = 0; + virtual void VertexAttrib3fv (GLuint indx, const GLfloat* values) = 0; + virtual void VertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) = 0; + virtual void VertexAttrib4fv (GLuint indx, const GLfloat* values) = 0; + virtual void VertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) = 0; + virtual void Viewport (GLint x, GLint y, GLsizei width, GLsizei height) = 0; + + /* OpenGL ES 3.0 */ + + virtual void ReadBuffer (GLenum mode) = 0; + virtual void DrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices) = 0; + virtual void TexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) = 0; + virtual void TexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) = 0; + virtual void CopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) = 0; + virtual void CompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) = 0; + virtual void CompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) = 0; + virtual void GenQueries (GLsizei n, GLuint* ids) = 0; + virtual void DeleteQueries (GLsizei n, const GLuint* ids) = 0; + virtual GLboolean IsQuery (GLuint id) = 0; + virtual void BeginQuery (GLenum target, GLuint id) = 0; + virtual void EndQuery (GLenum target) = 0; + virtual void GetQueryiv (GLenum target, GLenum pname, GLint* params) = 0; + virtual void GetQueryObjectuiv (GLuint id, GLenum pname, GLuint* params) = 0; + virtual GLboolean UnmapBuffer (GLenum target) = 0; + virtual void GetBufferPointerv (GLenum target, GLenum pname, GLvoid** params) = 0; + virtual void DrawBuffers (GLsizei n, const GLenum* bufs) = 0; + virtual void UniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0; + virtual void UniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0; + virtual void UniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0; + virtual void UniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0; + virtual void UniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0; + virtual void UniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0; + virtual void BlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) = 0; + virtual void RenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) = 0; + virtual void FramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) = 0; + virtual GLvoid* MapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) = 0; + virtual void FlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length) = 0; + virtual void BindVertexArray (GLuint array) = 0; + virtual void DeleteVertexArrays (GLsizei n, const GLuint* arrays) = 0; + virtual void GenVertexArrays (GLsizei n, GLuint* arrays) = 0; + virtual GLboolean IsVertexArray (GLuint array) = 0; + virtual void GetIntegeri_v (GLenum target, GLuint index, GLint* data) = 0; + virtual void BeginTransformFeedback (GLenum primitiveMode) = 0; + virtual void EndTransformFeedback (void) = 0; + virtual void BindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) = 0; + virtual void BindBufferBase (GLenum target, GLuint index, GLuint buffer) = 0; + virtual void TransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) = 0; + virtual void GetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) = 0; + virtual void VertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) = 0; + virtual void GetVertexAttribIiv (GLuint index, GLenum pname, GLint* params) = 0; + virtual void GetVertexAttribIuiv (GLuint index, GLenum pname, GLuint* params) = 0; + virtual void VertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w) = 0; + virtual void VertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) = 0; + virtual void VertexAttribI4iv (GLuint index, const GLint* v) = 0; + virtual void VertexAttribI4uiv (GLuint index, const GLuint* v) = 0; + virtual void GetUniformuiv (GLuint program, GLint location, GLuint* params) = 0; + virtual GLint GetFragDataLocation (GLuint program, const GLchar *name) = 0; + virtual void Uniform1ui (GLint location, GLuint v0) = 0; + virtual void Uniform2ui (GLint location, GLuint v0, GLuint v1) = 0; + virtual void Uniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2) = 0; + virtual void Uniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) = 0; + virtual void Uniform1uiv (GLint location, GLsizei count, const GLuint* value) = 0; + virtual void Uniform2uiv (GLint location, GLsizei count, const GLuint* value) = 0; + virtual void Uniform3uiv (GLint location, GLsizei count, const GLuint* value) = 0; + virtual void Uniform4uiv (GLint location, GLsizei count, const GLuint* value) = 0; + virtual void ClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint* value) = 0; + virtual void ClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint* value) = 0; + virtual void ClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat* value) = 0; + virtual void ClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0; + virtual const GLubyte* GetStringi (GLenum name, GLuint index) = 0; + virtual void CopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) = 0; + virtual void GetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) = 0; + virtual void GetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) = 0; + virtual GLuint GetUniformBlockIndex (GLuint program, const GLchar* uniformBlockName) = 0; + virtual void GetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) = 0; + virtual void GetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) = 0; + virtual void UniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0; + virtual void DrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) = 0; + virtual void DrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) = 0; + virtual GLsync FenceSync (GLenum condition, GLbitfield flags) = 0; + virtual GLboolean IsSync (GLsync sync) = 0; + virtual void DeleteSync (GLsync sync) = 0; + virtual GLenum ClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout) = 0; + virtual void WaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout) = 0; + virtual void GetInteger64v (GLenum pname, GLint64* params) = 0; + virtual void GetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) = 0; + virtual void GetInteger64i_v (GLenum target, GLuint index, GLint64* data) = 0; + virtual void GetBufferParameteri64v (GLenum target, GLenum pname, GLint64* params) = 0; + virtual void GenSamplers (GLsizei count, GLuint* samplers) = 0; + virtual void DeleteSamplers (GLsizei count, const GLuint* samplers) = 0; + virtual GLboolean IsSampler (GLuint sampler) = 0; + virtual void BindSampler (GLuint unit, GLuint sampler) = 0; + virtual void SamplerParameteri (GLuint sampler, GLenum pname, GLint param) = 0; + virtual void SamplerParameteriv (GLuint sampler, GLenum pname, const GLint* param) = 0; + virtual void SamplerParameterf (GLuint sampler, GLenum pname, GLfloat param) = 0; + virtual void SamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat* param) = 0; + virtual void GetSamplerParameteriv (GLuint sampler, GLenum pname, GLint* params) = 0; + virtual void GetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat* params) = 0; + virtual void VertexAttribDivisor (GLuint index, GLuint divisor) = 0; + virtual void BindTransformFeedback (GLenum target, GLuint id) = 0; + virtual void DeleteTransformFeedbacks (GLsizei n, const GLuint* ids) = 0; + virtual void GenTransformFeedbacks (GLsizei n, GLuint* ids) = 0; + virtual GLboolean IsTransformFeedback (GLuint id) = 0; + virtual void PauseTransformFeedback (void) = 0; + virtual void ResumeTransformFeedback (void) = 0; + virtual void GetProgramBinary (GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) = 0; + virtual void ProgramBinary (GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) = 0; + virtual void ProgramParameteri (GLuint program, GLenum pname, GLint value) = 0; + virtual void InvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum* attachments) = 0; + virtual void InvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) = 0; + virtual void TexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) = 0; + virtual void TexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0; + virtual void GetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) = 0; + +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_GL_ABSTRACTION_H__ diff --git a/dali/integration-api/gl-defines.h b/dali/integration-api/gl-defines.h new file mode 100644 index 0000000..5af7acd --- /dev/null +++ b/dali/integration-api/gl-defines.h @@ -0,0 +1,827 @@ +#ifndef __DALI_INTERNAL_GL_DEFINES_H__ +#define __DALI_INTERNAL_GL_DEFINES_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +/* + * This file is based on gl3.h, the following licence is included for conformance. + */ +/* +** Copyright (c) 2007-2012 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* OpenGL ES 2.0 */ + +/* ClearBufferMask */ +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 + +/* Boolean */ +#define GL_FALSE 0 +#define GL_TRUE 1 + +/* BeginMode */ +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 + +/* BlendingFactorDest */ +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 + +/* BlendingFactorSrc */ +/* GL_ZERO */ +/* GL_ONE */ +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +/* GL_SRC_ALPHA */ +/* GL_ONE_MINUS_SRC_ALPHA */ +/* GL_DST_ALPHA */ +/* GL_ONE_MINUS_DST_ALPHA */ + +/* BlendEquationSeparate */ +#define GL_FUNC_ADD 0x8006 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */ +#define GL_BLEND_EQUATION_ALPHA 0x883D + +/* BlendSubtract */ +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B + +/* Separate Blend Functions */ +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 + +/* Buffer Objects */ +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 + +#define GL_STREAM_DRAW 0x88E0 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 + +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 + +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 + +/* CullFaceMode */ +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 + +/* DepthFunction */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* EnableCap */ +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_BLEND 0x0BE2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_COVERAGE 0x80A0 + +/* ErrorCode */ +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 + +/* FrontFaceDirection */ +#define GL_CW 0x0900 +#define GL_CCW 0x0901 + +/* GetPName */ +#define GL_LINE_WIDTH 0x0B21 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +/* GL_SCISSOR_TEST */ +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +/* GL_POLYGON_OFFSET_FILL */ +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB + +/* GetTextureParameter */ +/* GL_TEXTURE_MAG_FILTER */ +/* GL_TEXTURE_MIN_FILTER */ +/* GL_TEXTURE_WRAP_S */ +/* GL_TEXTURE_WRAP_T */ + +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 + +/* HintMode */ +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 + +/* HintTarget */ +#define GL_GENERATE_MIPMAP_HINT 0x8192 + +/* DataType */ +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C + +/* PixelFormat */ +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A + +/* PixelType */ +/* GL_UNSIGNED_BYTE */ +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 + +/* Shaders */ +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_SHADER_TYPE 0x8B4F +#define GL_DELETE_STATUS 0x8B80 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D + +/* StencilFunction */ +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 + +/* StencilOp */ +/* GL_ZERO */ +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_INVERT 0x150A +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 + +/* StringName */ +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 + +/* TextureMagFilter */ +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 + +/* TextureMinFilter */ +/* GL_NEAREST */ +/* GL_LINEAR */ +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 + +/* TextureParameterName */ +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 + +/* TextureTarget */ +/* GL_TEXTURE_2D */ +#define GL_TEXTURE 0x1702 + +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C + +/* TextureUnit */ +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 + +/* TextureWrapMode */ +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MIRRORED_REPEAT 0x8370 + +/* Uniform Types */ +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_CUBE 0x8B60 + +/* Vertex Arrays */ +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F + +/* Read Format */ +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B + +/* Shader Source */ +#define GL_COMPILE_STATUS 0x8B81 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_COMPILER 0x8DFA + +/* Shader Binary */ +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 + +/* Shader Precision-Specified Types */ +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 + +/* Framebuffer Object. */ +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 + +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGB565 0x8D62 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_STENCIL_INDEX8 0x8D48 + +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 + +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 + +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 + +#define GL_NONE 0 + +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD + +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 + +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 + +/* OpenGL ES 3.0 */ + +#define GL_READ_BUFFER 0x0C02 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_RED 0x1903 +#define GL_RGB8 0x8051 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_RG8 0x822B +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_COPY_READ_BUFFER_BINDING GL_COPY_READ_BUFFER +#define GL_COPY_WRITE_BUFFER_BINDING GL_COPY_WRITE_BUFFER +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x8D63 + +/*------------------------------------------------------------------------* + * EXT extension tokens + *------------------------------------------------------------------------*/ + +/* GL_EXT_blend_minmax */ +#ifndef GL_EXT_blend_minmax +#define GL_MIN_EXT 0x8007 +#define GL_MAX_EXT 0x8008 +#endif + +/* GL_EXT_discard_framebuffer */ +#ifndef GL_EXT_discard_framebuffer +#define GL_COLOR_EXT 0x1800 +#define GL_DEPTH_EXT 0x1801 +#define GL_STENCIL_EXT 0x1802 +#endif + +/* GL_EXT_multi_draw_arrays */ +/* No new tokens introduced by this extension. */ + +/* GL_EXT_read_format_bgra */ +#ifndef GL_EXT_read_format_bgra +#define GL_BGRA_EXT 0x80E1 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366 +#endif + +/* GL_EXT_texture_filter_anisotropic */ +#ifndef GL_EXT_texture_filter_anisotropic +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#endif + +/* GL_EXT_texture_format_BGRA8888 */ +#ifndef GL_EXT_texture_format_BGRA8888 +#define GL_BGRA_EXT 0x80E1 +#endif + +/* GL_EXT_texture_type_2_10_10_10_REV */ +#ifndef GL_EXT_texture_type_2_10_10_10_REV +#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368 +#endif + +/* GL_OES_get_program_binary */ +#ifndef GL_PROGRAM_BINARY_LENGTH_OES +#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE +#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF +#endif + + +#endif // __DALI_INTERNAL_GL_DEFINES_H__ diff --git a/dali/integration-api/gl-sync-abstraction.h b/dali/integration-api/gl-sync-abstraction.h new file mode 100644 index 0000000..a06cf8b --- /dev/null +++ b/dali/integration-api/gl-sync-abstraction.h @@ -0,0 +1,80 @@ +#ifndef __DALI_INTEGRATION_GL_SYNC_ABSTRACTION_H__ +#define __DALI_INTEGRATION_GL_SYNC_ABSTRACTION_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include + +namespace Dali +{ +namespace Integration +{ + +/** + * This abstraction defines an API for syncing CPU with GPU. + * A typical use case is to determine when GL draw calls have finished drawing + * to a framebuffer. + */ +class GlSyncAbstraction +{ +protected: + /** + * Virtual protected destructor, no deletion through this interface + */ + virtual ~GlSyncAbstraction() {} + +public: + + class SyncObject + { + protected: + /** + * Virtual protected destructor, no deletion through this interface. This prevents + * Core from deleting SyncObjects - only Adaptor implementation is able to delete + * them. + */ + virtual ~SyncObject() {} + + public: + + /** + * Determine if the synchronisation object has been signalled. + * @return false if the sync object has not been signalled, true if it has been signalled (and + * can now be destroyed) + */ + virtual bool IsSynced() = 0; + }; + + /** + * Create a synchronisation object based on the resource id, typically that of + * a framebuffer texture. It can then be polled using the same resource id. + * @return A pointer to an opaque sync object + */ + virtual SyncObject* CreateSyncObject() = 0; + + /** + * Destroy the synchronisation object. + * @param[in] syncObject The sync object to destroy + */ + virtual void DestroySyncObject(SyncObject* syncObject) = 0; +}; + +} // namespace Integration +} // namespace Dali + +#endif // __DALI_INTEGRATION_GL_SYNC_ABSTRACTION_H__ diff --git a/dali/integration-api/image-data.cpp b/dali/integration-api/image-data.cpp new file mode 100644 index 0000000..a0d772a --- /dev/null +++ b/dali/integration-api/image-data.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES + +// EXTERNAL INCLUDES + +namespace Dali +{ + +namespace Integration +{ + +ImageData::ImageData( const size_t numBytes, const unsigned imageWidth, const unsigned imageHeight, const Pixel::Format pixelFormat ) : + mData( new uint8_t[numBytes] ), + dataSize( numBytes ), + imageWidth( imageWidth ), + imageHeight( imageHeight ), + pixelFormat( pixelFormat ), + mAlphaChannelUsed( ALPHA_USAGE_UNDETERMINED ) +{ + DALI_ASSERT_DEBUG( numBytes > 0U && imageWidth > 0U && imageHeight > 0U ); +} + +ImageData::ImageData( uint8_t * const imageBuffer, const size_t numBytes, const unsigned imageWidth, const unsigned imageHeight, const Pixel::Format pixelFormat ) : + mData( imageBuffer ), + dataSize( numBytes ), + imageWidth( imageWidth ), + imageHeight( imageHeight ), + pixelFormat( pixelFormat ), + mAlphaChannelUsed( ALPHA_USAGE_UNDETERMINED ) +{ + DALI_ASSERT_DEBUG( imageBuffer != 0 && numBytes > 0U && imageWidth > 0U && imageHeight > 0U ); +} + +ImageData::~ImageData() +{ + delete[] mData; +} + +ImageDataPtr ImageData::New( const BufferSize numBytes, unsigned imageWidth, unsigned imageHeight, Pixel::Format pixelFormat ) +{ + DALI_ASSERT_DEBUG( numBytes.bufferSize > 0 && "Zero allocations are pointless if also harmless." ); + DALI_ASSERT_DEBUG( imageWidth > 0 && imageHeight > 0 && "Zero dimensioned images are pointless if also harmless." ); + return ImageDataPtr( new ImageData( numBytes, imageWidth, imageHeight, pixelFormat ) ); +} + +ImageDataPtr ImageData::New( uint8_t * const imageBuffer, const BufferSize numBytes, unsigned imageWidth, unsigned imageHeight, Pixel::Format pixelFormat ) +{ + DALI_ASSERT_DEBUG( numBytes.bufferSize > 0 && "Zero-length buffers are pointless if also harmless." ); + DALI_ASSERT_DEBUG( imageWidth > 0 && imageHeight > 0 && "Zero dimensioned images are pointless if also harmless." ); + return ImageDataPtr( new ImageData( imageBuffer, numBytes, imageWidth, imageHeight, pixelFormat ) ); +} + +ImageDataPtr NewBitmapImageData( unsigned imageWidth, unsigned imageHeight, Pixel::Format pixelFormat ) +{ + DALI_ASSERT_DEBUG( pixelFormat <= Pixel::BGRA8888 && "Pixel format must be an addressable one." ); + const size_t numBytes = imageWidth * imageHeight * Pixel::GetBytesPerPixel( pixelFormat ); + + return ImageData::New( BufferSize(numBytes), imageWidth, imageHeight, pixelFormat ); +} + +} //namespace Integration + +} //namespace Dali + diff --git a/dali/integration-api/image-data.h b/dali/integration-api/image-data.h new file mode 100644 index 0000000..58c9d80 --- /dev/null +++ b/dali/integration-api/image-data.h @@ -0,0 +1,197 @@ +#ifndef __DALI_INTEGRATION_IMAGE_DATA_H__ +#define __DALI_INTEGRATION_IMAGE_DATA_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include // For DALI_LOG_OBJECT_STRING_DECLARATION +#include +#include +#include + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Integration +{ + +class ImageData; +typedef IntrusivePtr ImageDataPtr; + +typedef uint8_t PixelBuffer; + +/** + * Used to avoid accidentally mixing the order of parameters where some are uint + * dimensions and one is a buffer size. + **/ +class BufferSize +{ +public: + explicit BufferSize(size_t size) : bufferSize( size ) + { } + operator size_t() const { return bufferSize; } + const size_t bufferSize; +}; + +/** + * @brief A simple container for image data. + * + * Just a pointer to a buffer and some minimal metadata. It always owns the + * buffer of image data that it points to until it is destroyed or the buffer + * is released with ReleaseImageBuffer(). + * + * The width and height stored are the logical image values. Compressed formats + * such as ETC group pixels into blocks (ETC = 4*4) and these logical width and + * height may indicate, for example for ETC, that 1 to 3 pixels in the rightmost + * column of blocks or bottom row are ignored for rendering. + * For simple uncompressed images, the buffer is exactly width * height * + * bytes-per-pixel in size with no spare bytes at right or bottom edge. + */ +class DALI_IMPORT_API ImageData : public Dali::RefObject +{ +public: + /** + * @brief Three values for the information about the alpha values in the + * pixels. + * + * Alpha in pixels with the channel can be undetermined, it can be all-ones, + * or it can have at least one pixel that is translucent with an alpha < 1.0. + **/ + enum AlphaUsage + { + /** Alpha not yet been tested.*/ + ALPHA_USAGE_UNDETERMINED, + /** Alpha == 1.0 in every pixel.*/ + ALPHA_USAGE_ALL_OPAQUE, + /** Alpha < 1.0 in at least one pixel.*/ + ALPHA_USAGE_SOME_TRANSLUCENT + }; + +private: + + /** + * Construct an instance and allocate a buffer owned by it. + * @param[in] numBytes The number of bytes to allocate to hold the image data. + * @param[in] imageWidth The width in pixels of the image. + * @param[in] imageHeight The height in pixels of the image. + * @param[in] pixelFormat The format of the image data in the buffer. + */ + ImageData( const size_t numBytes, const unsigned imageWidth, const unsigned imageHeight, const Pixel::Format pixelFormat ); + + /** + * Construct an instance and have it take ownership of the buffer passed in. + * @param[in] imageBuffer A buffer of pixel data that should have been allocated using new uint8_t[]. + * @param[in] numBytes The number of bytes in the buffer pointed to by imageBuffer. + * @param[in] imageWidth The width in pixels of the image. + * @param[in] imageHeight The height in pixels of the image. + * @param[in] pixelFormat The format of the image data in the buffer. + */ + ImageData( uint8_t * const imageBuffer, const size_t numBytes, const unsigned imageWidth, const unsigned imageHeight, const Pixel::Format pixelFormat ); + + ~ImageData(); + +public: + + /** Allocate and initialize a fresh ImageData object pointing at a new buffer, + * returning a smart pointer owning it. + * @note Clients can alternatively use the helper function NewBitmapImageData() to + * calculate the buffer size from other parameters if the image data represents + * a bitmap (a 2d grid of addressable pixels). + * @param[in] numBytes The number of bytes to allocate to hold the image data. + * @param[in] imageWidth The width in pixels of the image. + * @param[in] imageHeight The height in pixels of the image. + * @param[in] pixelFormat The format of the image data in the buffer. + **/ + static ImageDataPtr New( const BufferSize numBytes, unsigned imageWidth, unsigned imageHeight, Pixel::Format pixelFormat ); + + /** Allocate and initialise a fresh ImageData object, taking ownership of the + * buffer passed in. + * @param[in] imageBuffer A block of memory allocated with + * new uint8_t[]. This is owned by the new ImageData instance + * on successful return and should be forgotten by the caller. + * @param[in] numBytes The number of bytes in the buffer pointed to by imageBuffer. + * @param[in] imageWidth The width in pixels of the image. + * @param[in] imageHeight The height in pixels of the image. + * @param[in] pixelFormat The format of the image data in the buffer. + **/ + static ImageDataPtr New( uint8_t * const imageBuffer, const BufferSize numBytes, unsigned imageWidth, unsigned imageHeight, Pixel::Format pixelFormat ); + + /** Access the buffer of image data. */ + const uint8_t * GetBuffer() const { return mData; } + + /** Access the buffer of image data. */ + uint8_t * GetBuffer() { return mData; } + + /** + * Pass ownership of the buffer of pixel-level data that this instance + * currently owns to the caller, and forget about the buffer here as a + * side effect. + * @returns A pointer to the underlying buffer of pixel-level image data. + * The caller takes ownership of the buffer and is responsible for calling + * delete[] on it eventually. + **/ + uint8_t * ReleaseImageBuffer() { uint8_t * const data = mData; mData = 0; return data; } + + /** + * @brief Get whether the alpha channel in the pixels is used. + */ + AlphaUsage GetAlphaUsage() const { return mAlphaChannelUsed; } + + /** + * @brief Set whether the alpha channel in the pixels is used. + */ + void SetAlphaUsed( const bool alphaUsed ) { mAlphaChannelUsed = alphaUsed ? ALPHA_USAGE_SOME_TRANSLUCENT : ALPHA_USAGE_ALL_OPAQUE; } + +private: + + ImageData(const ImageData& other); ///< defined private to prevent use + ImageData& operator = (const ImageData& other); ///< defined private to prevent use + + /** Pointer to the buffer of image data. */ + uint8_t* mData; + +public: + const size_t dataSize; ///< Number of bytes in buffer pointed at by mData + const uint16_t imageWidth; ///< Image logical width in pixels + const uint16_t imageHeight; ///< Image logical height in pixels + const Pixel::Format pixelFormat; ///< Pixel format + +private: + AlphaUsage mAlphaChannelUsed; + + // Changes scope, should be at end of class + DALI_LOG_OBJECT_STRING_DECLARATION; +}; + +/** + * A convenience function for creating the common case of an uncompressed image + * having width * height pixels in the buffer. + * @param[in] imageWidth The width in pixels of the image. + * @param[in] imageHeight The height in pixels of the image. + * @param[in] pixelFormat The format of the image data in the buffer. + */ +DALI_IMPORT_API ImageDataPtr NewBitmapImageData( unsigned imageWidth, unsigned imageHeight, Pixel::Format pixelFormat ); + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_IMAGE_DATA_H__ diff --git a/dali/integration-api/input-options.cpp b/dali/integration-api/input-options.cpp new file mode 100644 index 0000000..e05619f --- /dev/null +++ b/dali/integration-api/input-options.cpp @@ -0,0 +1,108 @@ +#include "input-options.h" + +#include +#include + +using Dali::Internal::GestureEventProcessor; +using Dali::Internal::ThreadLocalStorage; + +namespace Dali +{ + +namespace Integration +{ + +void SetPanGesturePredictionMode( int mode ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGesturePredictionMode(mode); +} + +void SetPanGesturePredictionAmount( unsigned int amount ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGesturePredictionAmount(amount); +} + +void SetPanGestureMaximumPredictionAmount( unsigned int amount ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGestureMaximumPredictionAmount(amount); +} + +void SetPanGestureMinimumPredictionAmount( unsigned int amount ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGestureMinimumPredictionAmount(amount); +} + +void SetPanGesturePredictionAmountAdjustment( unsigned int amount ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGesturePredictionAmountAdjustment(amount); +} + +void SetPanGestureSmoothingMode( int mode ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGestureSmoothingMode(mode); +} + +void SetPanGestureSmoothingAmount( float amount ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGestureSmoothingAmount(amount); +} + +void SetPanGestureUseActualTimes( bool value ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGestureUseActualTimes( value ); +} + +void SetPanGestureInterpolationTimeRange( int value ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGestureInterpolationTimeRange( value ); +} + +void SetPanGestureScalarOnlyPredictionEnabled( bool value ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGestureScalarOnlyPredictionEnabled( value ); +} + +void SetPanGestureTwoPointPredictionEnabled( bool value ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGestureTwoPointPredictionEnabled( value ); +} + +void SetPanGestureTwoPointInterpolatePastTime( int value ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGestureTwoPointInterpolatePastTime( value ); +} + +void SetPanGestureTwoPointVelocityBias( float value ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGestureTwoPointVelocityBias( value ); +} + +void SetPanGestureTwoPointAccelerationBias( float value ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGestureTwoPointAccelerationBias( value ); +} + +void SetPanGestureMultitapSmoothingRange( int value ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + eventProcessor.SetPanGestureMultitapSmoothingRange( value ); +} + + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/input-options.h b/dali/integration-api/input-options.h new file mode 100644 index 0000000..1e58d18 --- /dev/null +++ b/dali/integration-api/input-options.h @@ -0,0 +1,151 @@ +#ifndef __DALI_INTEGRATION_INPUT_OPTIONS_H__ +#define __DALI_INTEGRATION_INPUT_OPTIONS_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Integration +{ + +/** + * @brief Called by adaptor to set the pan gesture prediction mode from + * an environment variable + * + * @pre Should be called after Core creation. + * @param mode The pan gesture prediction mode. + */ +DALI_IMPORT_API void SetPanGesturePredictionMode( int mode ); + +/** + * @brief Called by adaptor to set the prediction amount of the pan gesture + * from an environment variable + * + * @param[in] amount The prediction amount in milliseconds + */ +DALI_IMPORT_API void SetPanGesturePredictionAmount(unsigned int amount); + +/** + * @brief Sets the upper bound of the prediction amount for clamping + * from an environment variable + * + * @param[in] amount The prediction amount in milliseconds + */ +DALI_IMPORT_API void SetPanGestureMaximumPredictionAmount( unsigned int amount ); + +/** + * @brief Sets the lower bound of the prediction amount for clamping + * from an environment variable + * + * @param[in] amount The prediction amount in milliseconds + */ +DALI_IMPORT_API void SetPanGestureMinimumPredictionAmount( unsigned int amount ); + +/** + * @brief Sets the prediction amount to adjust when the pan velocity is changed + * from an environment variable. If the pan velocity is accelerating, the prediction + * amount will be increased by the specified amount until it reaches the upper bound. + * If the pan velocity is decelerating, the prediction amount will be decreased by + * the specified amount until it reaches the lower bound. + * + * @param[in] amount The prediction amount in milliseconds + */ +DALI_IMPORT_API void SetPanGesturePredictionAmountAdjustment( unsigned int amount ); + +/** + * @brief Called to set how pan gestures smooth input + * + * @param[in] mode The smoothing mode to use + */ +DALI_IMPORT_API void SetPanGestureSmoothingMode( int mode ); + +/** + * @brief Sets the smoothing amount of the pan gesture + * + * @param[in] amount The smoothing amount [0.0f,1.0f] - 0.0f would be no smoothing, 1.0f maximum smoothing + */ +DALI_IMPORT_API void SetPanGestureSmoothingAmount( float amount ); + +/** + * @brief Sets whether to use actual times of the real gesture and frames or not. + * + * @param[in] value True = use actual times, False = use perfect values + */ +DALI_IMPORT_API void SetPanGestureUseActualTimes( bool value ); + +/** + * @brief Sets the interpolation time range (ms) of past points to use (with weights) when interpolating. + * + * @param[in] value Time range in ms + */ +DALI_IMPORT_API void SetPanGestureInterpolationTimeRange( int value ); + +/** + * @brief Sets whether to use scalar only prediction, which when enabled, ignores acceleration. + * + * @param[in] value True = use scalar prediction only + */ +DALI_IMPORT_API void SetPanGestureScalarOnlyPredictionEnabled( bool value ); + +/** + * @brief Sets whether to use two point prediction. This combines two interpolated points to get more steady acceleration and velocity values. + * + * @param[in] value True = use two point prediction + */ +DALI_IMPORT_API void SetPanGestureTwoPointPredictionEnabled( bool value ); + +/** + * @brief Sets the time in the past to interpolate the second point when using two point interpolation. + * + * @param[in] value Time in past in ms + */ +DALI_IMPORT_API void SetPanGestureTwoPointInterpolatePastTime( int value ); + +/** + * @brief Sets the two point velocity bias. This is the ratio of first and second points to use for velocity. + * + * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point. + */ +DALI_IMPORT_API void SetPanGestureTwoPointVelocityBias( float value ); + +/** + * @brief Sets the two point acceleration bias. This is the ratio of first and second points to use for acceleration. + * + * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point. + */ +DALI_IMPORT_API void SetPanGestureTwoPointAccelerationBias( float value ); + +/** + * @brief Sets the range of time (ms) of points in the history to perform multitap smoothing with (if enabled). + * + * @param[in] value Time in past in ms + */ +DALI_IMPORT_API void SetPanGestureMultitapSmoothingRange( int value ); + + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_INPUT_OPTIONS_H__ diff --git a/dali/integration-api/lockless-buffer.cpp b/dali/integration-api/lockless-buffer.cpp new file mode 100644 index 0000000..b704dbc --- /dev/null +++ b/dali/integration-api/lockless-buffer.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include "lockless-buffer.h" + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Integration +{ + +LocklessBuffer::LocklessBuffer( size_t size ) +: mState( R0W1 ), + mSize( size ) +{ + // allocate memory to speed up operation + mBuffer[0] = new unsigned char[size]; + mBuffer[1] = new unsigned char[size]; + + memset (mBuffer[0], 0, size ); + memset (mBuffer[1], 0, size ); +} + +LocklessBuffer::~LocklessBuffer() +{ + delete[] mBuffer[0]; + delete[] mBuffer[1]; +} + +void LocklessBuffer::Write( const unsigned char *src, size_t size ) +{ + DALI_ASSERT_ALWAYS( size <= mSize ); + + // set WRITING bit + BufferState currentState( __sync_fetch_and_or( &mState, WRITING ) ); + DALI_ASSERT_DEBUG( !(currentState & WRITING_MASK) ); // WRITING bit should never be set when we get here + + // copy data to current write buffer, negate state to get actual index (recap: R0W1 = 0, R1W0 = 1) + const unsigned int index = (currentState & WRITE_BUFFER_MASK); + memcpy( mBuffer[index], src, size ); + + // unset WRITING bit, set UPDATED bit + BufferState checkState = __sync_val_compare_and_swap( &mState, + static_cast(currentState | WRITING), + static_cast(index | UPDATED) ); + + DALI_ASSERT_DEBUG( checkState & WRITING ); + (void)checkState; // Avoid unused variable warning +} + +const unsigned char* LocklessBuffer::Read() +{ + // current state (only to avoid multiple memory reads with volatile variable) + BufferState currentState( mState ); + BufferState currentWriteBuf( static_cast( currentState & WRITE_BUFFER_MASK ) ); + + if( currentState & UPDATED_MASK ) + { + // Try to swap buffers. + // This will set mState to 1 if readbuffer 0 was updated, 0 if readbuffer 1 was updated and fail if WRITING is set + if( __sync_bool_compare_and_swap( &mState, + static_cast(currentWriteBuf | UPDATED), + static_cast(!currentWriteBuf) ) ) + { + // swap successful + return mBuffer[currentWriteBuf]; + } + } + + // UPDATE bit wasn't set or WRITING bit was set in other thread + // swap failed, read from current readbuffer + return mBuffer[!currentWriteBuf]; +} + +unsigned int LocklessBuffer::GetSize() const +{ + return static_cast(mSize); +} + +} // Internal + +} // Dali diff --git a/dali/integration-api/lockless-buffer.h b/dali/integration-api/lockless-buffer.h new file mode 100644 index 0000000..dfb9a90 --- /dev/null +++ b/dali/integration-api/lockless-buffer.h @@ -0,0 +1,113 @@ +#ifndef __DALI_INTEGRATION_LOCKLESS_BUFFER_H__ +#define __DALI_INTEGRATION_LOCKLESS_BUFFER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Integration +{ + +/** + * The LocklessBuffer class implements double buffering eligible for multi-(two) threaded use, + * where it's possible to read from one thread and write from another + * without requiring a mutex lock to avoid performance hit. + * It's intended to be used for reading bitmap data in render thread + * while still possible to write data in another thread. + * + * Ideally Write() and Read() calls should be alternating, otherwise written data might be thrown away. + * + * The buffers are swapped in the reading thread, just before reading begins. + * In case the other thread is writing at that moment, buffers are not swapped and previously available data is read. + * Similarly if Write() is called before a Read() has finished the previous write buffer is overwritten. + */ +class DALI_IMPORT_API LocklessBuffer +{ + +public: + /** + * Constructor. + * @param[in] size The size of buffers in bytes. + */ + LocklessBuffer( size_t size ); + + /** + * Destructor. + */ + ~LocklessBuffer(); + + /** + * Write data to buffer. + * @param[in] src data source + * @param[in] size size of data in bytes + */ + void Write( const unsigned char *src, size_t size ); + + /** + * Try to swap buffers and read data. + * @note returned value only valid until Read() is called again or object is destroyed + * @return current read buffer contents + */ + const unsigned char* Read(); + + /** + * @return the buffer size in bytes + */ + unsigned int GetSize() const; + +private: + /** + * Atomically set state. + * We're always writing to one buffer and reading from the other. + * Write() sets WRITING bit when started and unsets it when finished. + */ + enum BufferState + { + R0W1 = 0, ///< Read from buffer 0 write to buffer 1 + R1W0 = 1, ///< Read from buffer 1 write to buffer 0 + WRITING = 2, ///< Currently writing to buffer + UPDATED = 4, ///< Swapping buffer required; there is new data available + WRITE_BUFFER_MASK = 1, ///< indicates which buffer to write to + WRITING_MASK = 2, ///< indicates whether currently writing + UPDATED_MASK = 4 ///< indicates whether new data is available + }; + +private: + LocklessBuffer(); ///< undefined default constructor, need to give size on construction + LocklessBuffer( const LocklessBuffer& ); ///< undefined copy constructor + LocklessBuffer& operator=( const LocklessBuffer& ); ///< undefined assignment operator + +private: + unsigned char* mBuffer[2]; ///< bitmap buffers + BufferState volatile mState; ///< readbuffer number and whether we're currently writing into writebuffer or not + size_t mSize; ///< size of buffers +}; + +} // Internal + +} // Dali + +#endif // __DALI_INTEGRATION_LOCKLESS_H__ diff --git a/dali/integration-api/platform-abstraction.h b/dali/integration-api/platform-abstraction.h new file mode 100644 index 0000000..3b3f460 --- /dev/null +++ b/dali/integration-api/platform-abstraction.h @@ -0,0 +1,245 @@ +#ifndef __DALI_INTEGRATION_PLATFORM_ABSTRACTION_H__ +#define __DALI_INTEGRATION_PLATFORM_ABSTRACTION_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES + +#include +#include ///@todo Remove this include (a bunch of stuff needs to include it though) +#include +#include + +namespace Dali +{ + +namespace Integration +{ + +/** + * PlatformAbstraction is an abstract interface, used by Dali to access platform specific services. + * A concrete implementation must be created for each platform, and provided when creating the + * Dali::Integration::Core object. + */ +class PlatformAbstraction +{ +public: + + virtual ~PlatformAbstraction() {} + + // Dali Lifecycle + + /** + * Get the monotonic time since an unspecified reference point. + * This is used by Dali to calculate time intervals during animations; the interval is + * recalculated when Dali is resumed with Dali::Integration::Core::Resume(). + * Multi-threading note: this method may be called from either the main or rendering thread. + * @param[out] seconds The time in seconds since the reference point. + * @param[out] microSeconds The remainder in microseconds. + */ + virtual void GetTimeMicroseconds(unsigned int& seconds, unsigned int& microSeconds) = 0; + + /** + * Tell the platform abstraction that Dali is ready to pause, such as when the + * application enters a background state. + * Allows background threads to pause their work until Resume() is called. + * This is a good time to release recreatable data such as memory caches + * to cooperate with other apps and reduce the chance of this one being + * force-killed in a low memory situation. + */ + virtual void Suspend() = 0; + + /** + * Tell the platform abstraction that Dali is resuming from a pause, such as + * when it has transitioned from a background state to a foreground one. + * It is time to wake up sleeping background threads and recreate memory + * caches and other temporary data. + */ + virtual void Resume() = 0; + + // Resource Loading + + /** + * @brief Determine the size of an image the resource loaders will provide when + * given the same image loading parameters. + * + * This is a synchronous request. + * This function is used to determine the size of an image before it has loaded. + * @param[in] filename name of the image. + * @param[in] size The requested size for the image. + * @param[in] fittingMode The method to use to map the source image to the desired + * dimensions. + * @param[in] samplingMode The image filter to use if the image needs to be + * downsampled to the requested size. + * @param[in] orientationCorrection Whether to use image metadata to rotate or + * flip the image, e.g., from portrait to landscape. + * @return dimensions that image will have if it is loaded with given parameters. + */ + virtual ImageDimensions GetClosestImageSize( const std::string& filename, + ImageDimensions size = ImageDimensions( 0, 0 ), + FittingMode::Type fittingMode = FittingMode::SHRINK_TO_FIT, + SamplingMode::Type samplingMode = SamplingMode::BOX, + bool orientationCorrection = true) = 0; + + /** + @brief Determine the size of an image the resource loaders will provide when + * given the same image loading parameters. + * + * This is a synchronous request. + * This function is used to determine the size of an image before it has loaded. + * @param[in] filename name of the image. + * @param[in] size The requested size for the image. + * @param[in] fittingMode The method to use to map the source image to the desired + * dimensions. + * @param[in] samplingMode The image filter to use if the image needs to be + * downsampled to the requested size. + * @param[in] orientationCorrection Whether to use image metadata to rotate or + * flip the image, e.g., from portrait to landscape. + * @return dimensions that image will have if it is loaded with given parameters. + */ + virtual ImageDimensions GetClosestImageSize( ResourcePointer resourceBuffer, + ImageDimensions size = ImageDimensions( 0, 0 ), + FittingMode::Type fittingMode = FittingMode::SHRINK_TO_FIT, + SamplingMode::Type samplingMode = SamplingMode::BOX, + bool orientationCorrection = true) = 0; + + /** + * Request a resource from the native filesystem. This is an asynchronous request. + * After this method returns, FillResourceCache() will be called to retrieve the result(s) of the + * resource loading operation. Loading resources in separate worker thread is recommended. + * Multi-threading note: this method will be called from the main thread only i.e. not + * from within the Core::Render() method. + * @param[in] request A unique resource request. This is not guaranteed to survive after LoadResource + * returns; the loading process should take a copy. + */ + virtual void LoadResource(const ResourceRequest& request) = 0; + + /** + * Request a resource from the native filesystem. This is a synchronous request, i.e. + * it will block the main loop whilst executing. It should therefore be used sparingly. + * + * Multi-threading note: this method will be called from the main thread only i.e. not + * from within the Core::Render() method. + * @param[in] resourceType The type of resource to load + * @param[in] resourcePath The path to the resource + * @return A pointer to a ref-counted resource + */ + virtual ResourcePointer LoadResourceSynchronously( const ResourceType& resourceType, const std::string& resourcePath ) = 0; + + /** + * Decode a buffer of data synchronously. + * @param[in] resourceType The type of resource to load + * @param[in] buffer The decoded data + * @param[in] bufferSize The size of the buffer used by the decoded data. + * + * @return A pointer to the decoded buffer. + */ + virtual BitmapPtr DecodeBuffer( const ResourceType& resourceType, uint8_t * buffer, size_t bufferSize ) = 0; + + /** + * Cancel an ongoing LoadResource() request. + * Multi-threading note: this method will be called from the main thread only i.e. not + * from within the Core::Render() method. + * @param[in] id The ID of the resource to cancel. + * @param[in] typeId The ID type of the resource to cancel. + */ + virtual void CancelLoad(ResourceId id, ResourceTypeId typeId) = 0; + + /** + * Query whether any asynchronous LoadResource() requests are ongoing. + * Multi-threading note: this method may be called from either the main or rendering thread. + * @return True if resources are being loaded. + */ + virtual bool IsLoading() = 0; + + /** + * Retrieve newly loaded resources. + * If no resources have finished loading, then this method returns immediately. + * Multi-threading note: this method will be called from the update thread, from within + * the UpdateManager::Update() method. + * @param[in] cache The resource cache to fill. + */ + virtual void GetResources(ResourceCache& cache) = 0; + + /** + * Waits for the asynchronous loader threads (if any) to finish. + * This will be only be called before Core destruction; no resource loading requests will be + * made following this method. + */ + virtual void JoinLoaderThreads() = 0; + + // Font Queries + + /** + * Called by Dali to retrieve the default font size for the platform. + * This is an accessibility size, which is mapped to a UI Control specific point-size in stylesheets. + * For example if zero the smallest size, this could potentially map to TextLabel point-size 8. + * Multi-threading note: this method will be called from the main thread only i.e. not + * from within the Core::Render() method. + * @return The default font size. + */ + virtual int GetDefaultFontSize() const = 0; + + /** + * Sets horizontal and vertical pixels per inch value that is used by the display + * @param[in] dpiHorizontal horizontal dpi value + * @param[in] dpiVertical vertical dpi value + */ + virtual void SetDpi (unsigned int dpiHorizontal, unsigned int dpiVertical) = 0; + + /** + * Load a file into a buffer + * @param[in] filename The filename to load + * @param[out] buffer A buffer to receive the file. + * @result true if the file is loaded. + */ + virtual bool LoadFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const = 0; + + /** + * Load a file into a buffer + * @param[in] filename The filename to save + * @param[out] buffer A buffer containing some data + * The buffer is implemeneted with a Dali::Vector. The size() member specifies the buffer length. + * @result true if the file is saved. + */ + virtual bool SaveFile( const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const = 0; + + /** + * Load a shader binary file into a buffer + * @param[in] filename The shader binary filename to load + * @param[out] buffer A buffer to receive the file. + * @result true if the file is loaded. + */ + virtual bool LoadShaderBinaryFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const = 0; + + /** + * Save a shader binary file to the resource file system. + * @param[in] filename The shader binary filename to save to. + * @param[in] buffer A buffer to write the file from. + * @param[in] numbytes Size of the buffer. + * @result true if the file is saved, else false. + */ + virtual bool SaveShaderBinaryFile( const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const = 0; + +}; // class PlatformAbstraction + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_PLATFORM_ABSTRACTION_H__ diff --git a/dali/integration-api/profiling.cpp b/dali/integration-api/profiling.cpp new file mode 100644 index 0000000..fbe6236 --- /dev/null +++ b/dali/integration-api/profiling.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +using Dali::Internal::GestureEventProcessor; +using Dali::Internal::ThreadLocalStorage; + +namespace Dali +{ + +namespace Integration +{ + +void EnableProfiling( ProfilingType type ) +{ + GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor(); + + switch( type ) + { + case PROFILING_TYPE_PAN_GESTURE: + { + eventProcessor.EnablePanGestureProfiling(); + break; + } + case PROFILING_TYPE_END: + { + // nothing to do + break; + } + } +} + +namespace Profiling +{ + +const int ANIMATION_MEMORY_SIZE( + sizeof( Internal::Animation ) + + sizeof( Internal::AnimatorConnector ) + + sizeof( Internal::SceneGraph::Animation ) ); +const int CONSTRAINT_MEMORY_SIZE( + sizeof( Internal::Constraint ) + + sizeof( Internal::SceneGraph::Constraint > ) ); +const int ACTOR_MEMORY_SIZE( + sizeof( Internal::Actor ) + + sizeof( Internal::ActorAttachment ) + + sizeof( Internal::SceneGraph::Node ) + + sizeof( Internal::SceneGraph::NodeAttachment )); +const int CAMERA_ACTOR_MEMORY_SIZE( + sizeof( Internal::CameraActor ) + + sizeof( Internal::CameraAttachment ) + + sizeof( Internal::SceneGraph::Node ) + + sizeof( Internal::SceneGraph::CameraAttachment ) ); +const int IMAGE_ACTOR_MEMORY_SIZE( + sizeof( Internal::ImageActor ) + + sizeof( Internal::ImageAttachment ) + + sizeof( Internal::SceneGraph::Node ) + + sizeof( Internal::SceneGraph::ImageAttachment ) + + sizeof( Internal::SceneGraph::ImageRenderer )); +const int LAYER_MEMORY_SIZE( + sizeof( Internal::Layer ) + + sizeof( Internal::ActorAttachment ) + + sizeof( Internal::SceneGraph::Layer ) + + sizeof( Internal::SceneGraph::NodeAttachment ) ); +const int IMAGE_MEMORY_SIZE( + sizeof( Internal::Image ) + + sizeof( Internal::ImageFactoryCache::Request ) + + sizeof( Integration::Bitmap ) + + sizeof( Internal::BitmapMetadata ) + + sizeof( Internal::BitmapTexture ) + + sizeof( Internal::ImageTicket ) ); +const int RENDERER_MEMORY_SIZE( + sizeof( Internal::Renderer ) + + sizeof( Internal::RendererAttachment ) + + sizeof( Internal::SceneGraph::RendererAttachment ) + + sizeof( Internal::SceneGraph::Renderer ) + + sizeof( Internal::SceneGraph::NewRenderer ) ); +const int GEOMETRY_MEMORY_SIZE( + sizeof( Internal::Geometry ) + + sizeof( Internal::SceneGraph::Geometry ) ); +const int PROPERTY_BUFFER_MEMORY_SIZE( + sizeof( Internal::PropertyBuffer ) + + sizeof( Internal::SceneGraph::PropertyBuffer ) ); +const int MATERIAL_MEMORY_SIZE( + sizeof( Internal::Material ) + + sizeof( Internal::SceneGraph::Material ) ); +const int SAMPLER_MEMORY_SIZE( + sizeof( Internal::Sampler ) + + sizeof( Internal::SceneGraph::Sampler ) ); +const int SHADER_MEMORY_SIZE( + sizeof( Internal::Shader ) + + sizeof( Internal::SceneGraph::Shader ) ); + +} // namespace Profiling + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/profiling.h b/dali/integration-api/profiling.h new file mode 100644 index 0000000..2b60ca8 --- /dev/null +++ b/dali/integration-api/profiling.h @@ -0,0 +1,71 @@ +#ifndef __DALI_INTEGRATION_PROFILING_H__ +#define __DALI_INTEGRATION_PROFILING_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Integration +{ + +enum ProfilingType +{ + PROFILING_TYPE_PAN_GESTURE, + + PROFILING_TYPE_END +}; + +/** + * Called by adaptor to provide profiling information. + * + * @pre Should be called after Core creation. + * @param type The type of profiling information to output. + */ +DALI_IMPORT_API void EnableProfiling( ProfilingType type ); + + +namespace Profiling +{ + +DALI_IMPORT_API extern const int ANIMATION_MEMORY_SIZE; ///< Total size of animation and associated internal objects +DALI_IMPORT_API extern const int CONSTRAINT_MEMORY_SIZE; ///< Total size of constraint and associated internal objects +DALI_IMPORT_API extern const int ACTOR_MEMORY_SIZE; ///< Total size of actor and associated internal objects +DALI_IMPORT_API extern const int CAMERA_ACTOR_MEMORY_SIZE; ///< Total size of camera actor and associated internal objects +DALI_IMPORT_API extern const int IMAGE_ACTOR_MEMORY_SIZE; ///< Total size of image actor and associated internal objects +DALI_IMPORT_API extern const int LAYER_MEMORY_SIZE; ///< Total size of layer and associated internal objects +DALI_IMPORT_API extern const int IMAGE_MEMORY_SIZE; ///< Total size of image and associated internal objects + +DALI_IMPORT_API extern const int RENDERER_MEMORY_SIZE; ///< Total size of renderer and associated internal objects +DALI_IMPORT_API extern const int GEOMETRY_MEMORY_SIZE; ///< Total size of geometry and associated internal objects +DALI_IMPORT_API extern const int PROPERTY_BUFFER_MEMORY_SIZE; ///< Total size of property-0buffer and associated internal objects +DALI_IMPORT_API extern const int MATERIAL_MEMORY_SIZE; ///< Total size of material and associated internal objects +DALI_IMPORT_API extern const int SAMPLER_MEMORY_SIZE; ///< Total size of material and associated internal objects +DALI_IMPORT_API extern const int SHADER_MEMORY_SIZE; ///< Total size of material and associated internal objects +} // namespace Profiling + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_PROFILING_H__ diff --git a/dali/integration-api/render-controller.h b/dali/integration-api/render-controller.h new file mode 100644 index 0000000..253c67e --- /dev/null +++ b/dali/integration-api/render-controller.h @@ -0,0 +1,61 @@ +#ifndef __DALI_INTEGRATION_RENDER_CONTROLLER_H__ +#define __DALI_INTEGRATION_RENDER_CONTROLLER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +namespace Dali +{ + +namespace Integration +{ + +/** + * Abstract interface for an object which controls rendering. + * This will be informed when Dali has new content to render. + */ +class RenderController +{ +protected: + + /** + * Virtual protected destructor, no deletion through this interface + */ + virtual ~RenderController() {} + +public: + + /** + * Requests a future call to Dali::Integration::Core::Update(). + * This is called when Dali has new content, typically in response to Actors/Animations being added. + * Multi-threading note: this method will be called from the main thread only. + */ + virtual void RequestUpdate() = 0; + + /** + * Requests a future call to Dali::Integration::Core::ProcessEvents(), when the application is idle. + * Multi-threading note: this method will be called from the main thread only. + */ + virtual void RequestProcessEventsOnIdle() = 0; + +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_RENDER_CONTROLLER_H__ diff --git a/dali/integration-api/resource-cache.h b/dali/integration-api/resource-cache.h new file mode 100644 index 0000000..0ca6803 --- /dev/null +++ b/dali/integration-api/resource-cache.h @@ -0,0 +1,86 @@ +#ifndef __DALI_INTEGRATION_RESOURCE_CACHE_H__ +#define __DALI_INTEGRATION_RESOURCE_CACHE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Integration +{ +/** + * Used to determine why a resource IO operation has failed. + */ +enum ResourceFailure +{ + FailureUnknown, + FailureFileNotFound, + FailureInvalidPath +}; + +/** + * Used to return loaded resources for rendering etc. + */ +typedef IntrusivePtr ResourcePointer; + +/** + * Abstract interface to receive notifications of resource IO operations. + * This is used when pulling loaded resources from the PlatformAbstraction. + */ +class ResourceCache +{ +protected: + + /** + * Virtual protected destructor, no deletion through this interface + */ + virtual ~ResourceCache() {} + +public: + + /** + * Provide the results of a resource loading operation to the cache. + * @param[in] id The unique ID of the load request. + * This should match an ID previously passed into PlatformAbstraction::LoadResource(). + * LoadResponse() may be called multiple times with the same ID, when results are available + * at different stages e.g. a thumbnail image may be provided, before the full image is loaded. + * @param[in] type The type of the resource. + * @param[in] resource A pointer to a resource (Bitmap etc). + * @param[in] status The current loading status. RESOURCE_LOADING and RESOURCE_PARTIALLY_LOADED indicate there are more responses to come, RESOURCE_COMPLETELY_LOADED indicates this is the last response for this id. + */ + virtual void LoadResponse(ResourceId id, ResourceTypeId type, ResourcePointer resource, LoadStatus status) = 0; + + /** + * Report that a resource loading operation has failed. + * @param[in] id The unique ID of the load request. + * This should match an ID previously passed into PlatformAbstraction::LoadResource(). + * @param[in] failure An error code, used to determine why the load failed. + */ + virtual void LoadFailed(ResourceId id, ResourceFailure failure) = 0; +}; + + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_RESOURCE_CACHE_H__ diff --git a/dali/integration-api/resource-declarations.h b/dali/integration-api/resource-declarations.h new file mode 100644 index 0000000..69dface --- /dev/null +++ b/dali/integration-api/resource-declarations.h @@ -0,0 +1,67 @@ +#ifndef __DALI_INTEGRATION_RESOURCE_DECLARATIONS_H__ +#define __DALI_INTEGRATION_RESOURCE_DECLARATIONS_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +namespace Dali +{ + +namespace Integration +{ + +/** + * @brief Used to identify a resource loading operation. + * + * These unique ResourceId values can be used to identify a resource loading + * transaction in core-adaptor communication. + * A resource transaction is asynchronous and many can be in-flight + * concurrently. + * A ResourceId allows the core to track a resource transaction over its + * lifetime and match an asynchronous completion notification to the + * corresponding load request or to cancel the operation early. + * + * A resource transaction begins with a call to PlatformAbstraction::LoadResource() + * Later asynchronous status notifications obtained by polling + * PlatformAbstraction::GetResources() can be mapped to corresponding + * LoadResource() invocations using the ResourceId value. + * It is the core's responsibility to ensure that each invocation of + * PlatformAbstraction::LoadResource() passes in a Request object with a unique + * integer ResourceId. + * + * @sa Dali::Integration::PlatformAbstraction::LoadResource + * Dali::Integration::PlatformAbstraction::GetResources + * Dali::Integration::ResourceCache + * Dali::Internal::ImageFactoryCache::RequestId + */ +typedef unsigned int ResourceId; + +/** + * Used to inform the current loading status + */ +enum LoadStatus +{ + RESOURCE_LOADING, ///< There are missing resources, being loaded + RESOURCE_PARTIALLY_LOADED, ///< Enough resource has been loaded to start low quality rendering + RESOURCE_COMPLETELY_LOADED, ///< The resource has been completely loaded +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_RESOURCE_DECLARATIONS_H__ diff --git a/dali/integration-api/resource-policies.h b/dali/integration-api/resource-policies.h new file mode 100644 index 0000000..4713fb3 --- /dev/null +++ b/dali/integration-api/resource-policies.h @@ -0,0 +1,48 @@ +#ifndef __DALI_INTEGRATION_RESOURCE_POLICIES_H__ +#define __DALI_INTEGRATION_RESOURCE_POLICIES_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Dali +{ +namespace ResourcePolicy +{ + +/** + * The data retention policy describes how dali should retain resource data. + */ +enum DataRetention +{ + DALI_RETAINS_ALL_DATA, // retains all data e.g. bitmaps + DALI_DISCARDS_ALL_DATA, // discards all data (expects application to regenerate UI on context loss) +}; + +/** + * The discardable policy describes whether a resource is owned or can be discarded. + * Discarded means that it can be released after uploading to GPU. + */ +enum Discardable +{ + OWNED_DISCARD, + OWNED_RETAIN, + NOT_OWNED +}; + +} // namespace ResourcePolicy +} // namespace Dali + +#endif // __DALI_INTEGRATION_DISCARD_POLICY_H__ diff --git a/dali/integration-api/resource-request.h b/dali/integration-api/resource-request.h new file mode 100644 index 0000000..6690c64 --- /dev/null +++ b/dali/integration-api/resource-request.h @@ -0,0 +1,203 @@ +#ifndef __DALI_INTEGRATION_RESOURCE_REQUEST_H__ +#define __DALI_INTEGRATION_RESOURCE_REQUEST_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +class RefObject; + +namespace Integration +{ + +// Resource Requests + +/** + * Used to return loaded resources for rendering etc. + */ +typedef IntrusivePtr ResourcePointer; + +/** + * Used to prioritize between loading operations. + */ +enum LoadResourcePriority +{ + LoadPriorityLowest, + LoadPriorityLow, + LoadPriorityNormal, + LoadPriorityHigh, + LoadPriorityHighest, +}; + +/** + * Used to request a resource from the native filesystem. + */ +class ResourceRequest +{ +public: + + /** + * Used to request a resource be accessed from the native filesystem. + * @param[in] newId A unique ID for this request. + * @param[in] resourceType The type of resource requested. The implementation of + * PlatformAbstraction::LoadResource() is responsible for + * converting the native file(s) to this type + * e.g. decoding a jpeg to a bitmap. + * @param[in] resourcePath The path of the resource; typically a filename. + * @param[in] loadPriority The priority of the request. + */ + ResourceRequest(ResourceId newId, + const ResourceType& resourceType, + const std::string& resourcePath, + LoadResourcePriority loadPriority = LoadPriorityNormal) + : id(newId), + type(NULL), + path(resourcePath), + priority(loadPriority) + { + type = resourceType.Clone(); + } + + /** + * Used to request or save a resource from/to the native filesystem. + * @param[in] newId A unique ID for this request. + * @param[in] resourceType The type of resource. + * @param[in] resourcePath The location of the resource / where the resource should be saved. + * @param[in] resourcePtr The resource to decode / save. + * @param[in] savePriority The priority of the request. + */ + ResourceRequest(ResourceId newId, + const ResourceType& resourceType, + const std::string& resourcePath, + ResourcePointer resourcePtr, + LoadResourcePriority savePriority = LoadPriorityNormal) + : id(newId), + type(NULL), + path(resourcePath), + resource(resourcePtr), + priority(savePriority) + { + type = resourceType.Clone(); + } + + /** + * Copy constructor. + * @param[in] request The resource request to copy. + */ + ResourceRequest(const ResourceRequest& request) + : id(request.id), + type(NULL), + path(request.path), + resource(request.resource), + priority(request.priority) + { + type = request.type->Clone(); + } + + /** + * Assignment operator. + * @param[in] rhs The resource request to copy. + */ + ResourceRequest& operator=(const ResourceRequest& rhs) + { + if( this != &rhs ) + { + id = rhs.id; + type = rhs.type->Clone(); + path = rhs.path; + resource = rhs.resource; + priority = rhs.priority; + } + + return *this; + } + + /** + * Non-virtual destructor; not intended as a base class + */ + ~ResourceRequest() + { + delete type; + } + + /** + * Retrieve the resource ID + * @return The ID + */ + ResourceId GetId() const + { + return id; + } + + /** + * Retrieve the resource type + * @return The type + */ + ResourceType* GetType() const + { + return type; + } + + /** + * Retrieve the resource path + * @return The path + */ + const std::string& GetPath() const + { + return path; + } + + /** + * Retrieve the resource (for save and decode requests) + * @return The resource + */ + ResourcePointer GetResource() const + { + return resource; + } + + /** + * Retrieve the load priority + * @return The priority + */ + LoadResourcePriority GetPriority() const + { + return priority; + } + +private: + + ResourceId id; + ResourceType* type; + std::string path; + /** When saving resources or decoding them, the resource data will be passed + * through in a reference counted object here. When Loading, it will be null. */ + ResourcePointer resource; + LoadResourcePriority priority; +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_RESOURCE_REQUEST_H__ diff --git a/dali/integration-api/resource-types.h b/dali/integration-api/resource-types.h new file mode 100644 index 0000000..1d5182e --- /dev/null +++ b/dali/integration-api/resource-types.h @@ -0,0 +1,239 @@ +#ifndef __DALI_INTEGRATION_RESOURCE_TYPES_H__ +#define __DALI_INTEGRATION_RESOURCE_TYPES_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +typedef Uint16Pair ImageDimensions; + +namespace Integration +{ + +// Resource Types + +/** + * Extendable set of resource types + */ +enum ResourceTypeId +{ + ResourceBitmap, + ResourceNativeImage, + ResourceTargetImage +}; + +/** + * The abstract base class for resource types. + */ +struct ResourceType +{ + /** + * Constructor. + * @param[in] typeId resource type id + */ + ResourceType(ResourceTypeId typeId) + : id(typeId) {} + + /** + * Destructor. + */ + virtual ~ResourceType() {} + + /** + * Create a copy of the resource type with the same attributes. + * @return pointer to the new ResourceType. + */ + virtual ResourceType* Clone() const = 0; + + const ResourceTypeId id; + +private: + + // Undefined copy constructor. + ResourceType(const ResourceType& typePath); + + // Undefined assignment operator. + ResourceType& operator=(const ResourceType& rhs); +}; + +/** + * BitmapResourceType describes a bitmap resource, which can be requested + * from ResourceLoader::LoadResource() or AllocateBitmapImage. + */ +struct BitmapResourceType : public ResourceType +{ + /** + * Constructor. + * @param[in] size The requested size for the bitmap. + * @param[in] scalingMode The method to use to map the source bitmap to the desired + * dimensions. + * @param[in] samplingMode The filter to use if the bitmap needs to be downsampled + * to the requested size. + * @param[in] orientationCorrection Whether to use bitmap metadata to rotate or + * flip the bitmap, e.g., from portrait to landscape. + */ + BitmapResourceType( ImageDimensions size = ImageDimensions( 0, 0 ), + FittingMode::Type scalingMode = FittingMode::DEFAULT, + SamplingMode::Type samplingMode = SamplingMode::DEFAULT, + bool orientationCorrection = true ) + : ResourceType(ResourceBitmap), + size(size), scalingMode(scalingMode), samplingMode(samplingMode), orientationCorrection(orientationCorrection) {} + + /** + * Destructor. + */ + virtual ~BitmapResourceType() {} + + /** + * @copydoc ResourceType::Clone + */ + virtual ResourceType* Clone() const + { + return new BitmapResourceType( size, scalingMode, samplingMode, orientationCorrection ); + } + + /** + * Attributes are copied from the request. + */ + ImageDimensions size; + FittingMode::Type scalingMode; + SamplingMode::Type samplingMode; + bool orientationCorrection; + +private: + + // Undefined copy constructor. + BitmapResourceType(const BitmapResourceType& typePath); + + // Undefined assignment operator. + BitmapResourceType& operator=(const BitmapResourceType& rhs); +}; + +/** + * NativeImageResourceType describes a native image resource, which can be injected + * through ResourceManager::AddNativeImage() or requested through ResourceLoader::LoadResource(). + * If the adaptor does not support NativeImages, it can fall back to Bitmap type. + */ +struct NativeImageResourceType : public ResourceType +{ + /** + * Constructor. + */ + NativeImageResourceType() + : ResourceType(ResourceNativeImage) {} + + /** + * Constructor. + * @param[in] dimensions Width and Height to allocate for image. + */ + NativeImageResourceType( ImageDimensions dimensions ) + : ResourceType(ResourceNativeImage), + imageDimensions(dimensions) {} + + /** + * Destructor. + */ + virtual ~NativeImageResourceType() {} + + /** + * @copydoc ResourceType::Clone + */ + virtual ResourceType* Clone() const + { + return new NativeImageResourceType(imageDimensions); + } + + /** + * Attributes are copied from the request (if supplied). + */ + ImageDimensions imageDimensions; + +private: + + // Undefined copy constructor. + NativeImageResourceType(const NativeImageResourceType& typePath); + + // Undefined assignment operator. + NativeImageResourceType& operator=(const NativeImageResourceType& rhs); +}; + +/** + * RenderTargetResourceType describes a bitmap resource, which can injected + * through ResourceManager::AddTargetImage() + */ +struct RenderTargetResourceType : public ResourceType +{ + /** + * Constructor. + */ + RenderTargetResourceType() + : ResourceType(ResourceTargetImage) {} + + /** + * Constructor. + * @param[in] dims Width and Height to allocate for image. + */ + RenderTargetResourceType( ImageDimensions dims ) + : ResourceType(ResourceTargetImage), + imageDimensions(dims) {} + + /** + * Destructor. + */ + virtual ~RenderTargetResourceType() {} + + /** + * @copydoc ResourceType::Clone + */ + virtual ResourceType* Clone() const + { + return new RenderTargetResourceType(imageDimensions); + } + + /** + * Image size is copied from the request. + */ + ImageDimensions imageDimensions; + +private: + + // Undefined copy constructor. + RenderTargetResourceType(const RenderTargetResourceType& typePath); + + // Undefined assignment operator. + RenderTargetResourceType& operator=(const RenderTargetResourceType& rhs); +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_RESOURCE_TYPES_H__ diff --git a/dali/integration-api/system-overlay.cpp b/dali/integration-api/system-overlay.cpp new file mode 100644 index 0000000..a6ab5ad --- /dev/null +++ b/dali/integration-api/system-overlay.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Integration +{ + +SystemOverlay::~SystemOverlay() +{ + delete mImpl; +} + +void SystemOverlay::Add( Actor actor ) +{ + mImpl->Add( GetImplementation(actor) ); +} + +void SystemOverlay::Remove( Actor actor ) +{ + mImpl->Remove( GetImplementation(actor) ); +} + +RenderTaskList SystemOverlay::GetOverlayRenderTasks() +{ + return RenderTaskList( &mImpl->GetOverlayRenderTasks() ); +} + +SystemOverlay::SystemOverlay( Internal::SystemOverlay* impl ) +: mImpl( impl ) +{ +} + +Internal::SystemOverlay* SystemOverlay::GetImpl() +{ + return mImpl; +} + +} // namespace Integration + +} // namespace Dali diff --git a/dali/integration-api/system-overlay.h b/dali/integration-api/system-overlay.h new file mode 100644 index 0000000..0d90702 --- /dev/null +++ b/dali/integration-api/system-overlay.h @@ -0,0 +1,104 @@ +#ifndef __DALI_INTEGRATION_SYSTEM_OVERLAY_H__ +#define __DALI_INTEGRATION_SYSTEM_OVERLAY_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +class Actor; +class RenderTaskList; + +namespace Internal +{ +class SystemOverlay; +} + +namespace Integration +{ + +/** + * Use this interface to draw content for system-level indicators, dialogs etc. + * The SystemOverlay is accessible using Dali::Integration::Core::GetSystemOverlay(). + */ +class DALI_IMPORT_API SystemOverlay +{ +public: + + /** + * Non-virtual destructor. SystemOverlay is not intended as a base class. + */ + ~SystemOverlay(); + + /** + * Add an Actor to the SystemOverlay. + * @pre The actor handle is not empty. + * @param [in] actor A handle to the actor to add. + * @post The actor will be referenced. + */ + void Add( Actor actor ); + + /** + * Remove an Actor that was added to the SystemOverlay. + * @pre The actor handle is not empty. + * @param [in] actor A handle to the actor to remove. + * @post The actor will be unreferenced. + */ + void Remove( Actor actor ); + + /** + * Retrieve the list of render-tasks for system-level overlays. + * This is a seperate list, processed after the render-tasks provided by Stage::GetRenderTaskList(). + * @return The list of overlay render-tasks. + */ + RenderTaskList GetOverlayRenderTasks(); + + /** + * Create the SystemOverlay entrance. + * This is not intended for adaptor implementors; see also Dali::Integration::Core::GetSystemOverlay(). + * @param[in] impl The SystemOverlay implementation. + */ + SystemOverlay( Internal::SystemOverlay* impl ); + + /** + * Retreive the internal implementation; this is not intended for adaptor implementors. + * @return The SystemOverlay implementation. + */ + Internal::SystemOverlay* GetImpl(); + +private: + + // Undefined copy-constructor. + SystemOverlay( const SystemOverlay& core ); + + // Undefined assignment operator. + SystemOverlay& operator=( const SystemOverlay& rhs ); + +private: + + Dali::Internal::SystemOverlay* mImpl; +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTEGRATION_SYSTEM_OVERLAY_H__ diff --git a/dali/internal/common/blending-options.cpp b/dali/internal/common/blending-options.cpp new file mode 100644 index 0000000..181b8f6 --- /dev/null +++ b/dali/internal/common/blending-options.cpp @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace // unnamed namespace +{ + +using namespace Dali; + +const int MASK_SRC_FACTOR_RGB = 0x0000000F; +const int MASK_SRC_FACTOR_ALPHA = 0x000000F0; +const int MASK_DEST_FACTOR_RGB = 0x00000F00; +const int MASK_DEST_FACTOR_ALPHA = 0x0000F000; +const int MASK_EQUATION_RGB = 0x000F0000; +const int MASK_EQUATION_ALPHA = 0x00F00000; + +const int SHIFT_TO_SRC_FACTOR_RGB = 0; +const int SHIFT_TO_SRC_FACTOR_ALPHA = 4; +const int SHIFT_TO_DEST_FACTOR_RGB = 8; +const int SHIFT_TO_DEST_FACTOR_ALPHA = 12; +const int SHIFT_TO_EQUATION_RGB = 16; +const int SHIFT_TO_EQUATION_ALPHA = 20; + +static unsigned int CLEAR_BLEND_FUNC_MASK = 0xFFFF0000; // Bottom 16 bits cleared +static unsigned int CLEAR_BLEND_EQUATION_MASK = 0xFF00FFFF; // 8 bits cleared + +/** + * Utility to store one of the BlendFunc values. + * @param[out] options A bitmask used to store the BlendFunc values. + * @param[in] factor The BlendFunc value. + * @param[in] bitshift Used to shift to the correct part of options. + */ +void StoreBlendingFactor( unsigned int& options, BlendingFactor::Type factor, int bitShift ) +{ + switch ( factor ) + { + case BlendingFactor::ZERO: + options |= ( 0u << bitShift ); + break; + + case BlendingFactor::ONE: + options |= ( 1u << bitShift ); + break; + + case BlendingFactor::SRC_COLOR: + options |= ( 2u << bitShift ); + break; + + case BlendingFactor::ONE_MINUS_SRC_COLOR: + options |= ( 3u << bitShift ); + break; + + case BlendingFactor::SRC_ALPHA: + options |= ( 4u << bitShift ); + break; + + case BlendingFactor::ONE_MINUS_SRC_ALPHA: + options |= ( 5u << bitShift ); + break; + + case BlendingFactor::DST_ALPHA: + options |= ( 6u << bitShift ); + break; + + case BlendingFactor::ONE_MINUS_DST_ALPHA: + options |= ( 7u << bitShift ); + break; + + case BlendingFactor::DST_COLOR: + options |= ( 8u << bitShift ); + break; + + case BlendingFactor::ONE_MINUS_DST_COLOR: + options |= ( 9u << bitShift ); + break; + + case BlendingFactor::SRC_ALPHA_SATURATE: + options |= ( 10u << bitShift ); + break; + + case BlendingFactor::CONSTANT_COLOR: + options |= ( 11u << bitShift ); + break; + + case BlendingFactor::ONE_MINUS_CONSTANT_COLOR: + options |= ( 12u << bitShift ); + break; + + case BlendingFactor::CONSTANT_ALPHA: + options |= ( 13u << bitShift ); + break; + + case BlendingFactor::ONE_MINUS_CONSTANT_ALPHA: + options |= ( 14u << bitShift ); + break; + } +} + +/** + * Utility to store one of the BlendEquation values. + * @param[out] options A bitmask used to store the BlendEquation values. + * @param[in] factor The BlendEquation value. + * @param[in] bitshift Used to shift to the correct part of options. + */ +void StoreBlendingEquation( unsigned int& options, BlendingEquation::Type factor, int bitShift ) +{ + switch ( factor ) + { + case BlendingEquation::ADD: + options |= ( 0u << bitShift ); + break; + + case BlendingEquation::SUBTRACT: + options |= ( 1u << bitShift ); + break; + + case BlendingEquation::REVERSE_SUBTRACT: + options |= ( 2u << bitShift ); + break; + } +} + +const unsigned int BLENDING_FACTOR_COUNT = 15; +const unsigned int BLENDING_EQUATION_COUNT = 3; + +BlendingFactor::Type BLENDING_FACTORS[ BLENDING_FACTOR_COUNT ] = + { BlendingFactor::ZERO, + BlendingFactor::ONE, + BlendingFactor::SRC_COLOR, + BlendingFactor::ONE_MINUS_SRC_COLOR, + BlendingFactor::SRC_ALPHA, + BlendingFactor::ONE_MINUS_SRC_ALPHA, + BlendingFactor::DST_ALPHA, + BlendingFactor::ONE_MINUS_DST_ALPHA, + BlendingFactor::DST_COLOR, + BlendingFactor::ONE_MINUS_DST_COLOR, + BlendingFactor::SRC_ALPHA_SATURATE, + BlendingFactor::CONSTANT_COLOR, + BlendingFactor::ONE_MINUS_CONSTANT_COLOR, + BlendingFactor::CONSTANT_ALPHA, + BlendingFactor::ONE_MINUS_CONSTANT_ALPHA }; + +BlendingEquation::Type BLENDING_EQUATIONS[ BLENDING_EQUATION_COUNT ] = + { BlendingEquation::ADD, + BlendingEquation::SUBTRACT, + BlendingEquation::REVERSE_SUBTRACT }; + +/** + * Utility to retrieve one of the BlendFunc values. + * @param[in] options A bitmask of blending values. + * @param[in] mask The used to mask unwanted values. + * @param[in] bitshift Used to shift to the correct part of options. + * @return The blending factor. + */ +BlendingFactor::Type RetrieveBlendingFactor( unsigned int options, int mask, int bitShift ) +{ + unsigned int index = options & mask; + index = index >> bitShift; + + DALI_ASSERT_DEBUG( index < BLENDING_FACTOR_COUNT ); + + return BLENDING_FACTORS[ index ]; +} + +/** + * Utility to retrieve one of the BlendEquation values. + * @param[in] options A bitmask of blending values. + * @param[in] mask The used to mask unwanted values. + * @param[in] bitshift Used to shift to the correct part of options. + * @return The blending equation. + */ +BlendingEquation::Type RetrieveBlendingEquation( unsigned int options, int mask, int bitShift ) +{ + unsigned int index = options & mask; + index = index >> bitShift; + + DALI_ASSERT_DEBUG( index < BLENDING_EQUATION_COUNT ); + + return BLENDING_EQUATIONS[ index ]; +} + +} // unnamed namespace + +namespace Dali +{ + +namespace Internal +{ + +BlendingOptions::BlendingOptions() +: mBitmask( 0u ), + mOptionalColor( NULL ) +{ + SetBlendFunc( DEFAULT_BLENDING_SRC_FACTOR_RGB, DEFAULT_BLENDING_DEST_FACTOR_RGB, + DEFAULT_BLENDING_SRC_FACTOR_ALPHA, DEFAULT_BLENDING_DEST_FACTOR_ALPHA ); + + SetBlendEquation( DEFAULT_BLENDING_EQUATION_RGB, DEFAULT_BLENDING_EQUATION_ALPHA ); +} + +BlendingOptions::~BlendingOptions() +{ + delete mOptionalColor; +} + +void BlendingOptions::SetBitmask( unsigned int bitmask ) +{ + mBitmask = bitmask; +} + +unsigned int BlendingOptions::GetBitmask() const +{ + return mBitmask; +} + +void BlendingOptions::SetBlendFunc( BlendingFactor::Type srcFactorRgb, BlendingFactor::Type destFactorRgb, + BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha ) +{ + mBitmask &= CLEAR_BLEND_FUNC_MASK; // Clear the BlendFunc values + + StoreBlendingFactor( mBitmask, srcFactorRgb, SHIFT_TO_SRC_FACTOR_RGB ); + StoreBlendingFactor( mBitmask, destFactorRgb, SHIFT_TO_DEST_FACTOR_RGB ); + StoreBlendingFactor( mBitmask, srcFactorAlpha, SHIFT_TO_SRC_FACTOR_ALPHA ); + StoreBlendingFactor( mBitmask, destFactorAlpha, SHIFT_TO_DEST_FACTOR_ALPHA ); +} + +BlendingFactor::Type BlendingOptions::GetBlendSrcFactorRgb() const +{ + return RetrieveBlendingFactor( mBitmask, MASK_SRC_FACTOR_RGB, SHIFT_TO_SRC_FACTOR_RGB ); +} + +BlendingFactor::Type BlendingOptions::GetBlendDestFactorRgb() const +{ + return RetrieveBlendingFactor( mBitmask, MASK_DEST_FACTOR_RGB, SHIFT_TO_DEST_FACTOR_RGB ); +} + +BlendingFactor::Type BlendingOptions::GetBlendSrcFactorAlpha() const +{ + return RetrieveBlendingFactor( mBitmask, MASK_SRC_FACTOR_ALPHA, SHIFT_TO_SRC_FACTOR_ALPHA ); +} + +BlendingFactor::Type BlendingOptions::GetBlendDestFactorAlpha() const +{ + return RetrieveBlendingFactor( mBitmask, MASK_DEST_FACTOR_ALPHA, SHIFT_TO_DEST_FACTOR_ALPHA ); +} + +void BlendingOptions::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha ) +{ + mBitmask &= CLEAR_BLEND_EQUATION_MASK; // Clear the BlendEquation values + + StoreBlendingEquation( mBitmask, equationRgb, SHIFT_TO_EQUATION_RGB ); + StoreBlendingEquation( mBitmask, equationAlpha, SHIFT_TO_EQUATION_ALPHA ); +} + +BlendingEquation::Type BlendingOptions::GetBlendEquationRgb() const +{ + return RetrieveBlendingEquation( mBitmask, MASK_EQUATION_RGB, SHIFT_TO_EQUATION_RGB ); +} + +BlendingEquation::Type BlendingOptions::GetBlendEquationAlpha() const +{ + return RetrieveBlendingEquation( mBitmask, MASK_EQUATION_ALPHA, SHIFT_TO_EQUATION_ALPHA ); +} + +bool BlendingOptions::SetBlendColor( const Vector4& color ) +{ + bool changed( false ); + + if( Vector4::ZERO == color ) + { + if( mOptionalColor ) + { + // Discard unnecessary vector + delete mOptionalColor; + mOptionalColor = NULL; + + changed = true; + } + } + else if( !mOptionalColor ) + { + // Lazy allocation when non-default is set + mOptionalColor = new Vector4( color ); + changed = true; + } + else if( *mOptionalColor != color ) + { + *mOptionalColor = color; + changed = true; + } + + return changed; +} + +const Vector4* BlendingOptions::GetBlendColor() const +{ + return mOptionalColor; +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/common/blending-options.h b/dali/internal/common/blending-options.h new file mode 100644 index 0000000..cc6a938 --- /dev/null +++ b/dali/internal/common/blending-options.h @@ -0,0 +1,129 @@ +#ifndef __DALI_BLENDING_OPTIONS_H__ +#define __DALI_BLENDING_OPTIONS_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +// This is an optimization to avoid storing 6 separate blending values +struct BlendingOptions +{ + /** + * Create some default blending options. + */ + BlendingOptions(); + + /** + * Non-virtual destructor. + */ + ~BlendingOptions(); + + /** + * Set the blending options. + * @param[in] A bitmask of blending options. + */ + void SetBitmask( unsigned int bitmask ); + + /** + * Retrieve the blending options as a bitmask. + * @return A bitmask of blending options. + */ + unsigned int GetBitmask() const; + + /** + * @copydoc Dali::RenderableActor::SetBlendFunc() + */ + void SetBlendFunc( BlendingFactor::Type srcFactorRgb, BlendingFactor::Type destFactorRgb, + BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha ); + + /** + * @copydoc Dali::RenderableActor::GetBlendFunc() + */ + BlendingFactor::Type GetBlendSrcFactorRgb() const; + + /** + * @copydoc Dali::RenderableActor::GetBlendFunc() + */ + BlendingFactor::Type GetBlendDestFactorRgb() const; + + /** + * @copydoc Dali::RenderableActor::GetBlendFunc() + */ + BlendingFactor::Type GetBlendSrcFactorAlpha() const; + + /** + * @copydoc Dali::RenderableActor::GetBlendFunc() + */ + BlendingFactor::Type GetBlendDestFactorAlpha() const; + + /** + * @copydoc Dali::RenderableActor::SetBlendEquation() + */ + void SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha ); + + /** + * @copydoc Dali::RenderableActor::GetBlendEquation() + */ + BlendingEquation::Type GetBlendEquationRgb() const; + + /** + * @copydoc Dali::RenderableActor::GetBlendEquation() + */ + BlendingEquation::Type GetBlendEquationAlpha() const; + + /** + * Set the blend color. + * @param[in] color The blend color. + * @return True if the blend color changed, otherwise it was already the same color. + */ + bool SetBlendColor( const Vector4& color ); + + /** + * Query the blend color. + * The blend color, or NULL if no blend color was set. + */ + const Vector4* GetBlendColor() const; + +private: + + // Undefined copy constructor. + BlendingOptions(const BlendingOptions& typePath); + + // Undefined copy constructor. + BlendingOptions& operator=(const BlendingOptions& rhs); + +private: + + unsigned int mBitmask; ///< A bitmask of blending options + + Vector4* mOptionalColor; ///< A heap-allocated color (owned) +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_BLENDING_OPTIONS_H__ diff --git a/dali/internal/common/buffer-index.h b/dali/internal/common/buffer-index.h new file mode 100644 index 0000000..f5dee67 --- /dev/null +++ b/dali/internal/common/buffer-index.h @@ -0,0 +1,33 @@ +#ifndef __DALI_INTERNAL_BUFFER_INDEX_H__ +#define __DALI_INTERNAL_BUFFER_INDEX_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +namespace Dali +{ + +namespace Internal +{ + +typedef unsigned int BufferIndex; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_BUFFER_INDEX_H__ diff --git a/dali/internal/common/core-impl.cpp b/dali/internal/common/core-impl.cpp new file mode 100644 index 0000000..0489dcf --- /dev/null +++ b/dali/internal/common/core-impl.cpp @@ -0,0 +1,469 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using Dali::Internal::SceneGraph::UpdateManager; +using Dali::Internal::SceneGraph::RenderManager; +using Dali::Internal::SceneGraph::DiscardQueue; +using Dali::Internal::SceneGraph::RenderQueue; +using Dali::Internal::SceneGraph::TextureCache; + +namespace +{ +// The Update for frame N+1 may be processed whilst frame N is being rendered. +const unsigned int MAXIMUM_UPDATE_COUNT = 2u; + +#if defined(DEBUG_ENABLED) +Debug::Filter* gCoreFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CORE"); +#endif +} + +namespace Dali +{ + +namespace Internal +{ + +using Integration::RenderController; +using Integration::PlatformAbstraction; +using Integration::GlSyncAbstraction; +using Integration::GestureManager; +using Integration::GlAbstraction; +using Integration::Event; +using Integration::UpdateStatus; +using Integration::RenderStatus; + +Core::Core( RenderController& renderController, PlatformAbstraction& platform, + GlAbstraction& glAbstraction, GlSyncAbstraction& glSyncAbstraction, + GestureManager& gestureManager, ResourcePolicy::DataRetention dataRetentionPolicy) +: mRenderController( renderController ), + mPlatform(platform), + mGestureEventProcessor(NULL), + mEventProcessor(NULL), + mUpdateManager(NULL), + mRenderManager(NULL), + mDiscardQueue(NULL), + mResourcePostProcessQueue(), + mNotificationManager(NULL), + mImageFactory(NULL), + mShaderFactory(NULL), + mIsActive(true), + mProcessingEvent(false) +{ + // Create the thread local storage + CreateThreadLocalStorage(); + + // This does nothing until Core is built with --enable-performance-monitor + PERFORMANCE_MONITOR_INIT( platform ); + + mNotificationManager = new NotificationManager(); + + mAnimationPlaylist = AnimationPlaylist::New(); + + mPropertyNotificationManager = PropertyNotificationManager::New(); + + std::vector< ResourcePostProcessRequest> init; + mResourcePostProcessQueue = new ResourcePostProcessList(init); + + mRenderManager = RenderManager::New( glAbstraction, *mResourcePostProcessQueue ); + + RenderQueue& renderQueue = mRenderManager->GetRenderQueue(); + TextureCache& textureCache = mRenderManager->GetTextureCache(); + + ResourcePolicy::Discardable discardPolicy = ResourcePolicy::OWNED_DISCARD; + if( dataRetentionPolicy == ResourcePolicy::DALI_RETAINS_ALL_DATA ) + { + discardPolicy = ResourcePolicy::OWNED_RETAIN; + } + textureCache.SetDiscardBitmapsPolicy(discardPolicy); + + mDiscardQueue = new DiscardQueue( renderQueue ); + + mResourceManager = new ResourceManager( mPlatform, + *mNotificationManager, + textureCache, + *mResourcePostProcessQueue, + *mRenderManager, + *mDiscardQueue, + renderQueue ); + + mTouchResampler = TouchResampler::New(); + + mUpdateManager = new UpdateManager( *mNotificationManager, + glSyncAbstraction, + *mAnimationPlaylist, + *mPropertyNotificationManager, + *mResourceManager, + *mDiscardQueue, + renderController, + *mRenderManager, + renderQueue, + textureCache, + *mTouchResampler ); + + mRenderManager->SetShaderSaver( *mUpdateManager ); + + mStage = IntrusivePtr( Stage::New( *mAnimationPlaylist, *mPropertyNotificationManager, *mUpdateManager, *mNotificationManager ) ); + + // This must be called after stage is created but before stage initialization + mRelayoutController = IntrusivePtr< RelayoutController >( new RelayoutController( mRenderController ) ); + + mStage->Initialize(); + + mResourceClient = new ResourceClient( *mResourceManager, *mStage ); + + mGestureEventProcessor = new GestureEventProcessor(*mStage, gestureManager, mRenderController); + mEventProcessor = new EventProcessor(*mStage, *mNotificationManager, *mGestureEventProcessor); + + mImageFactory = new ImageFactory( *mResourceClient ); + mShaderFactory = new ShaderFactory(); + mUpdateManager->SetShaderSaver( *mShaderFactory ); + mShaderFactory->LoadDefaultShaders(); + + GetImplementation(Dali::TypeRegistry::Get()).CallInitFunctions(); +} + +Core::~Core() +{ + /** + * TODO this should be done by Adaptor, Core does not know about threading + * First stop the resource loading thread(s) + */ + mPlatform.JoinLoaderThreads(); + + /* + * The order of destructing these singletons is important!!! + */ + + // clear the thread local storage first + // allows core to be created / deleted many times in the same thread (how TET cases work). + // Do this before mStage.Reset() so Stage::IsInstalled() returns false + ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal(); + if( tls ) + { + tls->Remove(); + } + + // Stop relayout requests being raised on stage destruction + mRelayoutController.Reset(); + + // Clean-up stage - remove default camera and root layer + mStage->Uninitialize(); + + // remove (last?) reference to stage + mStage.Reset(); + + delete mEventProcessor; + delete mGestureEventProcessor; + delete mNotificationManager; + delete mImageFactory; + delete mShaderFactory; + delete mResourceClient; + delete mResourceManager; + delete mUpdateManager; + delete mTouchResampler; + delete mRenderManager; + delete mDiscardQueue; + delete mResourcePostProcessQueue; +} + +Integration::ContextNotifierInterface* Core::GetContextNotifier() +{ + return mStage.Get(); +} + +void Core::RecoverFromContextLoss() +{ + DALI_LOG_INFO(gCoreFilter, Debug::Verbose, "Core::RecoverFromContextLoss()\n"); + + mImageFactory->RecoverFromContextLoss(); // Reload images from files + mStage->GetRenderTaskList().RecoverFromContextLoss(); // Re-trigger render-tasks +} + +void Core::ContextCreated() +{ + mRenderManager->ContextCreated(); +} + +void Core::ContextDestroyed() +{ + mRenderManager->ContextDestroyed(); +} + +void Core::SurfaceResized( unsigned int width, unsigned int height ) +{ + mStage->SetSize( width, height ); + mRelayoutController->SetStageSize( width, height ); +} + +void Core::SetDpi( unsigned int dpiHorizontal, unsigned int dpiVertical ) +{ + mPlatform.SetDpi( dpiHorizontal, dpiVertical ); + mStage->SetDpi( Vector2( dpiHorizontal , dpiVertical) ); +} + +void Core::Update( float elapsedSeconds, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds, Integration::UpdateStatus& status ) +{ + // set the time delta so adaptor can easily print FPS with a release build with 0 as + // it is cached by frametime + status.secondsFromLastFrame = elapsedSeconds; + + // Render returns true when there are updates on the stage or one or more animations are completed. + // Use the estimated time diff till we render as the elapsed time. + status.keepUpdating = mUpdateManager->Update( elapsedSeconds, + lastVSyncTimeMilliseconds, + nextVSyncTimeMilliseconds ); + + // Check the Notification Manager message queue to set needsNotification + status.needsNotification = mNotificationManager->MessagesToProcess(); + + // No need to keep update running if there are notifications to process. + // Any message to update will wake it up anyways + + if ( mResourceManager->ResourcesToProcess() ) + { + // If we are still processing resources, then we have to continue the update + status.keepUpdating |= Integration::KeepUpdating::LOADING_RESOURCES; + } +} + +void Core::Render( RenderStatus& status ) +{ + bool updateRequired = mRenderManager->Render( status ); + + status.SetNeedsUpdate( updateRequired ); +} + +void Core::Suspend() +{ + mPlatform.Suspend(); + + mIsActive = false; +} + +void Core::Resume() +{ + mPlatform.Resume(); + + mIsActive = true; + + // trigger processing of events queued up while paused + ProcessEvents(); +} + +void Core::SceneCreated() +{ + mStage->EmitSceneCreatedSignal(); + + mRelayoutController->OnApplicationSceneCreated(); +} + +void Core::QueueEvent( const Integration::Event& event ) +{ + mEventProcessor->QueueEvent( event ); +} + +void Core::ProcessEvents() +{ + // Guard against calls to ProcessEvents() during ProcessEvents() + if( mProcessingEvent ) + { + DALI_LOG_ERROR( "ProcessEvents should not be called from within ProcessEvents!" ); + mRenderController.RequestProcessEventsOnIdle(); + return; + } + + mProcessingEvent = true; + mRelayoutController->SetProcessingCoreEvents( true ); + + // Signal that any messages received will be flushed soon + mUpdateManager->EventProcessingStarted(); + + mEventProcessor->ProcessEvents(); + + mNotificationManager->ProcessMessages(); + + // Avoid allocating MessageBuffers, triggering size-negotiation or sending any other spam whilst paused + if( mIsActive ) + { + // Emit signal here to start size negotiation and control relayout. + mStage->EmitEventProcessingFinishedSignal(); + + // Run the size negotiation after event processing finished signal + mRelayoutController->Relayout(); + + // Flush discard queue for image factory + mImageFactory->FlushReleaseQueue(); + + // Flush any queued messages for the update-thread + const bool messagesToProcess = mUpdateManager->FlushQueue(); + + // Check if the touch or gestures require updates. + const bool touchNeedsUpdate = mTouchResampler->NeedsUpdate(); + const bool gestureNeedsUpdate = mGestureEventProcessor->NeedsUpdate(); + + if( messagesToProcess || touchNeedsUpdate || gestureNeedsUpdate ) + { + // tell the render controller to keep update thread running + mRenderController.RequestUpdate(); + } + } + + mRelayoutController->SetProcessingCoreEvents( false ); + + // ProcessEvents() may now be called again + mProcessingEvent = false; +} + +void Core::UpdateTouchData(const Integration::TouchData& touch) +{ + mTouchResampler->SendTouchData( touch ); +} + +unsigned int Core::GetMaximumUpdateCount() const +{ + return MAXIMUM_UPDATE_COUNT; +} + +Integration::SystemOverlay& Core::GetSystemOverlay() +{ + return mStage->GetSystemOverlay(); +} + +void Core::SetViewMode( ViewMode viewMode ) +{ + mStage->SetViewMode( viewMode ); +} + +ViewMode Core::GetViewMode() const +{ + return mStage->GetViewMode(); +} + +void Core::SetStereoBase( float stereoBase ) +{ + mStage->SetStereoBase( stereoBase ); +} + +float Core::GetStereoBase() const +{ + return mStage->GetStereoBase(); +} + +void Core::SetPixmapYInverted( bool yInverted ) +{ + mRenderManager->SetPixmapYInverted( yInverted ); +} + +StagePtr Core::GetCurrentStage() +{ + return mStage.Get(); +} + +PlatformAbstraction& Core::GetPlatform() +{ + return mPlatform; +} + +UpdateManager& Core::GetUpdateManager() +{ + return *(mUpdateManager); +} + +RenderManager& Core::GetRenderManager() +{ + return *(mRenderManager); +} + +NotificationManager& Core::GetNotificationManager() +{ + return *(mNotificationManager); +} + +ResourceManager& Core::GetResourceManager() +{ + return *(mResourceManager); +} + +ResourceClient& Core::GetResourceClient() +{ + return *(mResourceClient); +} + +ImageFactory& Core::GetImageFactory() +{ + return *(mImageFactory); +} + +ShaderFactory& Core::GetShaderFactory() +{ + return *(mShaderFactory); +} + +GestureEventProcessor& Core::GetGestureEventProcessor() +{ + return *(mGestureEventProcessor); +} + +RelayoutController& Core::GetRelayoutController() +{ + return *(mRelayoutController.Get()); +} + +void Core::CreateThreadLocalStorage() +{ + // a pointer to the ThreadLocalStorage object will be stored in TLS + // and automatically deleted when the thread is killed + new ThreadLocalStorage(this); +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/common/core-impl.h b/dali/internal/common/core-impl.h new file mode 100644 index 0000000..8d130b4 --- /dev/null +++ b/dali/internal/common/core-impl.h @@ -0,0 +1,320 @@ +#ifndef __DALI_INTERNAL_CORE_H__ +#define __DALI_INTERNAL_CORE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Integration +{ +class RenderController; +class PlatformAbstraction; +class GestureManager; +class GlAbstraction; +class GlSyncAbstraction; +class SystemOverlay; +class UpdateStatus; +class RenderStatus; +struct Event; +struct TouchData; +} + +namespace Internal +{ + +class NotificationManager; +class AnimationPlaylist; +class PropertyNotificationManager; +class EventProcessor; +class GestureEventProcessor; +class ResourceClient; +class ResourceManager; +class ImageFactory; +class ShaderFactory; +class TouchResampler; +class RelayoutController; + +namespace SceneGraph +{ +class UpdateManager; +class RenderManager; +class DiscardQueue; +} + +/** + * Internal class for Dali::Integration::Core + */ +class Core +{ +public: + + /** + * Create and initialise a new Core instance + */ + Core( Integration::RenderController& renderController, + Integration::PlatformAbstraction& platform, + Integration::GlAbstraction& glAbstraction, + Integration::GlSyncAbstraction& glSyncAbstraction, + Integration::GestureManager& gestureManager, + ResourcePolicy::DataRetention dataRetentionPolicy ); + + /** + * Destructor + */ + ~Core(); + + /** + * @copydoc Dali::Integration::Core::GetContextNotifier() + */ + Integration::ContextNotifierInterface* GetContextNotifier(); + + /** + * @copydoc Dali::Integration::Core::ContextCreated() + */ + void ContextCreated(); + + /** + * @copydoc Dali::Integration::Core::ContextDestroyed() + */ + void ContextDestroyed(); + + /** + * @copydoc Dali::Integration::Core::RecoverFromContextLoss() + */ + void RecoverFromContextLoss(); + + /** + * @copydoc Dali::Integration::Core::SurfaceResized(unsigned int, unsigned int) + */ + void SurfaceResized(unsigned int width, unsigned int height); + + /** + * @copydoc Dali::Integration::Core::SetDpi(unsigned int, unsigned int) + */ + void SetDpi(unsigned int dpiHorizontal, unsigned int dpiVertical); + + /** + * @copydoc Dali::Integration::Core::SetMinimumFrameTimeInterval(unsigned int) + */ + void SetMinimumFrameTimeInterval(unsigned int interval); + + /** + * @copydoc Dali::Integration::Core::Update() + */ + void Update( float elapsedSeconds, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds, Integration::UpdateStatus& status ); + + /** + * @copydoc Dali::Integration::Core::Render() + */ + void Render( Integration::RenderStatus& status ); + + /** + * @copydoc Dali::Integration::Core::Suspend() + */ + void Suspend(); + + /** + * @copydoc Dali::Integration::Core::Resume() + */ + void Resume(); + + /** + * @copydoc Dali::Integration::Core::SceneCreated() + */ + void SceneCreated(); + + /** + * @copydoc Dali::Integration::Core::QueueEvent(const Integration::Event&) + */ + void QueueEvent( const Integration::Event& event ); + + /** + * @copydoc Dali::Integration::Core::ProcessEvents() + */ + void ProcessEvents(); + + /** + * @copydoc Dali::Integration::Core::UpdateTouchData(const Integration::TouchData&) + */ + void UpdateTouchData(const Integration::TouchData& touch); + + /** + * @copydoc Dali::Integration::Core::GetMaximumUpdateCount() + */ + unsigned int GetMaximumUpdateCount() const; + + /** + * @copydoc Dali::Integration::Core::GetSystemOverlay() + */ + Integration::SystemOverlay& GetSystemOverlay(); + + // Stereoscopy + + /** + * @copydoc Dali::Integration::Core::SetViewMode() + */ + void SetViewMode( ViewMode viewMode ); + + /** + * @copydoc Dali::Integration::Core::GetViewMode() + */ + ViewMode GetViewMode() const; + + /** + * @copydoc Dali::Integration::Core::SetStereoBase() + */ + void SetStereoBase( float stereoBase ); + + /** + * @copydoc Dali::Integration::Core::GetStereoBase() + */ + float GetStereoBase() const; + + // Pixmap + + /** + * @copydoc Dali::Integration::Core::SetPixmapYInverted() + */ + void SetPixmapYInverted( bool yInverted ); + +private: // for use by ThreadLocalStorage + + /** + * Returns the current stage. + * @return A smart-pointer to the current stage. + */ + StagePtr GetCurrentStage(); + + /** + * Returns the platform abstraction. + * @return A reference to the platform abstraction. + */ + Integration::PlatformAbstraction& GetPlatform(); + + /** + * Returns the update manager. + * @return A reference to the update manager. + */ + SceneGraph::UpdateManager& GetUpdateManager(); + + /** + * Returns the render manager. + * @return A reference to the render manager. + */ + SceneGraph::RenderManager& GetRenderManager(); + + /** + * Returns the notification manager. + * @return A reference to the Notification Manager. + */ + NotificationManager& GetNotificationManager(); + + /** + * Returns the Resource Manager. + * @return A reference to the Resource Manager. + */ + ResourceManager& GetResourceManager(); + + /** + * Returns the Resource client. + * @return A reference to the Resource Client. + */ + ResourceClient& GetResourceClient(); + + /** + * Returns the Image factory + * @return A reference to the Image factory. + */ + ImageFactory& GetImageFactory(); + + /** + * Returns the Shader factory + * @return A reference to the Shader binary factory. + */ + ShaderFactory& GetShaderFactory(); + + /** + * Returns the gesture event processor. + * @return A reference to the gesture event processor. + */ + GestureEventProcessor& GetGestureEventProcessor(); + + /** + * Return the relayout controller + * @Return Return a reference to the relayout controller + */ + RelayoutController& GetRelayoutController(); + +private: + + /** + * Undefined copy and assignment operators + */ + Core(const Core& core); // No definition + Core& operator=(const Core& core); // No definition + + /** + * Create Thread local storage + */ + void CreateThreadLocalStorage(); + +private: + + Integration::RenderController& mRenderController; ///< Reference to Render controller to tell it to keep rendering + Integration::PlatformAbstraction& mPlatform; ///< The interface providing platform specific services. + + IntrusivePtr mStage; ///< The current stage + GestureEventProcessor* mGestureEventProcessor; ///< The gesture event processor + EventProcessor* mEventProcessor; ///< The event processor + SceneGraph::UpdateManager* mUpdateManager; ///< Update manager + SceneGraph::RenderManager* mRenderManager; ///< Render manager + SceneGraph::DiscardQueue* mDiscardQueue; ///< Used to cleanup nodes & resources when no longer in use. + ResourcePostProcessList* mResourcePostProcessQueue; ///< Stores resource ids which require post processing after render + NotificationManager* mNotificationManager; ///< Notification manager + AnimationPlaylistOwner mAnimationPlaylist; ///< For 'Fire and forget' animation support + OwnerPointer mPropertyNotificationManager; ///< For safe signal emmision of property changed notifications + ImageFactory* mImageFactory; ///< Image resource factory + ShaderFactory* mShaderFactory; ///< Shader resource factory + ResourceClient* mResourceClient; ///< Asynchronous Resource Loading + ResourceManager* mResourceManager; ///< Asynchronous Resource Loading + TouchResampler* mTouchResampler; ///< Resamples touches to correct frame rate. + IntrusivePtr< RelayoutController > mRelayoutController; ///< Size negotiation relayout controller + + bool mIsActive : 1; ///< Whether Core is active or suspended + bool mProcessingEvent : 1; ///< True during ProcessEvents() + + friend class ThreadLocalStorage; + +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_CORE_H__ diff --git a/dali/internal/common/fixed-size-memory-pool.cpp b/dali/internal/common/fixed-size-memory-pool.cpp new file mode 100644 index 0000000..8b69193 --- /dev/null +++ b/dali/internal/common/fixed-size-memory-pool.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL HEADERS +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * @brief Private implementation class + */ +struct FixedSizeMemoryPool::Impl +{ + /** + * @brief Struct to represent a block of memory from which allocations can be made. + * + * The block forms a linked list. + */ + struct Block + { + void* blockMemory; ///< The allocated memory from which allocations can be made + Block* nextBlock; ///< The next block in the linked list + + /** + * @brief Construct a new block with given size + * + * @param size The size of the memory block to allocate in bytes. Must be non-zero. + */ + Block( SizeType size ) + : nextBlock( NULL ) + { + blockMemory = ::operator new( size ); + DALI_ASSERT_ALWAYS( blockMemory && "Out of memory" ); + } + + /** + * @brief Destructor + */ + ~Block() + { + ::operator delete( blockMemory ); + } + + private: + // Undefined + Block( const Block& block ); + + // Undefined + Block& operator=( const Block& block ); + }; + + /** + * @brief Constructor + */ + Impl( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity ) + : mFixedSize( fixedSize ), + mMemoryBlocks( initialCapacity * mFixedSize ), + mMaximumBlockCapacity( maximumBlockCapacity ), + mCurrentBlock( &mMemoryBlocks ), + mCurrentBlockCapacity( initialCapacity ), + mCurrentBlockSize( 0 ), + mDeletedObjects( NULL ) + { + // We need enough room to store the deleted list in the data + DALI_ASSERT_DEBUG( mFixedSize >= sizeof( void* ) ); + } + + /** + * @brief Destructor + */ + ~Impl() + { + // Clean up memory block linked list (mMemoryBlocks will be auto-destroyed by its destructor) + Block* block = mMemoryBlocks.nextBlock; + while( block ) + { + Block* nextBlock = block->nextBlock; + delete block; + block = nextBlock; + } + } + + /** + * @brief Allocate a new block for allocating memory from + */ + void AllocateNewBlock() + { + // Double capacity for the new block + SizeType size = mCurrentBlockCapacity * 2; + if( size > mMaximumBlockCapacity || size < mCurrentBlockCapacity ) // Check for overflow of size type + { + size = mMaximumBlockCapacity; + } + + mCurrentBlockCapacity = size; + + // Allocate + Block* block = new Block( mCurrentBlockCapacity * mFixedSize ); + mCurrentBlock->nextBlock = block; // Add to end of linked list + mCurrentBlock = block; + + mCurrentBlockSize = 0; + } + + SizeType mFixedSize; ///< The size of each allocation in bytes + + Block mMemoryBlocks; ///< Linked list of allocated memory blocks + SizeType mMaximumBlockCapacity; ///< The maximum allowed capacity of allocations in a new memory block + + Block* mCurrentBlock; ///< Pointer to the active block + SizeType mCurrentBlockCapacity; ///< The maximum number of allocations that can be allocated for the current block + SizeType mCurrentBlockSize; ///< The number of allocations allocated to the current block + + void* mDeletedObjects; ///< Pointer to the head of the list of deleted objects. The addresses are stored in the allocated memory blocks. +}; + +FixedSizeMemoryPool::FixedSizeMemoryPool( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity ) +{ + mImpl = new Impl( fixedSize, initialCapacity, maximumBlockCapacity ); +} + +FixedSizeMemoryPool::~FixedSizeMemoryPool() +{ + delete mImpl; +} + +void* FixedSizeMemoryPool::Allocate() +{ + // First, recycle deleted objects + if( mImpl->mDeletedObjects ) + { + void* recycled = mImpl->mDeletedObjects; + mImpl->mDeletedObjects = *( reinterpret_cast< void** >( mImpl->mDeletedObjects ) ); // Pop head off front of deleted objects list + return recycled; + } + + // Check if current block is full + if( mImpl->mCurrentBlockSize >= mImpl->mCurrentBlockCapacity ) + { + mImpl->AllocateNewBlock(); + } + + // Placement new the object in block memory + unsigned char* objectAddress = static_cast< unsigned char* >( mImpl->mCurrentBlock->blockMemory ); + objectAddress += mImpl->mCurrentBlockSize * mImpl->mFixedSize; + mImpl->mCurrentBlockSize++; + + return objectAddress; +} + +void FixedSizeMemoryPool::Free( void* memory ) +{ + // Add memory to head of deleted objects list. Store next address in the same memory space as the old object. + *( reinterpret_cast< void** >( memory ) ) = mImpl->mDeletedObjects; + mImpl->mDeletedObjects = memory; +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/common/fixed-size-memory-pool.h b/dali/internal/common/fixed-size-memory-pool.h new file mode 100644 index 0000000..4389106 --- /dev/null +++ b/dali/internal/common/fixed-size-memory-pool.h @@ -0,0 +1,109 @@ +#ifndef __DALI_INTERNAL_FIXED_SIZE_MEMORY_POOL_H__ +#define __DALI_INTERNAL_FIXED_SIZE_MEMORY_POOL_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * @brief Calculate the size of a type taking alignment into account + */ +template< typename T > +struct TypeSizeWithAlignment +{ + ///< The size of the type with alignment taken into account + static const size_t size = ( ( sizeof( T ) + sizeof( void* ) - 1 ) / sizeof( void* ) ) * sizeof( void* ); +}; + +/** + * @brief Memory pool for a given fixed size of memory. + * + * The pool will allocate and reclaim blocks of memory without concern for what is + * stored in them. This means it is up to the client to construct/destruct objects + * and hence determine what data type is stored in the memory block. See FixedSizeObjectAllocator + * below for an example client for creating objects of a given type. It is also up to the client + * to ensure that the size of the block takes memory alignment into account for the + * type of data they wish to store in the block. The TypeSizeWithAlignment template + * can be useful for determining the size of memory aligned blocks for a given type. + */ +class FixedSizeMemoryPool +{ +public: + + typedef uint32_t SizeType; + +public: + + /** + * @brief Constructor. + * + * @param fixedSize The fixed size of each memory allocation. Use TypeSizeWithAlignment if aligned memory is required. + * @param initialCapacity The initial size of the memory pool. Defaults to a small value (32) after + * which the capacity will double as needed. + * @param maximumBlockCapacity The maximum size that a new block of memory can be allocated. Defaults to + * a large value (1024 * 1024 = 1048576). + */ + explicit FixedSizeMemoryPool( SizeType fixedSize, SizeType initialCapacity = 32, SizeType maximumBlockCapacity = 1048576 ); + + /** + * @brief Destructor. + */ + ~FixedSizeMemoryPool(); + + /** + * @brief Allocate a new fixed size block of memory + * + * @return Return the newly allocated memory + */ + void* Allocate(); + + /** + * @brief Delete a block of memory for the allocation that has been allocated by this memory pool + * + * @param memory The memory to be deleted. Must have been allocated by this memory pool + */ + void Free( void* memory ); + +private: + + // Undefined + FixedSizeMemoryPool( const FixedSizeMemoryPool& fixedSizeMemoryPool ); + + // Undefined + FixedSizeMemoryPool& operator=( const FixedSizeMemoryPool& fixedSizeMemoryPool ); + +private: + + struct Impl; + Impl* mImpl; + +}; + +} // namespace Internal + +} // namespace Dali + +#endif /* __DALI_INTERNAL_FIXED_SIZE_MEMORY_POOL_H__ */ diff --git a/dali/internal/common/image-attributes.cpp b/dali/internal/common/image-attributes.cpp new file mode 100644 index 0000000..134debc --- /dev/null +++ b/dali/internal/common/image-attributes.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ +namespace Internal +{ + +const ImageAttributes ImageAttributes::DEFAULT_ATTRIBUTES; + +struct ImageAttributes::ImageAttributesImpl +{ + ImageAttributesImpl() + : width(0), + height(0), + scaling(Dali::FittingMode::SHRINK_TO_FIT), + filtering(SamplingMode::BOX), + mOrientationCorrection(false) + { + } + + ~ImageAttributesImpl() + { + } + + ImageAttributesImpl(const ImageAttributesImpl& rhs) + : width( rhs.width ), + height( rhs.height ), + scaling( rhs.scaling ), + filtering( rhs.filtering ), + mOrientationCorrection( rhs.mOrientationCorrection ) + { + } + + ImageAttributesImpl& operator=(const ImageAttributesImpl& rhs) + { + if (this != &rhs) + { + width = rhs.width; + height = rhs.height; + scaling = rhs.scaling; + filtering = rhs.filtering; + + mOrientationCorrection = rhs.mOrientationCorrection; + } + + return *this; + } + + unsigned int width : 16; ///< image width in pixels + unsigned int height : 16; ///< image height in pixels + ScalingMode scaling : 3; ///< scaling option, ShrinkToFit is default + FilterMode filtering : 3; ///< filtering option. Box is the default + bool mOrientationCorrection : 1; ///< If true, image pixels are reordered according to orientation metadata on load. + bool isDistanceField : 1; ///< true, if the image is a distancefield. Default is false. +}; + + +ImageAttributes::ImageAttributes() +: impl( new ImageAttributesImpl() ) +{ +} + +ImageAttributes::ImageAttributes(const ImageAttributes& rhs) +: impl( new ImageAttributesImpl(*rhs.impl) ) +{ +} + +ImageAttributes& ImageAttributes::operator=(const ImageAttributes& rhs) +{ + *impl = *rhs.impl; + + return *this; +} + +ImageAttributes::~ImageAttributes() +{ + delete impl; +} + +void ImageAttributes::SetSize(unsigned int width, unsigned int height) +{ + impl->width = width; + impl->height = height; +} + +void ImageAttributes::SetSize( const Size& size ) +{ + impl->width = size.width; + impl->height = size.height; +} + +void ImageAttributes::SetScalingMode( ScalingMode scale ) +{ + impl->scaling = scale; +} + +void ImageAttributes::SetFilterMode( FilterMode filtering ) +{ + impl->filtering = filtering; +} + +void ImageAttributes::SetOrientationCorrection(const bool enabled) +{ + impl->mOrientationCorrection = enabled; +} + +void ImageAttributes::Reset( ImageDimensions dimensions, ScalingMode scaling, FilterMode sampling, bool orientationCorrection ) +{ + impl->width = dimensions.GetWidth(); + impl->height = dimensions.GetHeight(); + impl->scaling = scaling; + impl->filtering = sampling; + impl->mOrientationCorrection = orientationCorrection; +} + +unsigned int ImageAttributes::GetWidth() const +{ + return impl->width; +} + +unsigned int ImageAttributes::GetHeight() const +{ + return impl->height; +} + +Size ImageAttributes::GetSize() const +{ + return Size(impl->width, impl->height); +} + +ImageAttributes::ScalingMode ImageAttributes::GetScalingMode() const +{ + return impl->scaling; +} + +ImageAttributes::FilterMode ImageAttributes::GetFilterMode() const +{ + return impl->filtering; +} + +bool ImageAttributes::GetOrientationCorrection() const +{ + return impl->mOrientationCorrection; +} + +ImageAttributes ImageAttributes::New() +{ + return ImageAttributes(); +} + +ImageAttributes ImageAttributes::New(unsigned int imageWidth, unsigned int imageHeight) +{ + ImageAttributes attributes; + attributes.impl->width = imageWidth; + attributes.impl->height = imageHeight; + return attributes; +} + +/** + * Less then comparison operator. + * @param [in] a parameter tested + * @param [in] b parameter tested + */ +bool operator<(const ImageAttributes& a, const ImageAttributes& b) +{ + // Bail out if one is distance field and the other is not. + if (a.impl->isDistanceField != b.impl->isDistanceField) + { + return a.impl->isDistanceField < b.impl->isDistanceField; + } + + if (a.impl->width != b.impl->width) + { + return a.impl->width < b.impl->width; + } + + if (a.impl->height != b.impl->height) + { + return a.impl->height < b.impl->height; + } + + if (a.impl->mOrientationCorrection != b.impl->mOrientationCorrection) + { + return a.impl->mOrientationCorrection < b.impl->mOrientationCorrection; + } + + if (a.impl->scaling != b.impl->scaling) + { + return a.impl->scaling < b.impl->scaling; + } + + if (a.impl->filtering != b.impl->filtering) + { + return a.impl->filtering < b.impl->filtering; + } + + // they are equal + return false; +} + +/** + * Equal to comparison operator. + * @param [in] a parameter tested for equality + * @param [in] b parameter tested for equality + */ +bool operator==(const ImageAttributes& a, const ImageAttributes& b) +{ + return a.impl->width == b.impl->width && + a.impl->height == b.impl->height && + a.impl->mOrientationCorrection == b.impl->mOrientationCorrection && + a.impl->scaling == b.impl->scaling && + a.impl->filtering == b.impl->filtering; +} + +/** + * Not equal to comparison operator. + * @param [in] a parameter tested for equality + * @param [in] b parameter tested for equality + */ +bool operator!=(const ImageAttributes& a, const ImageAttributes& b) +{ + return !(a == b); +} + +} // namespace Internal +} // namespace Dali diff --git a/dali/internal/common/image-attributes.h b/dali/internal/common/image-attributes.h new file mode 100644 index 0000000..a0803cb --- /dev/null +++ b/dali/internal/common/image-attributes.h @@ -0,0 +1,312 @@ +#ifndef __DALI_INTERNAL_IMAGE_ATTRIBUTES_H__ +#define __DALI_INTERNAL_IMAGE_ATTRIBUTES_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ +namespace Internal +{ + +/** + * @brief Describes Image properties like dimensions and pixel format and + * operations to be applied to images during the load process. + * + * ImageAttributes is used to define a set of properties of an image and a + * sequence of operations to be applied when loading it. + * + * The overall order of operations which can be applied is: + * 1. Determine the desired dimensions for the final bitmap. + * 2. Scale the image to fit the desired dimensions. + * + * The default for each stage is to do nothing. + * To enable a calculation of desired final image dimensions and fitting to it, SetSize() must be called. + * + * The loader does not guarantee to rescale a loaded image to the exact desired dimensions, but it will make a best effort to downscale images. + * The fitting to destination dimensions controlled by the ScalingMode may choose to fit to a larger area with an equivalent aspect ratio. + * If the requested dimensions are larger than the loaded ones, it will never upscale on load to fill them but will instead fit to smaller dimensions of identical aspect ratio. + * This is transparent to an application as the upscaling can happen during rendering. + * + * To enable scaling of images on load, desired dimensions must be set using SetSize(). + * Only one of the dimensions need be supplied, in which case, the other is calculated based on the aspect ratio of the raw loaded image. + * The desired dimensions 2-tuple 'd' is determined as follows for loaded image dimensions 'l' and 's', the dimensions tuple set with SetSize(): + * * `d = s, if s.x != 0 & s.y != 0, else:` + * * `d = [s.x, s.x * (l.y / l.x)], if s.x != 0 & s.y = 0, else:` + * * `d = [s.y * (l.x / l.y), s.y], if s.x = 0 & s.y != 0, else:` + * * `d = l, otherwise.` + * + * Use cases for scaling images on load include: + * 1. Full-screen image display: Limit loaded image resolution to device resolution using ShrinkToFit mode. + * 2. Thumbnail gallery grid: Limit loaded image resolution to screen tile using ScaleToFill mode. + * 3. Image columns: Limit loaded image resolution to column width using FitWidth mode. + * 4. Image rows: Limit loaded image resolution to row height using FitHeight mode. + * + * @note The aspect ratio of image contents is preserved by all scaling modes, so for example squares in input images stay square after loading. + */ +class ImageAttributes +{ +public: + + /** + * @brief Scaling options, used when resizing images on load to fit desired dimensions. + * + * A scaling mode controls the region of a loaded image to be mapped to the + * desired image rectangle specified using ImageAttributes.SetSize(). + * All scaling modes preserve the aspect ratio of the image contents. + */ + typedef Dali::FittingMode::Type ScalingMode; + + /** + * @brief Filtering options, used when resizing images on load to sample original pixels. + * + * A FilterMode controls how pixels in the raw image on-disk are sampled and + * combined to generate each pixel of the destination loaded image. + * + * @note NoFilter and Box modes do not guarantee that the loaded pixel array + * exactly matches the rectangle specified by the desired dimensions and + * ScalingMode, but all other filter modes do if the desired dimensions are + * `<=` the raw dimensions of the image file. + */ + typedef Dali::SamplingMode::Type FilterMode; + + static const ImageAttributes DEFAULT_ATTRIBUTES; ///< Default attributes have no size + + /** + * @brief Default constructor, initializes to default values. + */ + ImageAttributes(); + + /** + * @brief This copy constructor is required for correctly copying internal implementation. + * + * @param [in] rhs A reference to the copied handle + */ + ImageAttributes(const ImageAttributes& rhs); + + /** + * @brief This assignment operator is required for correctly handling the internal implementation. + * + * @param [in] rhs A reference to the copied handle + * @return a reference to this object + */ + ImageAttributes& operator=(const ImageAttributes& rhs); + + /** + * @brief Default destructor. + */ + ~ImageAttributes(); + + /** + * @brief Create an initialised image attributes object. + * + * @return A handle to a newly allocated object + */ + static ImageAttributes New(); + + /** + * @brief Create an initialised image attributes object. + * + * @param [in] width desired width. + * @param [in] height desired height + * @return A handle to a newly allocated object + */ + static ImageAttributes New(unsigned int width, unsigned int height); + + /** + * @brief Set the size properties. + * + * By default width and height are set to zero which means the image loaded has the original size. + * If one dimension is set to non-zero, but the other zeroed, the unspecified one is derived from + * the one that is set and the aspect ratio of the image. + * + * @param [in] width desired width. + * @param [in] height desired height + */ + void SetSize(unsigned int width, unsigned int height); + + /** + * @brief Set the image dimension properties. + * + * By default, width and height are set to zero which means the image loaded has the original size. + * If one dimension is set to non-zero, but the other zeroed, the unspecified one is derived from + * the one that is set and the aspect ratio of the image. + * + * @param [in] size desired size. + */ + void SetSize( const Size& size ); + + /** + * @brief Set the scale field of the image attributes. + * + * By default, ShrinkToFit is set. + * @param [in] scalingMode The desired scaling mode + */ + void SetScalingMode( ScalingMode scalingMode ); + + /** + * @brief Setter for the FilterMode. + * By default, Box is set. + * @param [in] filterMode The desired filter mode. + */ + void SetFilterMode( FilterMode filterMode ); + + /** + * @brief Set whether the image will be rotated/flipped back into portrait orientation. + * + * This will only be necessary if metadata indicates that the + * image has a different viewing orientation. + * + * This metadata, optionally present in formats that use exif for example, + * can encode the physical orientation of the camera which took the picture, + * establishing which directions in the image correspond to real-world "up" + * and the horizon. + * By default the metadata is ignored, but if this function is called with + * the value "true", the pixels of an image are reordered at load time to reflect + * the orientation in the metadata. + * + * @param [in] enabled If true, the image orientation metadata will be used to + * transform the pixels of the image as laid-out in memory. + */ + void SetOrientationCorrection(bool enabled); + + /** + * @brief Change all members in one operation. + * @param[in] dimensions width and height + * @param[in] scaling Scaling mode for resizing loads. + * @param[in] sampling Sampling mode. + * @param[in] orientation Orientation correction toggle. + */ + void Reset( ImageDimensions dimensions = ImageDimensions(0, 0), ScalingMode scaling = ScalingMode(), FilterMode sampling = FilterMode(), bool orientationCorrection = true ); + + + /** + * @brief Return the width currently represented by the attribute. + * + * @return width + */ + unsigned int GetWidth() const; + + /** + * @brief Return the height currently represented by the attribute. + * + * @return height + */ + unsigned int GetHeight() const; + + /** + * @brief Return the size currently represented by the attribute. + * + * @return size + */ + Size GetSize() const; + + /** + * @brief Return the scale currently represented by the attribute. + * + * @return scale + */ + ScalingMode GetScalingMode() const; + + /** + * @brief Getter for the FilterMode + * + * @return The FilterMode previously set, or the default value if none has + * been. + */ + FilterMode GetFilterMode() const; + + /** + * @brief Whether to correct for physical orientation of an image. + * + * @return Whether image pixels should be transformed according to the + * orientation metadata, if any. + */ + bool GetOrientationCorrection() const; + + /** + * @brief Less then comparison operator. + * + * @param [in] a parameter tested + * @param [in] b parameter tested + * @return true if a is less than b + */ + friend bool operator<(const ImageAttributes& a, const ImageAttributes& b); + + /** + * @brief Equal to comparison operator. + * + * @param [in] a parameter tested for equality + * @param [in] b parameter tested for equality + * @return true if a is equal to b + */ + friend bool operator==(const ImageAttributes& a, const ImageAttributes& b); + + /** + * @brief Not equal to comparison operator. + * + * @param [in] a parameter tested for equality + * @param [in] b parameter tested for equality + * @return true if a is not equal to b + */ + friend bool operator!=(const ImageAttributes& a, const ImageAttributes& b); + +private: + struct ImageAttributesImpl; + ImageAttributesImpl* impl; ///< Implementation pointer +}; + +/** + * @brief Less then comparison operator. + * + * @param [in] a parameter tested + * @param [in] b parameter tested + * @return true if a is less than b + */ +bool operator<(const ImageAttributes& a, const ImageAttributes& b); + +/** + * @brief Equal to comparison operator. + * + * @param [in] a parameter tested for equality + * @param [in] b parameter tested for equality + * @return true if a is equal to b + */ +bool operator==(const ImageAttributes& a, const ImageAttributes& b); + +/** + * @brief Not equal to comparison operator. + * + * @param [in] a parameter tested for equality + * @param [in] b parameter tested for equality + * @return true if a is not equal to b + */ +bool operator!=(const ImageAttributes& a, const ImageAttributes& b); + +} // namespace Internal +} // namespace Dali + +#endif // __DALI_INTERNAL_IMAGE_ATTRIBUTES_H__ diff --git a/dali/internal/common/image-sampler.cpp b/dali/internal/common/image-sampler.cpp new file mode 100644 index 0000000..036a69a --- /dev/null +++ b/dali/internal/common/image-sampler.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace ImageSampler +{ + +namespace +{ + +// @todo MESH_REWORK Remove file after image removal + +// Adjust these shift sizes if the FilterMode enum grows +const int MINIFY_BIT_SHIFT = 0; // Room for 16 +const int MAGNIFY_BIT_SHIFT = 4; + +const int MASK_MINIFY_FILTER = 0x0000000F; +const int MASK_MAGNIFY_FILTER = 0x000000F0; + +const unsigned int FILTER_MODE_COUNT = 4; + +FilterMode::Type FILTER_MODE_OPTIONS[ FILTER_MODE_COUNT ] = + { FilterMode::NONE, + FilterMode::DEFAULT, + FilterMode::NEAREST, + FilterMode::LINEAR }; + +} // namespace + +/** + * Utility to store one of the FilterMode values. + * @param[out] options A bitmask used to store the FilterMode values. + * @param[in] factor The FilterMode value. + * @param[in] bitshift Used to shift to the correct part of options. + */ +void StoreFilterMode( unsigned int& options, FilterMode::Type mode, int bitShift ) +{ + // Start shifting from 1 as 0 is the unassigned state + switch ( mode ) + { + case FilterMode::NONE: + { + // Nothing to do + break; + } + case FilterMode::DEFAULT: + { + options |= ( 1u << bitShift ); + break; + } + case FilterMode::NEAREST: + { + options |= ( 2u << bitShift ); + break; + } + case FilterMode::LINEAR: + { + options |= ( 3u << bitShift ); + break; + } + } +} + +/** + * Utility to retrieve one of the FilterMode values. + * @param[in] options A bitmask of filter values. + * @param[in] mask The used to mask unwanted values. + * @param[in] bitshift Used to shift to the correct part of options. + * @return Return the filter mode. + */ +FilterMode::Type RetrieveFilterMode( unsigned int options, int mask, int bitShift ) +{ + unsigned int index = options & mask; + + index = ( index >> bitShift ); // Zero based index for array + + DALI_ASSERT_DEBUG( index < FILTER_MODE_COUNT ); + + return FILTER_MODE_OPTIONS[ index ]; +} + +unsigned int PackBitfield( FilterMode::Type minify, FilterMode::Type magnify ) +{ + unsigned int bitfield = 0; + StoreFilterMode( bitfield, minify, MINIFY_BIT_SHIFT ); + StoreFilterMode( bitfield, magnify, MAGNIFY_BIT_SHIFT ); + return bitfield; +} + +FilterMode::Type GetMinifyFilterMode( unsigned int bitfield ) +{ + return RetrieveFilterMode( bitfield, MASK_MINIFY_FILTER, MINIFY_BIT_SHIFT ); +} + +FilterMode::Type GetMagnifyFilterMode( unsigned int bitfield ) +{ + return RetrieveFilterMode( bitfield, MASK_MAGNIFY_FILTER, MAGNIFY_BIT_SHIFT ); +} + +} // namespace ImageSampler + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/common/image-sampler.h b/dali/internal/common/image-sampler.h new file mode 100644 index 0000000..2ebd5a4 --- /dev/null +++ b/dali/internal/common/image-sampler.h @@ -0,0 +1,68 @@ +#ifndef __DALI_IMAGE_SAMPLER_H__ +#define __DALI_IMAGE_SAMPLER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * ImageSampler represents a set of sampling settings that can be applied to a texture. + */ +namespace ImageSampler +{ + /** + * @brief Pack the filter mode into a bitfield. + * + * @param[in] minify The minification filter. + * @param[in] magnify The magnification filter. + * @return Return the packed bitfield. + */ + unsigned int PackBitfield( FilterMode::Type minify, FilterMode::Type magnify ); + + /** + * @brief Return the minification filter from a packed bitfield. + * + * @return Return the minification filter. + */ + FilterMode::Type GetMinifyFilterMode( unsigned int bitfield ); + + /** + * @brief Return the magnification filter from a packed bitfield. + * + * @return Return the magnification filter. + */ + FilterMode::Type GetMagnifyFilterMode( unsigned int bitfield ); + +} // namespace ImageSampler + +} // namespace Internal + +} // namespace Dali + + +#endif // __DALI_INTERNAL_IMAGE_SAMPLER_H__ + + + diff --git a/dali/internal/common/internal-constants.cpp b/dali/internal/common/internal-constants.cpp new file mode 100644 index 0000000..bbbd31b --- /dev/null +++ b/dali/internal/common/internal-constants.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +const float Internal::FULLY_OPAQUE = 0.99f; +const float Internal::FULLY_TRANSPARENT = 0.01f; + +} // namespace Dali diff --git a/dali/internal/common/internal-constants.h b/dali/internal/common/internal-constants.h new file mode 100644 index 0000000..b0b3a75 --- /dev/null +++ b/dali/internal/common/internal-constants.h @@ -0,0 +1,36 @@ +#ifndef __DALI_INTERNAL_CONSTANTS_H__ +#define __DALI_INTERNAL_CONSTANTS_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +namespace Dali +{ + +namespace Internal +{ + +// Constants used by renderers and actors to determine if something is visible. +extern const float FULLY_OPAQUE; ///< Alpha values must drop below this, before an object is considered to be transparent. +extern const float FULLY_TRANSPARENT; ///< Alpha values must rise above this, before an object is considered to be visible. + +} // namespace Internal + +} // namespace Dali + + +#endif // __DALI_INTERNAL_CONSTANTS_H__ diff --git a/dali/internal/common/memory-pool-object-allocator.h b/dali/internal/common/memory-pool-object-allocator.h new file mode 100644 index 0000000..0349cf8 --- /dev/null +++ b/dali/internal/common/memory-pool-object-allocator.h @@ -0,0 +1,125 @@ +#ifndef __DALI_INTERNAL_MEMORY_POOL_OBJECT_ALLOCATOR_H__ +#define __DALI_INTERNAL_MEMORY_POOL_OBJECT_ALLOCATOR_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * @brief Helper for allocating/deallocating objects using a memory pool. + * + * This is a helper class for creating and destroying objects of a single given type. + * The type may be a class or POD. + * + */ +template< typename T > +class MemoryPoolObjectAllocator +{ +public: + + /** + * @brief Constructor + */ + MemoryPoolObjectAllocator() + : mPool( NULL ) + { + ResetMemoryPool(); + } + + /** + * @brief Destructor + */ + ~MemoryPoolObjectAllocator() + { + delete mPool; + } + + /** + * @brief Allocate from the memory pool + * + * @return Return the allocated object + */ + T* Allocate() + { + return new ( mPool->Allocate() ) T(); + } + + /** + * @brief Allocate a block of memory from the memory pool of the appropriate size to + * store an object of type T. This is usually so the memory can be used in a + * placement new for an object of type T with a constructor that takes multiple + * parameters. + * + * @return Return the allocated memory block + */ + void* AllocateRaw() + { + return mPool->Allocate(); + } + + /** + * @brief Return the object to the memory pool + * + * @param object Pointer to the object to delete + */ + void Free( T* object ) + { + object->~T(); + + mPool->Free( object ); + } + + /** + * @brief Reset the memory pool, unloading all block memory previously allocated + */ + void ResetMemoryPool() + { + if( mPool ) + { + delete mPool; + } + + mPool = new FixedSizeMemoryPool( TypeSizeWithAlignment< T >::size ); + } + +private: + + // Undefined + MemoryPoolObjectAllocator( const MemoryPoolObjectAllocator& memoryPoolObjectAllocator ); + + // Undefined + MemoryPoolObjectAllocator& operator=( const MemoryPoolObjectAllocator& memoryPoolObjectAllocator ); + +private: + + FixedSizeMemoryPool* mPool; ///< Memory pool from which allocations are made + +}; + +} // namespace Internal + +} // namespace Dali + +#endif /* __DALI_INTERNAL_MEMORY_POOL_OBJECT_ALLOCATOR_H__ */ diff --git a/dali/internal/common/message-buffer.cpp b/dali/internal/common/message-buffer.cpp new file mode 100644 index 0000000..22822aa --- /dev/null +++ b/dali/internal/common/message-buffer.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include + +// INTERNAL INCLUDES +#include + +namespace // unnamed namespace +{ + +// Increase capacity by 1.5 when buffer limit reached +const unsigned int INCREMENT_NUMERATOR = 3u; +const unsigned int INCREMENT_DENOMINATOR = 2u; + +const unsigned int MESSAGE_SIZE_FIELD = 1u; // Size required to mark the message size +const unsigned int MESSAGE_END_FIELD = 1u; // Size required to mark the end of messages + +const unsigned int MESSAGE_SIZE_PLUS_END_FIELD = MESSAGE_SIZE_FIELD + MESSAGE_END_FIELD; + +const unsigned int MAX_DIVISION_BY_WORD_REMAINDER = sizeof(Dali::Internal::MessageBuffer::WordType) - 1u; // For word alignment on ARM +const unsigned int WORD_SIZE = sizeof(Dali::Internal::MessageBuffer::WordType); + +} // unnamed namespace + +namespace Dali +{ + +namespace Internal +{ + +MessageBuffer::MessageBuffer( std::size_t initialCapacity ) +: mInitialCapacity( initialCapacity / WORD_SIZE ), + mData( NULL ), + mNextSlot( NULL ), + mCapacity( 0 ), + mSize( 0 ) +{ +} + +MessageBuffer::~MessageBuffer() +{ + free( mData ); +} + +unsigned int* MessageBuffer::ReserveMessageSlot( std::size_t size ) +{ + Dali::Mutex::ScopedLock lock(mMutex); + DALI_ASSERT_DEBUG( 0 != size ); + + // Number of aligned words required to handle a message of size in bytes + std::size_t requestedSize = (size + MAX_DIVISION_BY_WORD_REMAINDER) / WORD_SIZE; + std::size_t requiredSize = requestedSize + MESSAGE_SIZE_PLUS_END_FIELD; + + // Keep doubling the additional capacity until we have enough + std::size_t nextCapacity = mCapacity ? mCapacity : mInitialCapacity; + + if ( (nextCapacity - mSize) < requiredSize ) + { + nextCapacity = nextCapacity * INCREMENT_NUMERATOR / INCREMENT_DENOMINATOR; + + // Something has gone badly wrong if requiredSize is this big + DALI_ASSERT_DEBUG( (nextCapacity - mSize) > requiredSize ); + } + + if ( nextCapacity > mCapacity ) + { + IncreaseCapacity( nextCapacity ); + } + + // Now reserve the slot + WordType* slot = mNextSlot; + + *slot++ = requestedSize; // Object size marker is stored in first word + + mSize += requestedSize + MESSAGE_SIZE_FIELD; + mNextSlot = mData + mSize; + + // End marker + *mNextSlot = 0; + + // @todo Remove cast & change all messages to use WordType instead + return reinterpret_cast(slot); +} + +std::size_t MessageBuffer::GetCapacity() const +{ + return mCapacity * WORD_SIZE; +} + +MessageBuffer::Iterator MessageBuffer::Begin() const +{ + if ( 0 != mSize ) + { + return Iterator( mData ); + } + + return Iterator( NULL ); +} + +void MessageBuffer::Reset() +{ + // All messages have been processed, reset the buffer + mSize = 0; + mNextSlot = mData; +} + +void MessageBuffer::IncreaseCapacity( std::size_t newCapacity ) +{ + DALI_ASSERT_DEBUG( newCapacity > mCapacity ); + + if ( mData ) + { + // Often this avoids the need to copy memory + + WordType* oldData = mData; + mData = reinterpret_cast( realloc( mData, newCapacity * WORD_SIZE ) ); + + // if realloc fails the old data is still valid + if( !mData ) + { + // TODO: Process message queue to free up some data? + free(oldData); + DALI_ASSERT_DEBUG( false && "Realloc failed we're out of memory!" ); + } + } + else + { + mData = reinterpret_cast( malloc( newCapacity * WORD_SIZE ) ); + } + DALI_ASSERT_ALWAYS( NULL != mData ); + + mCapacity = newCapacity; + mNextSlot = mData + mSize; +} + +MessageBuffer::Iterator::Iterator(WordType* current) +: mCurrent(current), + mMessageSize(0) +{ + if( NULL != mCurrent ) + { + // The first word is the size of the following object + mMessageSize = *mCurrent++; + } +} + +MessageBuffer::Iterator::Iterator(const Iterator& copy) +: mCurrent( copy.mCurrent ), + mMessageSize( copy.mMessageSize ) +{ +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/common/message-buffer.h b/dali/internal/common/message-buffer.h new file mode 100644 index 0000000..d731b9d --- /dev/null +++ b/dali/internal/common/message-buffer.h @@ -0,0 +1,156 @@ +#ifndef __DALI_INTERNAL_MESSAGE_BUFFER_H__ +#define __DALI_INTERNAL_MESSAGE_BUFFER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * Utility class to reserve a buffer for storing messages. + */ +class MessageBuffer +{ +public: + typedef std::ptrdiff_t WordType; + + /** + * Create a new MessageBuffer + * @param[in] The smallest capacity which the buffer will allocate, with respect to the size of type "char". + * @note The buffer will not allocate memory until the first call to ReserveMessageSlot(). + */ + MessageBuffer( std::size_t initialCapacity ); + + /** + * Non-virtual destructor; not suitable as a base class + */ + ~MessageBuffer(); + + /** + * Reserve space for another message in the buffer. + * @pre size is greater than zero. + * @param[in] size The message size with respect to the size of type "char". + * @return A pointer to the address allocated for the message, aligned to a word boundary + */ + unsigned int* ReserveMessageSlot( std::size_t size ); + + /** + * Query the capacity of the message buffer. + * @return The capacity with respect to the size of type "char". + */ + std::size_t GetCapacity() const; + + /** + * Used to iterate though the messages in the buffer. + */ + class Iterator + { + public: + + // Constructor + Iterator(WordType* current); + + // Inlined for performance + bool IsValid() + { + // Valid until end marker has been found + return 0 != mMessageSize; + } + + // Inlined for performance + WordType* Get() + { + return ( 0 != mMessageSize ) ? mCurrent : NULL; + } + + // Inlined for performance + void Next() + { + // Jump to next object and read size + mCurrent += mMessageSize; + mMessageSize = *mCurrent++; + } + + // Copy constructor + Iterator(const Iterator& copy); + + private: + + // Undefined + Iterator& operator=(const Iterator& rhs); + + private: + + WordType* mCurrent; + std::size_t mMessageSize; + }; + + /** + * Returns an iterator to the first message in the buffer. + * There is no past-the-end iterator; use Iterator::IsValid() to determine when the has been reached. + * @note Adding more messages with ReserveMessageSlot() may corrupt this iterator. + * @return The iterator. + */ + Iterator Begin() const; + + /** + * Sets the size of the buffer to zero (does not deallocate memory) + */ + void Reset(); + +private: + + // Undefined + MessageBuffer(const MessageBuffer&); + + // Undefined + MessageBuffer& operator=(const MessageBuffer& rhs); + + /** + * Helper to increase the capacity of the buffer. + * @pre The newCapacity is greater than mCapacity. + * @param[in] The newCapacity + */ + void IncreaseCapacity( std::size_t newCapacity ); + +private: + + std::size_t mInitialCapacity; ///< The capacity to allocate during first call to ReserveMessageSlot + + WordType* mData; ///< The data allocated for the message buffer + WordType* mNextSlot; ///< The next free location in the buffer + + std::size_t mCapacity; ///< The memory allocated with respect to sizeof(WordType) + std::size_t mSize; ///< The memory reserved for messages with respect to sizeof(WordType) + Dali::Mutex mMutex; ///< Mutex to ensure correct access locking +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_MESSAGE_BUFFER_H__ diff --git a/dali/internal/common/message.h b/dali/internal/common/message.h new file mode 100644 index 0000000..201186c --- /dev/null +++ b/dali/internal/common/message.h @@ -0,0 +1,872 @@ +#ifndef __DALI_INTERNAL_MESSAGE_H__ +#define __DALI_INTERNAL_MESSAGE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * An abstract base class for messages queued across threads. + * Messages are only allowed to contain value objects, either copies of the parameters or pointers + * If message parameter type is & or const& the message will try to take a copy of the actual type + */ +class MessageBase +{ +public: + + /** + * Construct the message base. + */ + MessageBase( ) + { + } + + /** + * Virtual destructor + */ + virtual ~MessageBase() + { + } + + /** + * Called to process the message. + * @param [in] bufferIndex The current update/render buffer index (depending on which thread processes the message). + */ + virtual void Process( BufferIndex bufferIndex ) = 0; + +private: +}; + +/** + * Templated message which calls a member function of an object. + * This allows nodes etc. to be modified in a thread-safe manner, when the update occurs in a separate thread. + * The object lifetime must controlled i.e. not destroyed before the message is processed. + */ +template< typename T > +class Message : public MessageBase +{ +public: + + typedef void(T::*MemberFunction)(); + + /** + * Create a message. + * @note The object is expected to be const in the thread which sends this message. + * However it can be modified when Process() is called in a different thread. + * @param[in] obj The object to be updated in a separate thread. + * @param[in] member The member function of the object. + */ + Message( const T* obj, MemberFunction member ) + : MessageBase(), + object( const_cast< T* >( obj ) ), + memberFunction( member ) + { + } + + /** + * Virtual destructor + */ + virtual ~Message() + { + } + + /** + * @copydoc MessageBase::Process + */ + virtual void Process( BufferIndex /*bufferIndex*/ ) + { + DALI_ASSERT_DEBUG( object && "Message does not have an object" ); + (object->*memberFunction)(); + } + +private: + + T* object; + MemberFunction memberFunction; + +}; + +/** + * Templated message which calls a member function of an object. + * This overload passes one value-type parameter. + * Template parameters need to match the MemberFunction! + * The message will contain copy of the value (in case of & or const&) + */ +template< typename T, typename P > +class MessageValue1 : public MessageBase +{ +public: + + typedef void(T::*MemberFunction)( typename ParameterType< P >::PassingType ); + + /** + * Create a message. + * @note The object is expected to be const in the thread which sends this message. + * However it can be modified when Process() is called in a different thread. + * @param[in] obj The object. + * @param[in] member The member function of the object. + * @param[in] p1 The first value-type parameter to pass to the member function. + */ + MessageValue1( const T* obj, + MemberFunction member, + typename ParameterType< P >::PassingType p1 ) + : MessageBase(), + object( const_cast< T* >( obj ) ), + memberFunction( member ), + param1( p1 ) + { + } + + /** + * Virtual destructor + */ + virtual ~MessageValue1() + { + } + + /** + * @copydoc MessageBase::Process + */ + virtual void Process( BufferIndex /*bufferIndex*/ ) + { + DALI_ASSERT_DEBUG( object && "Message does not have an object" ); + (object->*memberFunction)( ParameterType< P >::PassObject( param1 ) ); + } + +private: + + T* object; + MemberFunction memberFunction; + typename ParameterType< P >::HolderType param1; + +}; + +/** + * Templated message which calls a member function of an object. + * This overload passes two value-type parameters. + * Template parameters need to match the MemberFunction! + * The message will contain copy of the value (in case of & or const&) + */ + +template< typename T, typename P1, typename P2 > +class MessageValue2 : public MessageBase +{ +public: + + typedef void(T::*MemberFunction)( + typename ParameterType< P1 >::PassingType, + typename ParameterType< P2 >::PassingType ); + + /** + * Create a message. + * @note The object is expected to be const in the thread which sends this message. + * However it can be modified when Process() is called in a different thread. + * @param[in] obj The object. + * @param[in] member The member function of the object. + * @param[in] p1 The first parameter to pass to the member function. + * @param[in] p2 The second parameter to pass to the member function. + */ + MessageValue2( const T* obj, + MemberFunction member, + typename ParameterType< P1 >::PassingType p1, + typename ParameterType< P2 >::PassingType p2 ) + : MessageBase(), + object( const_cast< T* >( obj ) ), + memberFunction( member ), + param1( p1 ), + param2( p2 ) + { + } + + /** + * Virtual destructor + */ + virtual ~MessageValue2() + { + } + + /** + * @copydoc MessageBase::Process + */ + virtual void Process( BufferIndex /*bufferIndex*/ ) + { + DALI_ASSERT_DEBUG( object && "Message does not have an object" ); + (object->*memberFunction)( + ParameterType< P1 >::PassObject( param1 ), + ParameterType< P2 >::PassObject( param2 ) ); + } + +private: + + T* object; + MemberFunction memberFunction; + typename ParameterType< P1 >::HolderType param1; + typename ParameterType< P2 >::HolderType param2; + +}; + +/** + * Templated message which calls a member function of an object. + * This overload passes three value-type parameters. + * Template parameters need to match the MemberFunction! + * The message will contain copy of the value (in case of & or const&) + */ +template< typename T, typename P1, typename P2, typename P3 > +class MessageValue3 : public MessageBase +{ +public: + + typedef void(T::*MemberFunction)( + typename ParameterType< P1 >::PassingType, + typename ParameterType< P2 >::PassingType, + typename ParameterType< P3 >::PassingType ); + + /** + * Create a message. + * @note The object is expected to be const in the thread which sends this message. + * However it can be modified when Process() is called in a different thread. + * @param[in] obj The object. + * @param[in] member The member function of the object. + * @param[in] p1 The first parameter to pass to the member function. + * @param[in] p2 The second parameter to pass to the member function. + * @param[in] p3 The third parameter to pass to the member function. + */ + MessageValue3( const T* obj, + MemberFunction member, + typename ParameterType< P1 >::PassingType p1, + typename ParameterType< P2 >::PassingType p2, + typename ParameterType< P3 >::PassingType p3 ) + : MessageBase(), + object( const_cast< T* >( obj ) ), + memberFunction( member ), + param1( p1 ), + param2( p2 ), + param3( p3 ) + { + } + + /** + * Virtual destructor + */ + virtual ~MessageValue3() + { + } + + /** + * @copydoc MessageBase::Process + */ + virtual void Process( BufferIndex /*bufferIndex*/ ) + { + DALI_ASSERT_DEBUG( object && "Message does not have an object" ); + (object->*memberFunction)( + ParameterType< P1 >::PassObject( param1 ), + ParameterType< P2 >::PassObject( param2 ), + ParameterType< P3 >::PassObject( param3 ) ); + } + +private: + + T* object; + MemberFunction memberFunction; + typename ParameterType< P1 >::HolderType param1; + typename ParameterType< P2 >::HolderType param2; + typename ParameterType< P3 >::HolderType param3; + +}; + +/** + * Templated message which calls a member function of an object. + * This overload passes four value-type parameters. + * Template parameters need to match the MemberFunction! + * The message will contain copy of the value (in case of & or const&) + */ +template< typename T, typename P1, typename P2, typename P3, typename P4 > +class MessageValue4 : public MessageBase +{ +public: + + typedef void(T::*MemberFunction)( + typename ParameterType< P1 >::PassingType, + typename ParameterType< P2 >::PassingType, + typename ParameterType< P3 >::PassingType, + typename ParameterType< P4 >::PassingType ); + + /** + * Create a message. + * @note The object is expected to be const in the thread which sends this message. + * However it can be modified when Process() is called in a different thread. + * @param[in] obj The object. + * @param[in] member The member function of the object. + * @param[in] p1 The first parameter to pass to the member function. + * @param[in] p2 The second parameter to pass to the member function. + * @param[in] p3 The third parameter to pass to the member function. + * @param[in] p4 The fourth parameter to pass to the member function. + */ + MessageValue4( const T* obj, + MemberFunction member, + typename ParameterType< P1 >::PassingType p1, + typename ParameterType< P2 >::PassingType p2, + typename ParameterType< P3 >::PassingType p3, + typename ParameterType< P4 >::PassingType p4 ) + : MessageBase(), + object( const_cast< T* >( obj ) ), + memberFunction( member ), + param1( p1 ), + param2( p2 ), + param3( p3 ), + param4( p4 ) + { + } + + /** + * Virtual destructor + */ + virtual ~MessageValue4() + { + } + + /** + * @copydoc MessageBase::Process + */ + virtual void Process( BufferIndex /*bufferIndex*/ ) + { + DALI_ASSERT_DEBUG( object && "Message does not have an object" ); + (object->*memberFunction)( + ParameterType< P1 >::PassObject( param1 ), + ParameterType< P2 >::PassObject( param2 ), + ParameterType< P3 >::PassObject( param3 ), + ParameterType< P4 >::PassObject( param4 ) ); + } + +private: + + T* object; + MemberFunction memberFunction; + typename ParameterType< P1 >::HolderType param1; + typename ParameterType< P2 >::HolderType param2; + typename ParameterType< P3 >::HolderType param3; + typename ParameterType< P4 >::HolderType param4; + +}; + +/** + * Templated message which calls a member function of an object. + * This overload passes five value-type parameters. + * Template parameters need to match the MemberFunction! + * The message will contain copy of the value (in case of & or const&) + */ +template< typename T, typename P1, typename P2, typename P3, typename P4, typename P5 > +class MessageValue5 : public MessageBase +{ +public: + + typedef void(T::*MemberFunction)( + typename ParameterType< P1 >::PassingType, + typename ParameterType< P2 >::PassingType, + typename ParameterType< P3 >::PassingType, + typename ParameterType< P4 >::PassingType, + typename ParameterType< P5 >::PassingType ); + + /** + * Create a message. + * @note The object is expected to be const in the thread which sends this message. + * However it can be modified when Process() is called in a different thread. + * @param[in] obj The object. + * @param[in] member The member function of the object. + * @param[in] p1 The first parameter to pass to the member function. + * @param[in] p2 The second parameter to pass to the member function. + * @param[in] p3 The third parameter to pass to the member function. + * @param[in] p4 The fourth parameter to pass to the member function. + * @param[in] p5 The fifth parameter to pass to the member function. + */ + MessageValue5( const T* obj, + MemberFunction member, + typename ParameterType< P1 >::PassingType p1, + typename ParameterType< P2 >::PassingType p2, + typename ParameterType< P3 >::PassingType p3, + typename ParameterType< P4 >::PassingType p4, + typename ParameterType< P5 >::PassingType p5 ) + : MessageBase(), + object( const_cast< T* >( obj ) ), + memberFunction( member ), + param1( p1 ), + param2( p2 ), + param3( p3 ), + param4( p4 ), + param5( p5 ) + { + } + + /** + * Virtual destructor + */ + virtual ~MessageValue5() + { + } + + /** + * @copydoc MessageBase::Process + */ + virtual void Process( BufferIndex /*bufferIndex*/ ) + { + DALI_ASSERT_DEBUG( object && "Message does not have an object" ); + (object->*memberFunction)( + ParameterType< P1 >::PassObject( param1 ), + ParameterType< P2 >::PassObject( param2 ), + ParameterType< P3 >::PassObject( param3 ), + ParameterType< P4 >::PassObject( param4 ), + ParameterType< P5 >::PassObject( param5 ) ); + + } + +private: + + T* object; + MemberFunction memberFunction; + typename ParameterType< P1 >::HolderType param1; + typename ParameterType< P2 >::HolderType param2; + typename ParameterType< P3 >::HolderType param3; + typename ParameterType< P4 >::HolderType param4; + typename ParameterType< P5 >::HolderType param5; + +}; + +/** + * Templated message which calls a member function of an object. + * This overload passes six value-type parameters. + * Template parameters need to match the MemberFunction! + * The message will contain copy of the value (in case of & or const&) + */ +template< typename T, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6 > +class MessageValue6 : public MessageBase +{ +public: + + typedef void(T::*MemberFunction)( + typename ParameterType< P1 >::PassingType, + typename ParameterType< P2 >::PassingType, + typename ParameterType< P3 >::PassingType, + typename ParameterType< P4 >::PassingType, + typename ParameterType< P5 >::PassingType, + typename ParameterType< P6 >::PassingType ); + + /** + * Create a message. + * @note The object is expected to be const in the thread which sends this message. + * However it can be modified when Process() is called in a different thread. + * @param[in] obj The object. + * @param[in] member The member function of the object. + * @param[in] p1 The first parameter to pass to the member function. + * @param[in] p2 The second parameter to pass to the member function. + * @param[in] p3 The third parameter to pass to the member function. + * @param[in] p4 The fourth parameter to pass to the member function. + * @param[in] p5 The fifth parameter to pass to the member function. + * @param[in] p6 The sixth parameter to pass to the member function. + */ + MessageValue6( const T* obj, + MemberFunction member, + typename ParameterType< P1 >::PassingType p1, + typename ParameterType< P2 >::PassingType p2, + typename ParameterType< P3 >::PassingType p3, + typename ParameterType< P4 >::PassingType p4, + typename ParameterType< P5 >::PassingType p5, + typename ParameterType< P6 >::PassingType p6 ) + : MessageBase(), + object( const_cast< T* >( obj ) ), + memberFunction( member ), + param1( p1 ), + param2( p2 ), + param3( p3 ), + param4( p4 ), + param5( p5 ), + param6( p6 ) + { + } + + /** + * Virtual destructor + */ + virtual ~MessageValue6() + { + } + + /** + * @copydoc MessageBase::Process + */ + virtual void Process( BufferIndex /*bufferIndex*/ ) + { + DALI_ASSERT_DEBUG( object && "Message does not have an object" ); + (object->*memberFunction)( + ParameterType< P1 >::PassObject( param1 ), + ParameterType< P2 >::PassObject( param2 ), + ParameterType< P3 >::PassObject( param3 ), + ParameterType< P4 >::PassObject( param4 ), + ParameterType< P5 >::PassObject( param5 ), + ParameterType< P6 >::PassObject( param6 ) ); + + } + +private: + + T* object; + MemberFunction memberFunction; + typename ParameterType< P1 >::HolderType param1; + typename ParameterType< P2 >::HolderType param2; + typename ParameterType< P3 >::HolderType param3; + typename ParameterType< P4 >::HolderType param4; + typename ParameterType< P5 >::HolderType param5; + typename ParameterType< P6 >::HolderType param6; + +}; + +/** + * Templated message which calls a member function of an object. + * This overload passes just the buffer index to the method, no parameters. + */ +template< typename T > +class MessageDoubleBuffered0 : public MessageBase +{ +public: + + typedef void(T::*MemberFunction)( BufferIndex ); + + /** + * Create a message. + * @note The object is expected to be const in the thread which sends this message. + * However it can be modified when Process() is called in a different thread. + * @param[in] obj The object. + * @param[in] member The member function of the object. + */ + MessageDoubleBuffered0( const T* obj, MemberFunction member ) + : MessageBase(), + object( const_cast< T* >( obj ) ), + memberFunction( member ) + { + } + + /** + * Virtual destructor + */ + virtual ~MessageDoubleBuffered0() + { + } + + /** + * @copydoc MessageBase::Process + */ + virtual void Process( BufferIndex bufferIndex ) + { + DALI_ASSERT_DEBUG( object && "Message does not have an object" ); + (object->*memberFunction)( bufferIndex ); + } + +private: + + T* object; + MemberFunction memberFunction; + +}; + + +/** + * Templated message which calls a member function of an object. + * This overload passes a value-type to set a double-buffered property. + * Template parameters need to match the MemberFunction! + * The message will contain copy of the value (in case of & or const&) + */ +template< typename T, typename P > +class MessageDoubleBuffered1 : public MessageBase +{ +public: + + typedef void(T::*MemberFunction)( + BufferIndex, + typename ParameterType< P >::PassingType ); + + /** + * Create a message. + * @note The object is expected to be const in the thread which sends this message. + * However it can be modified when Process() is called in a different thread. + * @param[in] obj The object. + * @param[in] member The member function of the object. + * @param[in] p The second parameter to pass. + */ + MessageDoubleBuffered1( const T* obj, + MemberFunction member, + typename ParameterType< P >::PassingType p ) + : MessageBase(), + object( const_cast< T* >( obj ) ), + memberFunction( member ), + param( p ) + { + } + + /** + * Virtual destructor + */ + virtual ~MessageDoubleBuffered1() + { + } + + /** + * @copydoc MessageBase::Process + */ + virtual void Process( BufferIndex bufferIndex ) + { + DALI_ASSERT_DEBUG( object && "Message does not have an object" ); + (object->*memberFunction)( + bufferIndex, + ParameterType< P >::PassObject( param ) ); + } + +private: + + T* object; + MemberFunction memberFunction; + typename ParameterType< P >::HolderType param; + +}; + +/** + * Templated message which calls a member function of an object. + * This overload passes two value-types to set double-buffered properties. + * Template parameters need to match the MemberFunction! + * The message will contain copy of the value (in case of & or const&) + */ +template< typename T, typename P2, typename P3 > +class MessageDoubleBuffered2 : public MessageBase +{ +public: + + typedef void(T::*MemberFunction)( + BufferIndex, + typename ParameterType< P2 >::PassingType, + typename ParameterType< P3 >::PassingType ); + + /** + * Create a message. + * @note The object is expected to be const in the thread which sends this message. + * However it can be modified when Process() is called in a different thread. + * @param[in] obj The object. + * @param[in] member The member function of the object. + * @param[in] p2 The second parameter to pass to the function. + * @param[in] p3 The third parameter to pass to the function. + */ + MessageDoubleBuffered2( const T* obj, + MemberFunction member, + typename ParameterType< P2 >::PassingType p2, + typename ParameterType< P3 >::PassingType p3 ) + : MessageBase(), + object( const_cast< T* >( obj ) ), + memberFunction( member ), + param2( p2 ), + param3( p3 ) + { + } + + /** + * Virtual destructor + */ + virtual ~MessageDoubleBuffered2() + { + } + + /** + * @copydoc MessageBase::Process + */ + virtual void Process( BufferIndex bufferIndex ) + { + DALI_ASSERT_DEBUG( object && "Message does not have an object" ); + (object->*memberFunction)( + bufferIndex, + ParameterType< P2 >::PassObject( param2 ), + ParameterType< P3 >::PassObject( param3 ) ); + } + +private: + + T* object; + MemberFunction memberFunction; + typename ParameterType< P2 >::HolderType param2; + typename ParameterType< P3 >::HolderType param3; + +}; + + +/** + * Templated message which calls a member function of an object. + * This overload passes three value-types to set double-buffered properties. + * Template parameters need to match the MemberFunction! + * The message will contain copy of the value (in case of & or const&) + */ +template< typename T, typename P2, typename P3, typename P4 > +class MessageDoubleBuffered3 : public MessageBase +{ +public: + + typedef void(T::*MemberFunction)( + BufferIndex, + typename ParameterType< P2 >::PassingType, + typename ParameterType< P3 >::PassingType, + typename ParameterType< P4 >::PassingType ); + + /** + * Create a message. + * @note The object is expected to be const in the thread which sends this message. + * However it can be modified when Process() is called in a different thread. + * @param[in] obj The object. + * @param[in] member The member function of the object. + * @param[in] p2 The second parameter to pass. + * @param[in] p3 The third parameter to pass. + * @param[in] p4 The forth parameter to pass. + */ + MessageDoubleBuffered3( const T* obj, + MemberFunction member, + typename ParameterType< P2 >::PassingType p2, + typename ParameterType< P3 >::PassingType p3, + typename ParameterType< P4 >::PassingType p4 ) + : MessageBase(), + object( const_cast< T* >( obj ) ), + memberFunction( member ), + param2( p2 ), + param3( p3 ), + param4( p4 ) + { + } + + /** + * Virtual destructor + */ + virtual ~MessageDoubleBuffered3() + { + } + + /** + * @copydoc MessageBase::Process + */ + virtual void Process( BufferIndex bufferIndex ) + { + DALI_ASSERT_DEBUG( object && "Message does not have an object" ); + (object->*memberFunction)( + bufferIndex, + ParameterType< P2 >::PassObject( param2 ), + ParameterType< P3 >::PassObject( param3 ), + ParameterType< P4 >::PassObject( param4 ) ); + } + +private: + + T* object; + MemberFunction memberFunction; + typename ParameterType< P2 >::HolderType param2; + typename ParameterType< P3 >::HolderType param3; + typename ParameterType< P4 >::HolderType param4; + +}; + +/** + * Templated message which calls a member function of an object. + * This overload passes four value-types to set double-buffered properties. + * Template parameters need to match the MemberFunction! + * The message will contain copy of the value (in case of & or const&) + */ +template< typename T, typename P2, typename P3, typename P4, typename P5 > +class MessageDoubleBuffered4 : public MessageBase +{ +public: + + typedef void(T::*MemberFunction)( + BufferIndex, + typename ParameterType< P2 >::PassingType, + typename ParameterType< P3 >::PassingType, + typename ParameterType< P4 >::PassingType, + typename ParameterType< P5 >::PassingType ); + + /** + * Create a message. + * @note The object is expected to be const in the thread which sends this message. + * However it can be modified when Process() is called in a different thread. + * @param[in] obj The object. + * @param[in] member The member function of the object. + * @param[in] p2 The second parameter to pass. + * @param[in] p3 The third parameter to pass. + * @param[in] p4 The forth parameter to pass. + * @param[in] p5 The fifth parameter to pass. + */ + MessageDoubleBuffered4( const T* obj, + MemberFunction member, + typename ParameterType< P2 >::PassingType p2, + typename ParameterType< P3 >::PassingType p3, + typename ParameterType< P4 >::PassingType p4, + typename ParameterType< P5 >::PassingType p5 ) + : MessageBase(), + object( const_cast< T* >( obj ) ), + memberFunction( member ), + param2( p2 ), + param3( p3 ), + param4( p4 ), + param5( p5 ) + { + } + + /** + * Virtual destructor + */ + virtual ~MessageDoubleBuffered4() + { + } + + /** + * @copydoc MessageBase::Process + */ + virtual void Process( BufferIndex bufferIndex ) + { + DALI_ASSERT_DEBUG( object && "Message does not have an object" ); + (object->*memberFunction)( + bufferIndex, + ParameterType< P2 >::PassObject( param2 ), + ParameterType< P3 >::PassObject( param3 ), + ParameterType< P4 >::PassObject( param4 ), + ParameterType< P5 >::PassObject( param5 ) ); + } + +private: + + T* object; + MemberFunction memberFunction; + typename ParameterType< P2 >::HolderType param2; + typename ParameterType< P3 >::HolderType param3; + typename ParameterType< P4 >::HolderType param4; + typename ParameterType< P5 >::HolderType param5; + +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_MESSAGE_H__ diff --git a/dali/internal/common/owner-container.h b/dali/internal/common/owner-container.h new file mode 100644 index 0000000..9131616 --- /dev/null +++ b/dali/internal/common/owner-container.h @@ -0,0 +1,178 @@ +#ifndef __DALI_INTERNAL_OWNER_CONTAINER_H__ +#define __DALI_INTERNAL_OWNER_CONTAINER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * OwnerContainer is a vector which own heap-allocated objects. + * Unlike vector this will call delete on the stored pointers during destruction. + * For example, you can define a vector of heap-allocated Node objects: + * @code + * typedef OwnerContainer< Node* > NodeContainer; + * + * NodeContainer container; + * container.PushBack( new Node() ); + * // container is now responsible for calling delete on Node + * + * @endcode + */ +template< class T > +class OwnerContainer : public Dali::Vector< T > +{ +public: + + typedef typename Dali::Vector< T >::SizeType SizeType; + typedef typename Vector< T >::Iterator Iterator; + typedef typename Vector< T >::ConstIterator ConstIterator; + + /** + * Create a pointer-container. + */ + OwnerContainer() + { } + + /** + * Non-virtual destructor; OwnerContainer is not suitable as base class. + */ + ~OwnerContainer() + { + Clear(); + VectorBase::Release(); + } + + /** + * Test whether the container is empty. + * @return True if the container is empty + */ + bool IsEmpty() const + { + return VectorBase::Count() == 0u; + } + + /** + * Erase an object from the container (delete from heap). + * @param[in] position A dereferencable iterator to an element in mContainer. + * @return iterator pointing to next element + */ + Iterator Erase( Iterator position ) + { + delete (*position); + return Vector< T >::Erase( position ); + } + + /** + * Release the ownership of an object, without deleting it. + * @param[in] position A dereferencable iterator to an element in mContainer. + * @post iterators are invalidated by this method. + * @return pointer to the released item + */ + T Release( Iterator position ) + { + T pointer = *position; + Vector< T >::Erase( position ); + return pointer; + } + + /** + * Destroy all of the elements in the container. + */ + void Clear() + { + ConstIterator end = Vector< T >::End(); + for( Iterator iter = Vector< T >::Begin(); iter != end; ++iter ) + { + delete (*iter); + } + Vector< T >::Clear(); + } + + /** + * Resizes the container to hold specific amount of elements + * @param size to resize to + */ + void Resize( SizeType size ) + { + if( size < VectorBase::Count() ) + { + // OwnerContainer owns these heap-allocated objects + ConstIterator end = Vector< T >::End(); + for( Iterator iter = Vector< T >::Begin() + size; iter != end; ++iter ) + { + delete (*iter); + } + } + Vector< T >::Resize( size ); + } + + /** + * Move the ownership of objects from another OwnerContainer to this one + * without deleting them. It will keep the original items here as well. + * @param[in] source where to move elements from to this OwnerContainer + */ + void MoveFrom( OwnerContainer& source ) + { + typename Vector< T >::SizeType sourceCount = source.Count(); + // if source is empty, nothing to move + if( sourceCount > 0u ) + { + // Optimisation for the case that this is empty + if( IsEmpty() ) + { + VectorBase::Swap( source ); + } + else + { + // make space for new items + Vector< T >::Reserve( VectorBase::Count() + sourceCount ); + Iterator iter = source.Begin(); + ConstIterator end = source.End(); + for( ; iter != end; ++iter ) + { + T pointer = *iter; + Vector< T >::PushBack( pointer ); + } + // cannot call Clear on OwnerContainer as that deletes the elements + source.Vector< T >::Clear(); + } + } + } + +private: + + // Undefined copy constructor. + OwnerContainer( const OwnerContainer& ); + // Undefined assignment operator. + OwnerContainer& operator=( const OwnerContainer& ); + +}; + +} // namespace Internal + +} // namespace Dali + +#endif //__DALI_INTERNAL_OWNER_CONTAINER_H__ diff --git a/dali/internal/common/owner-pointer.h b/dali/internal/common/owner-pointer.h new file mode 100644 index 0000000..7b92978 --- /dev/null +++ b/dali/internal/common/owner-pointer.h @@ -0,0 +1,230 @@ +#ifndef __DALI_INTERNAL_OWNER_POINTER_H__ +#define __DALI_INTERNAL_OWNER_POINTER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include // NULL + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +template < typename T > +class OwnerPointer +{ +public: + /** + * Default constructor. Creates an OwnerPointer that does not own any object. + */ + OwnerPointer() + { + mObject = NULL; + } + + /** + * Constructor. Creates an OwnerPointer that owns the object. + * @param[in] object A pointer to a heap allocated object. + */ + OwnerPointer( T* object ) + { + mObject = object; + } + + /** + * Copy constructor. Passes the ownership of a pointer to another. + * @param[in] other The pointer that gives away the ownership. + */ + OwnerPointer( OwnerPointer& other ) + { + Init( other ); + } + + /** + * Assignment operator. Passes the ownership of a pointer to another. + * @param[in] other The pointer that gives away the ownership. + */ + OwnerPointer& operator=( OwnerPointer& other ) + { + if( this != &other ) // no self-assignment + { + Reset(); + Init( other ); + } + + // return self + return *this; + } + + /** + * Assignment operator. Takes the ownership of the object. + * If it owns an object already, it will be deleted. + * @param[in] pointer A pointer to a heap allocated object. + */ + OwnerPointer& operator=( T* pointer ) + { + if( mObject != pointer ) + { + Reset(); + mObject = pointer; + } + + return *this; + } + + /** + * Destructor. + */ + ~OwnerPointer() + { + Reset(); + } + + /** + * Indirection operator. + * @return a reference to the object. + */ + T& operator*() + { + DALI_ASSERT_DEBUG( mObject != NULL ); + + return *mObject; + } + + /** + * Const indirection operator. + * @return a reference to the object from const OwnerPointer. + */ + T& operator*() const + { + DALI_ASSERT_DEBUG( mObject != NULL ); + + // Pointer semantics: A const pointer does not mean const data. + return const_cast< T& >( *mObject ); + } + + /** + * Pointer operator. + * @return a pointer to the object. + */ + T* operator->() + { + return mObject; + } + + /** + * Const pointer operator. + * @return a pointer to the object referenced by a const OwnerPointer. + */ + T* operator->() const + { + // Pointer semantics: A const pointer does not mean const data. + return const_cast< T* >( mObject ); + } + + /** + * Compare with a raw pointer. + * @return true if the raw pointer matches the one owned by this object. + */ + bool operator==( const T* pointer ) + { + return ( mObject == pointer ); + } + + /** + * Reset the pointer, deleting any owned object. + */ + void Reset() + { + if ( mObject != NULL ) + { + delete mObject; + mObject = NULL; + } + } + + /** + * Release the ownership, it does not delete the object. + * @return a pointer to the object. + */ + T* Release() + { + T* tmp = mObject; + mObject = NULL; + return tmp; + } + + /** + * Returns a const pointer to the object owned. + * @return a const pointer to the object. + */ + const T* Get() const + { + return mObject; + } + + // Handle comparisons - This is a variation of the safe bool idiom + + /** + * Pointer-to-member type. Objects can be implicitly converted to this for validity checks. + */ + typedef void (OwnerPointer::*BooleanType)() const; + + /** + * Converts an object handle to a BooleanType. + * This is useful for checking whether the handle is NULL. + */ + operator BooleanType() const + { + return (mObject != NULL) ? &OwnerPointer::ThisIsSaferThanReturningVoidStar : NULL; + } + +private: + + /** + * Used by the safe bool idiom. + */ + void ThisIsSaferThanReturningVoidStar() const {} + +private: + + /** + * Initialise this pointer from another one. + * ownerPointer parameter looses ownership. + * @param ownerPointer owner pointer + */ + void Init( OwnerPointer& ownerPointer ) + { + mObject = ownerPointer.mObject; + ownerPointer.mObject = NULL; + } + + // data + T* mObject; ///< Raw pointer to the object +}; + +} // namespace Internal + +} // namespace Dali + +#endif //__DALI_INTERNAL_OWNER_POINTER_H__ diff --git a/dali/internal/common/shader-data.h b/dali/internal/common/shader-data.h new file mode 100644 index 0000000..797568d --- /dev/null +++ b/dali/internal/common/shader-data.h @@ -0,0 +1,167 @@ +#ifndef __DALI_INTERNAL_SHADER_DATA_H__ +#define __DALI_INTERNAL_SHADER_DATA_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +class ShaderData; +typedef IntrusivePtr ShaderDataPtr; + +/** + * ShaderData class. + * A container for shader source code and compiled binary byte code. + */ +class ShaderData : public Dali::RefObject +{ +public: + + /** + * Constructor + * @param[in] vertexSource Source code for vertex program + * @param[in] fragmentSource Source code for fragment program + */ + ShaderData(const std::string& vertexSource, const std::string& fragmentSource) + : mShaderHash( -1 ), + mVertexShader(vertexSource), + mFragmentShader(fragmentSource) + { } + +protected: + /** + * Protected Destructor + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~ShaderData() + { + // vector releases its data + } + +public: // API + + /** + * Set hash value which is created with vertex and fragment shader code + * @param [in] shaderHash hash key created with vertex and fragment shader code + */ + void SetHashValue(size_t shaderHash) + { + DALI_ASSERT_DEBUG( shaderHash != size_t(-1) ); + mShaderHash = shaderHash; + } + + /** + * Get hash value which is created with vertex and fragment shader code + * @return shaderHash hash key created with vertex and fragment shader code + */ + size_t GetHashValue() const + { + DALI_ASSERT_DEBUG( mShaderHash != size_t(-1) ); + return mShaderHash; + } + + /** + * @return the vertex shader + */ + const char* GetVertexShader() const + { + return mVertexShader.c_str(); + } + + /** + * @return the vertex shader + */ + const char* GetFragmentShader() const + { + return mFragmentShader.c_str(); + } + + /** + * Check whether there is a compiled binary available + * @return true if this objects contains a compiled binary + */ + bool HasBinary() const + { + return 0 != mBuffer.Size(); + } + + /** + * Allocate a buffer for the compiled binary bytecode + * @param[in] size The size of the buffer in bytes + */ + void AllocateBuffer( size_t size ) + { + mBuffer.Resize( size ); + } + + /** + * Get the program buffer + * @return reference to the buffer + */ + size_t GetBufferSize() const + { + return mBuffer.Size(); + } + + /** + * Get the data that the buffer points to + * @return raw pointer to the buffer data + */ + unsigned char* GetBufferData() + { + DALI_ASSERT_DEBUG( mBuffer.Size() > 0 ); + return &mBuffer[0]; + } + + /** + * Get the data that the buffer points to + * @return raw pointer to the buffer data + */ + Dali::Vector& GetBuffer() + { + return mBuffer; + } + +private: // Not implemented + + ShaderData(const ShaderData& other); ///< no copying of this object + ShaderData& operator= (const ShaderData& rhs); ///< no copying of this object + +private: // Data + + size_t mShaderHash; ///< hash key created with vertex and fragment shader code + std::string mVertexShader; ///< source code for vertex program + std::string mFragmentShader; ///< source code for fragment program + Dali::Vector mBuffer; ///< buffer containing compiled binary bytecode +}; + +} // namespace Integration + +} // namespace Dali + +#endif // __DALI_INTERNAL_SHADER_DATA_H__ diff --git a/dali/internal/common/shader-saver.h b/dali/internal/common/shader-saver.h new file mode 100644 index 0000000..580cab6 --- /dev/null +++ b/dali/internal/common/shader-saver.h @@ -0,0 +1,60 @@ +#ifndef __DALI_INTERNAL_SHADER_DISPATCHER_H__ +#define __DALI_INTERNAL_SHADER_DISPATCHER_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +// EXTERNAL INCLUDES + + +namespace Dali +{ + +namespace Internal +{ +class ShaderData; +typedef IntrusivePtr ShaderDataPtr; + +/** + * Abstract interface for passing a ShaderData object towards being saved. + */ +class ShaderSaver +{ +public: + + /** + * A function saving the binary from a ShaderDataPtr or passing it on to where it can be saved. + * @param[in] shaderData A smart pointer to a ShaderData for which the program binary should be saved. + */ + virtual void SaveBinary( Internal::ShaderDataPtr shaderData ) = 0; + +protected: + /** + * Destructor. Protected as no derived class should ever be deleted + * through a reference to this pure abstract interface. + */ + virtual ~ShaderSaver(){} +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_SHADER_DISPATCHER_H__ diff --git a/dali/internal/common/text-vertex-2d.h b/dali/internal/common/text-vertex-2d.h new file mode 100644 index 0000000..54d5242 --- /dev/null +++ b/dali/internal/common/text-vertex-2d.h @@ -0,0 +1,46 @@ +#ifndef __DALI_INTERNAL_TEXT_VERTEX_2D_H__ +#define __DALI_INTERNAL_TEXT_VERTEX_2D_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +namespace Dali +{ + +namespace Internal +{ + +/** + * A 2D vertex with position, texture coordinate + * and texture coordinate for distance field drop shadow adjustment + */ +struct TextVertex2D +{ + float mX; + float mY; + float mU; + float mV; + float mU1; + float mV1; +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_TEXT_VERTEX_2D_H__ + diff --git a/dali/internal/common/type-abstraction-enums.h b/dali/internal/common/type-abstraction-enums.h new file mode 100644 index 0000000..465220b --- /dev/null +++ b/dali/internal/common/type-abstraction-enums.h @@ -0,0 +1,41 @@ +#ifndef __DALI_INTERNAL_TYPE_ABSTRACTION_ENUMS_H__ +#define __DALI_INTERNAL_TYPE_ABSTRACTION_ENUMS_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +template <> struct ParameterType< CullFaceMode > : public BasicType< CullFaceMode > {}; +template <> struct ParameterType< BlendingMode::Type > : public BasicType< BlendingMode::Type > {}; + +} //namespace Internal + +} //namespace Dali + +#endif // __DALI_INTERNAL_TYPE_ABSTRACTION_ENUMS_H__ diff --git a/dali/internal/common/type-abstraction.h b/dali/internal/common/type-abstraction.h new file mode 100644 index 0000000..3338913 --- /dev/null +++ b/dali/internal/common/type-abstraction.h @@ -0,0 +1,102 @@ +#ifndef __DALI_INTERNAL_TYPE_ABSTRACTION_H__ +#define __DALI_INTERNAL_TYPE_ABSTRACTION_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * Template helpers to strip of const reference and reference to prevent anyone + * from passing references as message parameters + */ + +// For basic types, they are always pass by copy +template +struct BasicType +{ + typedef Type HolderType; + typedef Type PassingType; + static PassingType PassObject( PassingType object ) { return object; } +}; + +// For complex types that are copied into the message, +// they are passed as const reference when they don't need to be copied +template +struct ComplexType +{ + typedef Type HolderType; + typedef const Type& PassingType; + static PassingType PassObject( PassingType object ) { return object; } +}; + +// For complex types that are owned by the message, +// They are passed as raw pointer and hold in an OwnerPointer +template +struct OwnedType +{ + typedef OwnerPointer HolderType; + typedef Type* PassingType; + static PassingType PassObject( HolderType& object ) { return object.Release(); } +}; + +// Default for Vector3 and other structures +template struct ParameterType : public ComplexType< T > {}; + +// For message owned parameters +template struct ParameterType< OwnerPointer > : public OwnedType< T > {}; + +// Basic types types +template struct ParameterType< T* > : public BasicType< T* > {}; +template struct ParameterType< const T* > : public BasicType< const T* > {}; +template <> struct ParameterType< int > : public BasicType< int > {}; +template <> struct ParameterType< unsigned int > : public BasicType< unsigned int > {}; +template <> struct ParameterType< float > : public BasicType< float > {}; +template <> struct ParameterType< bool > : public BasicType< bool > {}; +template <> struct ParameterType< short int > : public BasicType< short int > {}; + +#if INT_MAX != LONG_MAX +template <> struct ParameterType< long > : public BasicType< long > {}; +template <> struct ParameterType< unsigned long > : public BasicType< unsigned long > {}; +#endif + +//TODO: Passing intrusive pointers through messages is potentially dangerous, +// this should be checked +template struct ParameterType< IntrusivePtr > +: public BasicType< IntrusivePtr > {}; + +// poorly constructed types, types should not be defined as references +// this will trigger a compilation error. +template struct ParameterType< U& > {}; +template struct ParameterType< const U& > {}; + +} //namespace Internal + +} //namespace Dali + +#endif // __DALI_INTERNAL_TYPE_ABSTRACTION_H__ diff --git a/dali/internal/event/actor-attachments/actor-attachment-declarations.h b/dali/internal/event/actor-attachments/actor-attachment-declarations.h new file mode 100644 index 0000000..8dbd795 --- /dev/null +++ b/dali/internal/event/actor-attachments/actor-attachment-declarations.h @@ -0,0 +1,43 @@ +#ifndef __DALI_INTERNAL_ACTOR_ATTACHMENT_DECLARATIONS_H__ +#define __DALI_INTERNAL_ACTOR_ATTACHMENT_DECLARATIONS_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +class ActorAttachment; +class CameraAttachment; +class ImageAttachment; + +typedef IntrusivePtr ActorAttachmentPtr; +typedef IntrusivePtr CameraAttachmentPtr; +typedef IntrusivePtr ImageAttachmentPtr; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_ACTOR_ATTACHMENT_DECLARATIONS_H__ diff --git a/dali/internal/event/actor-attachments/actor-attachment-impl.cpp b/dali/internal/event/actor-attachments/actor-attachment-impl.cpp new file mode 100644 index 0000000..fcd6e8c --- /dev/null +++ b/dali/internal/event/actor-attachments/actor-attachment-impl.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Internal +{ + +bool ActorAttachment::OnStage() const +{ + return mIsOnStage; +} + +/** + * This method is called by the parent actor. + */ +void ActorAttachment::Connect() +{ + mIsOnStage = true; + + // Notification for derived classes + OnStageConnection(); +} + +/** + * This method is called by the parent actor. + */ +void ActorAttachment::Disconnect() +{ + // Notification for derived classes + OnStageDisconnection(); + + mIsOnStage = false; +} + +ActorAttachment::ActorAttachment( EventThreadServices& eventThreadServices ) +: mEventThreadServices( eventThreadServices ), + mIsOnStage( false ) +{ +} + +ActorAttachment::~ActorAttachment() +{ +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/actor-attachments/actor-attachment-impl.h b/dali/internal/event/actor-attachments/actor-attachment-impl.h new file mode 100644 index 0000000..7bfef97 --- /dev/null +++ b/dali/internal/event/actor-attachments/actor-attachment-impl.h @@ -0,0 +1,119 @@ +#ifndef __DALI_INTERNAL_ACTOR_ATTACHMENT_H__ +#define __DALI_INTERNAL_ACTOR_ATTACHMENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +class EventThreadServices; + +/** + * An abstract base class for attachments, such a renderable objects and lights. + * ActorAttachments must be attached to an actor, in order to be displayed. + */ +class ActorAttachment : public Dali::RefObject +{ +public: + + /** + * Query whether the attachment is connected to the stage. + * @return True if the attachment is connected to the stage. + */ + bool OnStage() const; + + /** + * Called by the attached actor, when connected to the Stage. + */ + void Connect(); + + /** + * Called by the attached actor, when the actor is disconnected from the Stage. + */ + void Disconnect(); + +protected: + + /** + * Construct a new attachment. + * @param[in] eventThreadServices Used for messaging to and reading from scene-graph. + */ + ActorAttachment( EventThreadServices& eventThreadServices ); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~ActorAttachment(); + +private: + + // Undefined + ActorAttachment(const ActorAttachment&); + + // Undefined + ActorAttachment& operator=(const ActorAttachment& rhs); + + /** + * For use in derived classes, called after ConnectToStage() + */ + virtual void OnStageConnection() = 0; + + /** + * For use in derived classes, called after DisconnectFromStage() + */ + virtual void OnStageDisconnection() = 0; + +protected: + /** + * For use in message sending to and property reading from the scene graph + * Inlined for speed + * @return The EventThreadServices object + */ + inline EventThreadServices& GetEventThreadServices() + { + return mEventThreadServices; + } + + /** + * For use in message sending to and property reading from the scene graph + * Inlined for speed + */ + inline const EventThreadServices& GetEventThreadServices() const + { + return mEventThreadServices; + } + +private: + EventThreadServices& mEventThreadServices; ///< Used to send messages to scene-graph; valid until Core destruction + +protected: + bool mIsOnStage : 1; ///< Flag to identify whether the attachment is on-stage + +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_ACTOR_ATTACHMENT_H__ diff --git a/dali/internal/event/actor-attachments/camera-attachment-impl.cpp b/dali/internal/event/actor-attachments/camera-attachment-impl.cpp new file mode 100644 index 0000000..aa66cd7 --- /dev/null +++ b/dali/internal/event/actor-attachments/camera-attachment-impl.cpp @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +CameraAttachmentPtr CameraAttachment::New( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode ) +{ + CameraAttachmentPtr attachment( new CameraAttachment( eventThreadServices ) ); + + // Transfer object ownership of scene-object to message + SceneGraph::CameraAttachment* sceneObject = CreateSceneObject(); + AttachToNodeMessage( eventThreadServices.GetUpdateManager(), parentNode, sceneObject ); + + // Keep raw pointer for message passing + attachment->mSceneObject = sceneObject; + + return attachment; +} + +CameraAttachment::CameraAttachment( EventThreadServices& eventThreadServices ) +: ActorAttachment( eventThreadServices ), + mSceneObject( NULL ), + mType( SceneGraph::CameraAttachment::DEFAULT_TYPE ), + mProjectionMode( SceneGraph::CameraAttachment::DEFAULT_MODE ), + mInvertYAxis( SceneGraph::CameraAttachment::DEFAULT_INVERT_Y_AXIS ), + mFieldOfView( SceneGraph::CameraAttachment::DEFAULT_FIELD_OF_VIEW ), + mAspectRatio( SceneGraph::CameraAttachment::DEFAULT_ASPECT_RATIO ), + mLeftClippingPlane( SceneGraph::CameraAttachment::DEFAULT_LEFT_CLIPPING_PLANE ), + mRightClippingPlane( SceneGraph::CameraAttachment::DEFAULT_RIGHT_CLIPPING_PLANE ), + mTopClippingPlane( SceneGraph::CameraAttachment::DEFAULT_TOP_CLIPPING_PLANE ), + mBottomClippingPlane( SceneGraph::CameraAttachment::DEFAULT_BOTTOM_CLIPPING_PLANE ), + mNearClippingPlane( SceneGraph::CameraAttachment::DEFAULT_NEAR_CLIPPING_PLANE ), + mFarClippingPlane( SceneGraph::CameraAttachment::DEFAULT_FAR_CLIPPING_PLANE ), + mStereoBias( SceneGraph::CameraAttachment::DEFAULT_STEREO_BIAS ), + mTargetPosition( SceneGraph::CameraAttachment::DEFAULT_TARGET_POSITION ) +{ +} + +CameraAttachment::~CameraAttachment() +{ +} + +SceneGraph::CameraAttachment* CameraAttachment::CreateSceneObject() +{ + return SceneGraph::CameraAttachment::New(); +} + +void CameraAttachment::SetType(Dali::Camera::Type type) +{ + if( type != mType ) + { + mType = type; + + // sceneObject is being used in a separate thread; queue a message to set + SetTypeMessage( GetEventThreadServices(), *mSceneObject, type ); + } +} + +Dali::Camera::Type CameraAttachment::GetType() const +{ + return mType; +} + +void CameraAttachment::SetProjectionMode(Dali::Camera::ProjectionMode projectionMode) +{ + if( ! Equals(projectionMode, mProjectionMode) ) + { + mProjectionMode = projectionMode; + + // sceneObject is being used in a separate thread; queue a message to set + SetProjectionModeMessage( GetEventThreadServices(), *mSceneObject, projectionMode ); + } +} + +Dali::Camera::ProjectionMode CameraAttachment::GetProjectionMode() const +{ + return mProjectionMode; +} + +void CameraAttachment::SetFieldOfView( float fieldOfView ) +{ + if( ! Equals(fieldOfView, mFieldOfView) ) + { + mFieldOfView = fieldOfView; + + // sceneObject is being used in a separate thread; queue a message to set + SetFieldOfViewMessage( GetEventThreadServices(), *mSceneObject, fieldOfView ); + } +} + +float CameraAttachment::GetFieldOfView() const +{ + return mFieldOfView; +} + +void CameraAttachment::SetAspectRatio( float aspectRatio ) +{ + if( ! Equals(aspectRatio, mAspectRatio) ) + { + mAspectRatio = aspectRatio; + + // sceneObject is being used in a separate thread; queue a message to set + SetAspectRatioMessage( GetEventThreadServices(), *mSceneObject, aspectRatio ); + } +} + +float CameraAttachment::GetAspectRatio() const +{ + return mAspectRatio; +} + +void CameraAttachment::SetStereoBias(const Vector2& stereoBias) +{ + if( ! Equals(stereoBias.x, mStereoBias.x ) || ! Equals(stereoBias.y, mStereoBias.y ) ) + { + mStereoBias = stereoBias; + + // sceneObject is being used in a separate thread; queue a message to set + SetStereoBiasMessage( GetEventThreadServices(), *mSceneObject, stereoBias ); + } +} + +Vector2 CameraAttachment::GetStereoBias() const +{ + return mStereoBias; +} + +void CameraAttachment::SetLeftClippingPlane( float leftClippingPlane ) +{ + if( ! Equals(leftClippingPlane, mLeftClippingPlane ) ) + { + mLeftClippingPlane = leftClippingPlane; + + // sceneObject is being used in a separate thread; queue a message to set + SetLeftClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, leftClippingPlane ); + } +} + +float CameraAttachment::GetLeftClippingPlane() const +{ + return mLeftClippingPlane; +} + +void CameraAttachment::SetRightClippingPlane( float rightClippingPlane ) +{ + if( ! Equals(rightClippingPlane, mRightClippingPlane ) ) + { + mRightClippingPlane = rightClippingPlane; + + // sceneObject is being used in a separate thread; queue a message to set + SetRightClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, rightClippingPlane ); + } +} + +float CameraAttachment::GetRightClippingPlane() const +{ + return mRightClippingPlane; +} + +void CameraAttachment::SetTopClippingPlane( float topClippingPlane ) +{ + if( ! Equals(topClippingPlane, mTopClippingPlane ) ) + { + mTopClippingPlane = topClippingPlane; + + // sceneObject is being used in a separate thread; queue a message to set + SetTopClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, topClippingPlane ); + } +} + +float CameraAttachment::GetTopClippingPlane() const +{ + return mTopClippingPlane; +} + +void CameraAttachment::SetBottomClippingPlane( float bottomClippingPlane ) +{ + if( ! Equals(bottomClippingPlane, mBottomClippingPlane ) ) + { + mBottomClippingPlane = bottomClippingPlane; + + // sceneObject is being used in a separate thread; queue a message to set + SetBottomClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, bottomClippingPlane ); + } +} + +float CameraAttachment::GetBottomClippingPlane() const +{ + return mBottomClippingPlane; +} + +void CameraAttachment::SetNearClippingPlane( float nearClippingPlane ) +{ + if( ! Equals(nearClippingPlane, mNearClippingPlane ) ) + { + mNearClippingPlane = nearClippingPlane; + + // sceneObject is being used in a separate thread; queue a message to set + SetNearClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, nearClippingPlane ); + } +} + +float CameraAttachment::GetNearClippingPlane() const +{ + return mNearClippingPlane; +} + +void CameraAttachment::SetFarClippingPlane( float farClippingPlane ) +{ + if( ! Equals( farClippingPlane, mFarClippingPlane ) ) + { + mFarClippingPlane = farClippingPlane; + + // sceneObject is being used in a separate thread; queue a message to set + SetFarClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, farClippingPlane ); + } +} + +float CameraAttachment::GetFarClippingPlane() const +{ + return mFarClippingPlane; +} + +void CameraAttachment::SetTargetPosition( Vector3 targetPosition ) +{ + if( targetPosition != mTargetPosition ) + { + mTargetPosition = targetPosition; + + SetTargetPositionMessage( GetEventThreadServices(), *mSceneObject, targetPosition ); + } +} + +Vector3 CameraAttachment::GetTargetPosition() +{ + return mTargetPosition; +} + +void CameraAttachment::SetInvertYAxis( bool invertYAxis ) +{ + if( invertYAxis != mInvertYAxis ) + { + mInvertYAxis = invertYAxis; + + // sceneObject is being used in a separate thread; queue a message to set + SetInvertYAxisMessage( GetEventThreadServices(), *mSceneObject, invertYAxis ); + } +} + +bool CameraAttachment::GetInvertYAxis() const +{ + return mInvertYAxis; +} + +const Matrix& CameraAttachment::GetViewMatrix() const +{ + const SceneGraph::CameraAttachment& sceneObject = *mSceneObject; + + return sceneObject.GetViewMatrix( GetEventThreadServices().GetEventBufferIndex() ); +} + +const Matrix& CameraAttachment::GetProjectionMatrix() const +{ + const SceneGraph::CameraAttachment& sceneObject = *mSceneObject; + + return sceneObject.GetProjectionMatrix( GetEventThreadServices().GetEventBufferIndex() ); +} + +const Matrix& CameraAttachment::GetInverseViewProjectionMatrix() const +{ + const SceneGraph::CameraAttachment& sceneObject = *mSceneObject; + + return sceneObject.GetInverseViewProjectionMatrix( GetEventThreadServices().GetEventBufferIndex() ); +} + +const PropertyInputImpl* CameraAttachment::GetViewMatrixProperty() const +{ + DALI_ASSERT_DEBUG( OnStage() ); + + const SceneGraph::CameraAttachment& sceneObject = *mSceneObject; + + return sceneObject.GetViewMatrix(); +} + +const PropertyInputImpl* CameraAttachment::GetProjectionMatrixProperty() const +{ + DALI_ASSERT_DEBUG( OnStage() ); + + const SceneGraph::CameraAttachment& sceneObject = *mSceneObject; + + return sceneObject.GetProjectionMatrix(); +} + +void CameraAttachment::OnStageConnection() +{ + // do nothing +} + +void CameraAttachment::OnStageDisconnection() +{ + // do nothing +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/actor-attachments/camera-attachment-impl.h b/dali/internal/event/actor-attachments/camera-attachment-impl.h new file mode 100644 index 0000000..4e3eedc --- /dev/null +++ b/dali/internal/event/actor-attachments/camera-attachment-impl.h @@ -0,0 +1,299 @@ +#ifndef __DALI_INTERNAL_CAMERA_ATTACHMENT_H__ +#define __DALI_INTERNAL_CAMERA_ATTACHMENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +class Matrix; +struct Vector3; + +namespace Internal +{ + +class Camera; + +namespace SceneGraph +{ +class CameraAttachment; +class Node; +} + +/** + * An attachment for managing the properties of a camera in the scene + */ +class CameraAttachment : public ActorAttachment +{ +public: + /** + * Create an initialised CameraAttachment. + * @param[in] eventThreadServices to use + * @param[in] parentNode The node to attach a scene-object to. + * @return A handle to a newly allocated Dali resource. + */ + static CameraAttachmentPtr New( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode ); + + /** + * @copydoc Dali::Camera::SetType + */ + void SetType(Dali::Camera::Type type); + + /** + * @copydoc Dali::Camera::GetType + */ + Dali::Camera::Type GetType() const; + + /** + * Set whether the Y Axis is inverted or not. + * Default camera inverts the Y axis to provide a +ve Y down LHS coordinate system + * Some cameras may require no inversion. + * @param[in] invertYAxis True if inverted, false otherwise + */ + void SetInvertYAxis( bool invertYAxis ); + + /** + * Get the setting of InvertYAxis + * @return True if the Y Axis is inverted. + */ + bool GetInvertYAxis() const; + + /** + * @copydoc Dali::Camera::SetProjectionMode + */ + void SetProjectionMode(Dali::Camera::ProjectionMode projectionMode); + + /** + * @copydoc Dali::Camera::GetProjectionMode + */ + Dali::Camera::ProjectionMode GetProjectionMode() const; + + /** + * @copydoc Dali::Camera::SetFieldOfView + */ + void SetFieldOfView(float fieldOfView); + + /** + * @copydoc Dali::Camera::GetFieldOfView + */ + float GetFieldOfView() const; + + /** + * @copydoc Dali::Camera::SetAspectRatio + */ + void SetAspectRatio(float aspectRatio); + + /** + * @copydoc Dali::Camera::GetAspectRatio + */ + float GetAspectRatio() const; + + /** + * @copydoc Dali::Camera::SetLeftClippingPlane * Set stereo bias. The frustum offset for a 3D camera + * @param[in] stereoBias The frustum offset for the 3D camera + */ + void SetStereoBias(const Vector2& stereoBias); + + /** + * Get stereo bias. The frustum offset for a 3D camera + * @return The frustum offset for the 3D camera + */ + Vector2 GetStereoBias() const; + + /** + * @copydoc Dali::Camera::SetLeftClippingPlane + */ + void SetLeftClippingPlane(float leftClippingPlane); + + /** + * @copydoc Dali::Camera::GetLeftClippingPlane + */ + float GetLeftClippingPlane() const; + + /** + * @copydoc Dali::Camera::SetRightClippingPlane + */ + void SetRightClippingPlane(float rightClippingPlane); + + /** + * @copydoc Dali::Camera::GetRightClippingPlane + */ + float GetRightClippingPlane() const; + + /** + * @copydoc Dali::Camera::SetTopClippingPlane + */ + void SetTopClippingPlane(float topClippingPlane); + + /** + * @copydoc Dali::Camera::GetTopClippingPlane + */ + float GetTopClippingPlane() const; + + /** + * @copydoc Dali::Camera::SetBottomClippingPlane + */ + void SetBottomClippingPlane(float bottomClippingPlane); + + /** + * @copydoc Dali::Camera::GetBottomClippingPlane + */ + float GetBottomClippingPlane() const; + + /** + * @copydoc Dali::Camera::SetNearClippingPlane + */ + void SetNearClippingPlane(float nearClippingPlane); + + /** + * @copydoc Dali::Camera::GetNearClippingPlane + */ + float GetNearClippingPlane() const; + + /** + * @copydoc Dali::Camera::SetFarClippingPlane + */ + void SetFarClippingPlane(float farClippingPlane); + + /** + * @copydoc Dali::Camera::GetFarClippingPlane + */ + float GetFarClippingPlane() const; + + /** + * Set the (lookAt) target for the camera + * @pre The Camera owned by this object must be of the type Camera::LookAtTarget + * @param target Position of object we want to look at + */ + void SetTargetPosition(Vector3 target); + + /** + * Get the (lookAt) target for the camera + * @return the last set target + */ + Vector3 GetTargetPosition(); + + /** + * Retrieve the view-matrix. + * @pre The attachment is on-stage. + * @return The view-matrix. + */ + const Matrix& GetViewMatrix() const; + + /** + * Retrieve the projection-matrix. + * @pre The attachment is on-stage. + * @return The projection-matrix. + */ + const Matrix& GetProjectionMatrix() const; + + /** + * Returns the inverse view-projection matrix + * @pre The attachment is on-stage. + * @return The inverse view-projection-matrix. + */ + const Matrix& GetInverseViewProjectionMatrix() const; + + /** + * Retrieve the view-matrix property querying interface. + * @pre The attachment is on-stage. + * @return The view-matrix property querying interface. + */ + const PropertyInputImpl* GetViewMatrixProperty() const; + + /** + * Retrieve the projection-matrix property querying interface. + * @pre The attachment is on-stage. + * @return The projection-matrix property querying interface. + */ + const PropertyInputImpl* GetProjectionMatrixProperty() const; + + /** + * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty() + */ + const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty() + */ + const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const; + + +private: + + /** + * First stage construction of a CameraAttachment. + * @param[in] eventThreadServices Used for messaging to and reading from scene-graph. + */ + CameraAttachment( EventThreadServices& eventThreadServices ); + + /** + * Creates the corresponding scene-graph CameraAttachment. + * @return A newly allocated scene object. + */ + static SceneGraph::CameraAttachment* CreateSceneObject(); + + /** + * @copydoc Dali::Internal::ActorAttachment::OnStageConnection() + */ + virtual void OnStageConnection(); + + /** + * @copydoc Dali::Internal::ActorAttachment::OnStageDisconnection() + */ + virtual void OnStageDisconnection(); + +protected: + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~CameraAttachment(); + +private: + + const SceneGraph::CameraAttachment* mSceneObject; ///< Not owned + + Dali::Camera::Type mType; + Dali::Camera::ProjectionMode mProjectionMode; + bool mInvertYAxis; + float mFieldOfView; + float mAspectRatio; + float mLeftClippingPlane; + float mRightClippingPlane; + float mTopClippingPlane; + float mBottomClippingPlane; + float mNearClippingPlane; + float mFarClippingPlane; + Vector2 mStereoBias; + Vector3 mTargetPosition; +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_CAMERA_ATTACHMENT_H__ diff --git a/dali/internal/event/actor-attachments/image-attachment-impl.cpp b/dali/internal/event/actor-attachments/image-attachment-impl.cpp new file mode 100644 index 0000000..4ebe539 --- /dev/null +++ b/dali/internal/event/actor-attachments/image-attachment-impl.cpp @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +ImageAttachmentPtr ImageAttachment::New( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode ) +{ + ImageAttachmentPtr attachment( new ImageAttachment( eventThreadServices ) ); + + // Transfer object ownership of scene-object to message + SceneGraph::ImageAttachment* sceneObject = CreateSceneObject(); + AttachToNodeMessage( eventThreadServices.GetUpdateManager(), parentNode, sceneObject ); + + // Keep raw pointer for message passing + attachment->mSceneObject = sceneObject; + + return attachment; +} + +ImageAttachment::ImageAttachment( EventThreadServices& eventThreadServices ) +: RenderableAttachment(eventThreadServices), + mSceneObject(NULL), + mPixelArea(0,0,0,0), + mStyle(Dali::ImageActor::STYLE_QUAD), + mBorder(0.45,0.45,0.1,0.1), + mIsPixelAreaSet(false), + mBorderInPixels(false), + + + mBlendingOptions(), + mSamplerBitfield( ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) ), + mSortModifier( 0.0f ), + mCullFaceMode( CullNone ), + mBlendingMode( BlendingMode::AUTO ), + mShaderEffect() +{ + mImageConnectable.Set( NULL, false ); +} + +ImageAttachment::~ImageAttachment() +{ +} + +void ImageAttachment::SetImage( ImagePtr& image ) +{ + bool onStage = OnStage(); + // keep a reference to Image object + mImageConnectable.Set( image, onStage ); + + // Wait until the scene-graph attachment is connected, before providing resource ID + if ( OnStage() ) + { + unsigned int resourceId = (image) ? image->GetResourceId() : 0u; + + // sceneObject is being used in a separate thread; queue a message to set + SetTextureIdMessage( GetEventThreadServices(), *mSceneObject, resourceId ); + } +} + +ImagePtr ImageAttachment::GetImage() +{ + return mImageConnectable.Get(); +} + +void ImageAttachment::SetPixelArea(const PixelArea& pixelArea) +{ + // check to see if pixel area is actually different, using rect::operator== + if( pixelArea != mPixelArea ) + { + // Cache for public getters + mPixelArea = pixelArea; + mIsPixelAreaSet = true; + + // sceneObject is being used in a separate thread; queue a message to set + SetPixelAreaMessage( GetEventThreadServices(), *mSceneObject, mPixelArea ); + } +} + +void ImageAttachment::ClearPixelArea() +{ + // Cache for public getters + mIsPixelAreaSet = false; + + // sceneObject is being used in a separate thread; queue a message to set + ClearPixelAreaMessage( GetEventThreadServices(), *mSceneObject ); +} + +void ImageAttachment::SetStyle(Style style) +{ + // Cache for public getters + mStyle = style; + + // sceneObject is being used in a separate thread; queue a message to set + SetStyleMessage( GetEventThreadServices(), *mSceneObject, style ); +} + +void ImageAttachment::SetNinePatchBorder(const Vector4& border, bool inPixels) +{ + // Cache for public getters + mBorder = border; + mBorderInPixels = inPixels; + + // sceneObject is being used in a separate thread; queue a message to set + SetNinePatchBorderMessage( GetEventThreadServices(), *mSceneObject, border, inPixels ); +} + +SceneGraph::ImageAttachment* ImageAttachment::CreateSceneObject() +{ + return SceneGraph::ImageAttachment::New( 0u ); +} + +const SceneGraph::ImageAttachment& ImageAttachment::GetSceneObject() const +{ + DALI_ASSERT_DEBUG( mSceneObject != NULL ); + return *mSceneObject; +} + +void ImageAttachment::SetSortModifier(float modifier) +{ + // Cache for actor-side getters + mSortModifier = modifier; + + // attachment is being used in a separate thread; queue a message to set the value & base value + SetSortModifierMessage( GetEventThreadServices(), GetSceneObject(), modifier ); +} + +float ImageAttachment::GetSortModifier() const +{ + // mSortModifier is not animatable; this is the most up-to-date value. + return mSortModifier; +} + +void ImageAttachment::SetCullFace( CullFaceMode mode ) +{ + // Cache for actor-side getters + mCullFaceMode = mode; + + // attachment is being used in a separate thread; queue a message to set the value + SetCullFaceMessage( GetEventThreadServices(), GetSceneObject(), mode ); +} + +CullFaceMode ImageAttachment::GetCullFace() const +{ + // mCullFaceMode is not animatable; this is the most up-to-date value. + return mCullFaceMode; +} + +void ImageAttachment::SetBlendMode( BlendingMode::Type mode ) +{ + mBlendingMode = mode; + + // attachment is being used in a separate thread; queue a message to set the value + SetBlendingModeMessage( GetEventThreadServices(), GetSceneObject(), mode ); +} + +BlendingMode::Type ImageAttachment::GetBlendMode() const +{ + return mBlendingMode; +} + +void ImageAttachment::SetBlendFunc( BlendingFactor::Type srcFactorRgb, BlendingFactor::Type destFactorRgb, + BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha ) +{ + // Cache for actor-side getters + mBlendingOptions.SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha ); + + // attachment is being used in a separate thread; queue a message to set the value + SetBlendingOptionsMessage( GetEventThreadServices(), GetSceneObject(), mBlendingOptions.GetBitmask() ); +} + +void ImageAttachment::GetBlendFunc( BlendingFactor::Type& srcFactorRgb, BlendingFactor::Type& destFactorRgb, + BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const +{ + // These are not animatable, the cached values are up-to-date. + srcFactorRgb = mBlendingOptions.GetBlendSrcFactorRgb(); + destFactorRgb = mBlendingOptions.GetBlendDestFactorRgb(); + srcFactorAlpha = mBlendingOptions.GetBlendSrcFactorAlpha(); + destFactorAlpha = mBlendingOptions.GetBlendDestFactorAlpha(); +} + +void ImageAttachment::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha ) +{ + mBlendingOptions.SetBlendEquation( equationRgb, equationAlpha ); + + // attachment is being used in a separate thread; queue a message to set the value + SetBlendingOptionsMessage( GetEventThreadServices(), GetSceneObject(), mBlendingOptions.GetBitmask() ); +} + +void ImageAttachment::GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const +{ + // These are not animatable, the cached values are up-to-date. + equationRgb = mBlendingOptions.GetBlendEquationRgb(); + equationAlpha = mBlendingOptions.GetBlendEquationAlpha(); +} + +void ImageAttachment::SetBlendColor( const Vector4& color ) +{ + if( mBlendingOptions.SetBlendColor( color ) ) + { + // attachment is being used in a separate thread; queue a message to set the value + SetBlendColorMessage( GetEventThreadServices(), GetSceneObject(), color ); + } +} + +const Vector4& ImageAttachment::GetBlendColor() const +{ + const Vector4* optionalColor = mBlendingOptions.GetBlendColor(); + if( optionalColor ) + { + return *optionalColor; + } + + return Vector4::ZERO; +} + +void ImageAttachment::SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter ) +{ + mSamplerBitfield = ImageSampler::PackBitfield( minFilter, magFilter ); + + SetSamplerMessage( GetEventThreadServices(), GetSceneObject(), mSamplerBitfield ); +} + +void ImageAttachment::GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const +{ + minFilter = ImageSampler::GetMinifyFilterMode( mSamplerBitfield ); + magFilter = ImageSampler::GetMagnifyFilterMode( mSamplerBitfield ); +} + + +void ImageAttachment::SetShaderEffect(ShaderEffect& effect) +{ + if ( OnStage() ) + { + if ( mShaderEffect ) + { + mShaderEffect->Disconnect(); + } + + mShaderEffect.Reset( &effect ); + + const SceneGraph::Shader& shader = dynamic_cast( *mShaderEffect->GetSceneObject() ); + + ApplyShaderMessage( GetEventThreadServices(), GetSceneObject(), shader ); + + mShaderEffect->Connect(); + } + else + { + mShaderEffect = ShaderEffectPtr(&effect); + } + // Effects can only be applied when the Node is connected to scene-graph +} + +ShaderEffectPtr ImageAttachment::GetShaderEffect() const +{ + return mShaderEffect; +} + +void ImageAttachment::RemoveShaderEffect() +{ + if ( OnStage() ) + { + RemoveShaderMessage( GetEventThreadServices(), GetSceneObject() ); + + // Notify shader effect + if (mShaderEffect) + { + mShaderEffect->Disconnect(); + } + } + + mShaderEffect.Reset(); +} + + +void ImageAttachment::OnStageConnection2() +{ + if ( mShaderEffect ) + { + const SceneGraph::Shader& shader = dynamic_cast( *mShaderEffect->GetSceneObject() ); + + ApplyShaderMessage( GetEventThreadServices(), GetSceneObject(), shader ); + + // Notify shader effect + mShaderEffect->Connect(); + } + + mImageConnectable.OnStageConnect(); + + // Provide resource ID when scene-graph attachment is connected + ImagePtr image = mImageConnectable.Get(); + unsigned int resourceId = (image) ? image->GetResourceId() : 0u; + if ( 0u != resourceId ) + { + SetTextureIdMessage( GetEventThreadServices(), *mSceneObject, resourceId ); + } +} + +void ImageAttachment::OnStageDisconnection2() +{ + // Notify shader effect + if ( mShaderEffect ) + { + mShaderEffect->Disconnect(); + } + + // Remove resource ID when scene-graph attachment is disconnected + SetTextureIdMessage( GetEventThreadServices(), *mSceneObject, 0u ); + + mImageConnectable.OnStageDisconnect(); +} + + + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/actor-attachments/image-attachment-impl.h b/dali/internal/event/actor-attachments/image-attachment-impl.h new file mode 100644 index 0000000..0d7a7a0 --- /dev/null +++ b/dali/internal/event/actor-attachments/image-attachment-impl.h @@ -0,0 +1,297 @@ +#ifndef __DALI_INTERNAL_IMAGE_ATTACHMENT_H__ +#define __DALI_INTERNAL_IMAGE_ATTACHMENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace SceneGraph +{ +class ImageAttachment; +class Node; +} + +/** + * An attachment for rendering images in various ways. + */ +class ImageAttachment : public RenderableAttachment +{ +public: + + typedef Dali::ImageActor::Style Style; + typedef Dali::ImageActor::PixelArea PixelArea; + + /** + * Create a new ImageAttachment. + * @param[in] eventThreadServices to use + * @param[in] parentNode The node to attach a scene-object to. + * @return A smart-pointer to the newly allocated ImageAttachment. + */ + static ImageAttachmentPtr New( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode ); + + /** + * Sets image rendered by the attachment. + * @param [in] image A pointer to the image to display or NULL to clear. Reference to avoid unnecessary increment/decrement reference count. + */ + void SetImage( ImagePtr& image ); + + /** + * Retrieve the image rendered by the attachment. + * @return The image or an uninitialized image in case the ImageActor was cleared. + */ + ImagePtr GetImage(); + + /** + * Set a region of the image to display, in pixels. + * @param [in] pixelArea The area of the image to display. + * This in pixels, relative to the top-left (0,0) of the image. + */ + void SetPixelArea(const PixelArea& pixelArea); + + /** + * Retrieve the region of the image to display, in pixels. + * @return The pixel area, or a default-constructed area if none was set. + */ + const PixelArea& GetPixelArea() const + { + // This is not animatable; the cached value is up-to-date. + return mPixelArea; + } + + /** + * Query whether a pixel area has been set. + * @return True if a pixel area has been set. + */ + bool IsPixelAreaSet() const + { + // This is not animatable; the cached value is up-to-date. + return mIsPixelAreaSet; + } + + /** + * Remove any pixel areas specified with SetPixelArea; the entire image will be displayed. + * @pre image must be initialized. + */ + void ClearPixelArea(); + + /** + * Set how the ImageAttachment is rendered; the default is STYLE_QUAD. + * @param [in] style The new style. + */ + void SetStyle(Style style); + + /** + * Query how the image is rendered. + * @return The rendering style. + */ + Style GetStyle() + { + // This is not animatable; the cached value is up-to-date. + return mStyle; + } + + /** + * @copydoc Dali::ImageActor::SetNinePatchBorder + */ + void SetNinePatchBorder(const Vector4& border, bool inPixels); + + /** + * @copydoc Dali::ImageActor::GetNinePatchBorder + */ + Vector4 GetNinePatchBorder() + { + // This is not animatable; the cached value is up-to-date. + return mBorder; + } + + + /** + * Set the depth-sort modifier for the renderable. + * This modifies the back-to-front distance calculation, when rendering with transparency. + * This is useful for ordering transparent objects that are positioned close to each other. + * @param[in] modifier The depth-sort modifier. + */ + void SetSortModifier(float modifier); + + /** + * From Renderable; Retrieve the depth-sort modifier for the renderable. + * @return The depth-sort modifier. + */ + float GetSortModifier() const; + + /** + * Set the face-culling mode for this attachment. + * @param[in] mode The culling mode. + */ + void SetCullFace(CullFaceMode mode); + + /** + * Retrieve the face-culling mode for this attachment. + * @return mode The culling mode. + */ + CullFaceMode GetCullFace() const; + + /** + * @copydoc Dali::RenderableActor::SetBlendMode() + */ + void SetBlendMode( BlendingMode::Type mode ); + + /** + * @copydoc Dali::RenderableActor::GetBlendMode() + */ + BlendingMode::Type GetBlendMode() const; + + /** + * @copydoc Dali::RenderableActor::SetBlendFunc() + */ + void SetBlendFunc( BlendingFactor::Type srcFactorRgb, BlendingFactor::Type destFactorRgb, + BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha ); + + /** + * @copydoc Dali::RenderableActor::GetBlendFunc() + */ + void GetBlendFunc( BlendingFactor::Type& srcFactorRgb, BlendingFactor::Type& destFactorRgb, + BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const; + + /** + * @copydoc Dali::RenderableActor::SetBlendEquation() + */ + void SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha ); + + /** + * @copydoc Dali::RenderableActor::GetBlendEquation() + */ + void GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const; + + /** + * @copydoc Dali::RenderableActor::SetBlendColor() + */ + void SetBlendColor( const Vector4& color ); + + /** + * @copydoc Dali::RenderableActor::GetBlendColor() + */ + const Vector4& GetBlendColor() const; + + /** + * @copydoc Dali::RenderableActor::SetFilterMode() + */ + void SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter ); + + /** + * @copydoc Dali::RenderableActor::GetFilterMode() + */ + void GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const; + + /** + * @copydoc Dali::RenderableActor::SetShaderEffect + */ + void SetShaderEffect(ShaderEffect& effect); + + /** + * @copydoc Dali::RenderableActor::GetShaderEffect + */ + ShaderEffectPtr GetShaderEffect() const; + + /** + * @copydoc Dali::RenderableActor::RemoveShaderEffect + */ + void RemoveShaderEffect(); + +private: + + /** + * First stage construction of a ImageAttachment. + * @param[in] eventThreadServices Used for messaging to and reading from scene-graph. + */ + ImageAttachment( EventThreadServices& eventThreadServices ); + + /** + * Creates the corresponding scene-graph ImageAttachment. + * @return A newly allocated scene object. + */ + static SceneGraph::ImageAttachment* CreateSceneObject(); + + /** + * @copydoc Dali::Internal::RenderableAttachment::OnStageConnection2() + */ + virtual void OnStageConnection2(); + + /** + * @copydoc Dali::Internal::RenderableAttachment::OnStageDisconnection2() + */ + virtual void OnStageDisconnection2(); + + /** + * @copydoc Dali::Internal::RenderableAttachment::GetSceneObject() + */ + const SceneGraph::ImageAttachment& GetSceneObject() const; + +protected: + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~ImageAttachment(); + +private: + + const SceneGraph::ImageAttachment* mSceneObject; ///< Not owned + + ImageConnector mImageConnectable; ///< Manages the image displayed by the attachment + + // Cached for public getters + + PixelArea mPixelArea; + + Style mStyle; + Vector4 mBorder; + + bool mIsPixelAreaSet : 1; + bool mBorderInPixels : 1; + + BlendingOptions mBlendingOptions; + unsigned int mSamplerBitfield; + float mSortModifier; + CullFaceMode mCullFaceMode:3; ///< cullface mode, 3 bits enough for 4 values + BlendingMode::Type mBlendingMode:2; ///< blending mode, 2 bits enough for 3 values + + ShaderEffectPtr mShaderEffect; ///< Optional referenced shader effect +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_IMAGE_ATTACHMENT_H__ diff --git a/dali/internal/event/actor-attachments/renderable-attachment-impl.cpp b/dali/internal/event/actor-attachments/renderable-attachment-impl.cpp new file mode 100644 index 0000000..9902e82 --- /dev/null +++ b/dali/internal/event/actor-attachments/renderable-attachment-impl.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include + +using Dali::Internal::SceneGraph::Shader; + +namespace Dali +{ + +namespace Internal +{ + +RenderableAttachment::RenderableAttachment( EventThreadServices& eventThreadServices ) +: ActorAttachment( eventThreadServices ) +{ +} + +RenderableAttachment::~RenderableAttachment() +{ +} + +void RenderableAttachment::OnStageConnection() +{ + // For derived classes + OnStageConnection2(); +} + +void RenderableAttachment::OnStageDisconnection() +{ + // For derived classes + OnStageDisconnection2(); +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/actor-attachments/renderable-attachment-impl.h b/dali/internal/event/actor-attachments/renderable-attachment-impl.h new file mode 100644 index 0000000..87d51d9 --- /dev/null +++ b/dali/internal/event/actor-attachments/renderable-attachment-impl.h @@ -0,0 +1,99 @@ +#ifndef __DALI_INTERNAL_RENDERABLE_ATTACHMENT_H__ +#define __DALI_INTERNAL_RENDERABLE_ATTACHMENT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace SceneGraph +{ +class RenderableAttachment; +} + +/** + * An base class for renderable actor attachments + */ +class RenderableAttachment : public ActorAttachment +{ +public: + + + +protected: + + /** + * Protected constructor; only base classes are instantiatable. + * @param[in] eventThreadServices Used for messaging to and reading from scene-graph. + */ + RenderableAttachment( EventThreadServices& eventThreadServices ); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~RenderableAttachment(); + +private: + + // Undefined + RenderableAttachment(const RenderableAttachment&); + + // Undefined + RenderableAttachment& operator=(const RenderableAttachment& rhs); + + /** + * Helper for getting the scene-graph renderable attachment. + * @return The scene object. + */ + const SceneGraph::RenderableAttachment& GetSceneAttachment() const; + + /** + * @copydoc Dali::Internal::ActorAttachment::OnStageConnection() + */ + virtual void OnStageConnection(); + + /** + * @copydoc Dali::Internal::ActorAttachment::OnStageDisconnection() + */ + virtual void OnStageDisconnection(); + + /** + * For derived classes, chained from OnStageConnection() + */ + virtual void OnStageConnection2() = 0; + + /** + * For derived classes, chained from OnStageDisconnection() + */ + virtual void OnStageDisconnection2() = 0; + +private: // Data, cached for actor-thread getters + +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_RENDERABLE_ATTACHMENT_H__ diff --git a/dali/internal/event/actor-attachments/renderer-attachment-impl.cpp b/dali/internal/event/actor-attachments/renderer-attachment-impl.cpp new file mode 100644 index 0000000..56ee7ca --- /dev/null +++ b/dali/internal/event/actor-attachments/renderer-attachment-impl.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +RendererAttachmentPtr RendererAttachment::New( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode, Renderer& renderer ) +{ + RendererAttachmentPtr attachment( new RendererAttachment( eventThreadServices ) ); + + if( attachment ) + { + attachment->Initialize( eventThreadServices, parentNode, renderer ); + } + return attachment; +} + +void RendererAttachment::Initialize( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode, Renderer& renderer ) +{ + SceneGraph::RendererAttachment* sceneObject = renderer.GetRendererSceneObject(); + + // Takes ownership of scene object + AttachToNodeMessage( eventThreadServices.GetUpdateManager(), parentNode, sceneObject ); + + // Connect to renderer + mRendererConnector.Set( renderer, false ); + + // Keep raw pointer for message passing + mSceneObject = sceneObject; +} + +RendererAttachment::RendererAttachment( EventThreadServices& eventThreadServices ) +: RenderableAttachment(eventThreadServices), + mSceneObject(NULL) +{ +} + +RendererAttachment::~RendererAttachment() +{ +} + +const SceneGraph::RendererAttachment& RendererAttachment::GetSceneObject() const +{ + DALI_ASSERT_DEBUG( mSceneObject != NULL ); + return *mSceneObject; +} + +void RendererAttachment::OnStageConnection2() +{ + mRendererConnector.OnStageConnect(); +} + +void RendererAttachment::OnStageDisconnection2() +{ + mRendererConnector.OnStageDisconnect(); +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/actor-attachments/renderer-attachment-impl.h b/dali/internal/event/actor-attachments/renderer-attachment-impl.h new file mode 100644 index 0000000..a61be66 --- /dev/null +++ b/dali/internal/event/actor-attachments/renderer-attachment-impl.h @@ -0,0 +1,120 @@ +#ifndef DALI_INTERNAL_RENDERER_ATTACHMENT_H +#define DALI_INTERNAL_RENDERER_ATTACHMENT_H + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace SceneGraph +{ +class Node; +class RendererAttachment; +} + +class RendererAttachment; +typedef IntrusivePtr RendererAttachmentPtr; + +/** + * An attachment for rendering renderers. + * + * Currently, the Renderer object creates the SceneGraph::RendererAttachment object, not this. It is attached + * here as needed. + */ +class RendererAttachment : public RenderableAttachment +{ +public: + + /** + * Create a new RendererAttachment. + * @param[in] eventThreadServices Used for messaging to and reading from the SceneGraph + * @param[in] parentNode The node to attach a scene-object to. + * @poaram[in] renderer The renderer for this attachment + * @return A smart-pointer to the newly allocated RendererAttachment. + */ + static RendererAttachmentPtr New( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode, Renderer& renderer ); + + + /** + * Second stage initialization + * + * @param[in] eventThreadServices Used for messaging to and reading from the SceneGraph + * @param[in] parentNode The node to attach a scene-object to. + * @poaram[in] renderer The renderer for this attachment + */ + void Initialize( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode, Renderer& renderer ); + + /** + * Get the renderer + * + * @return The renderer + */ + Renderer& GetRenderer() + { + return *mRendererConnector.Get(); + } + +private: + + /** + * First stage construction of a RendererAttachment. + * @param[in] eventThreadServices Used for messaging to and reading from the SceneGraph + */ + RendererAttachment( EventThreadServices& eventThreadServices ); + + /** + * @copydoc Dali::Internal::RenderableAttachment::GetSceneObject() + */ + virtual const SceneGraph::RendererAttachment& GetSceneObject() const; + + /** + * @copydoc Dali::Internal::RenderableAttachment::OnStageConnection2() + */ + virtual void OnStageConnection2(); + + /** + * @copydoc Dali::Internal::RenderableAttachment::OnStageDisconnection2() + */ + virtual void OnStageDisconnection2(); + +protected: + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~RendererAttachment(); + +private: + const SceneGraph::RendererAttachment* mSceneObject; ///< Not owned + + ObjectConnector mRendererConnector; +}; + +} // namespace Internal + +} // namespace Dali + +#endif // DALI_INTERNAL_RENDERER_ATTACHMENT_H diff --git a/dali/internal/event/actors/actor-declarations.h b/dali/internal/event/actors/actor-declarations.h new file mode 100644 index 0000000..a4b1e10 --- /dev/null +++ b/dali/internal/event/actors/actor-declarations.h @@ -0,0 +1,46 @@ +#ifndef __DALI_INTERNAL_ACTOR_DECLARATIONS_H__ +#define __DALI_INTERNAL_ACTOR_DECLARATIONS_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +class Actor; +class CameraActor; +class CustomActor; +class ImageActor; +class Layer; + +typedef IntrusivePtr ActorPtr; +typedef IntrusivePtr CameraActorPtr; +typedef IntrusivePtr CustomActorPtr; +typedef IntrusivePtr ImageActorPtr; +typedef IntrusivePtr LayerPtr; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_ACTOR_DECLARATIONS_H__ diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp new file mode 100644 index 0000000..dca7ba4 --- /dev/null +++ b/dali/internal/event/actors/actor-impl.cpp @@ -0,0 +1,4113 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include +#include + +// INTERNAL INCLUDES + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using Dali::Internal::SceneGraph::Node; +using Dali::Internal::SceneGraph::AnimatableProperty; +using Dali::Internal::SceneGraph::PropertyBase; + +namespace Dali +{ +namespace ResizePolicy +{ + +namespace +{ +DALI_ENUM_TO_STRING_TABLE_BEGIN( Type ) +DALI_ENUM_TO_STRING( FIXED ) +DALI_ENUM_TO_STRING( USE_NATURAL_SIZE ) +DALI_ENUM_TO_STRING( FILL_TO_PARENT ) +DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT ) +DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT ) +DALI_ENUM_TO_STRING( FIT_TO_CHILDREN ) +DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY ) +DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE ) +DALI_ENUM_TO_STRING_TABLE_END( Type ) + +} // unnamed namespace +} // ResizePolicy + +namespace SizeScalePolicy +{ +namespace +{ +// Enumeration to / from string conversion tables +DALI_ENUM_TO_STRING_TABLE_BEGIN( Type ) +DALI_ENUM_TO_STRING( USE_SIZE_SET ) +DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO ) +DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO ) +DALI_ENUM_TO_STRING_TABLE_END( Type ) +} // unnamed namespace +} // SizeScalePolicy + +namespace Internal +{ + +unsigned int Actor::mActorCounter = 0; + +namespace +{ +/// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet. +inline const Vector3& GetDefaultSizeModeFactor() +{ + return Vector3::ONE; +} + +/// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet. +inline const Vector2& GetDefaultPreferredSize() +{ + return Vector2::ZERO; +} + +/// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet. +inline const Vector2& GetDefaultDimensionPadding() +{ + return Vector2::ZERO; +} + +const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET; + +} // unnamed namespace + +/** + * Struct to collect relayout variables + */ +struct Actor::RelayoutData +{ + RelayoutData() + : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false ) + { + // Set size negotiation defaults + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + resizePolicies[ i ] = ResizePolicy::DEFAULT; + negotiatedDimensions[ i ] = 0.0f; + dimensionNegotiated[ i ] = false; + dimensionDirty[ i ] = false; + dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS; + dimensionPadding[ i ] = GetDefaultDimensionPadding(); + minimumSize[ i ] = 0.0f; + maximumSize[ i ] = FLT_MAX; + } + } + + ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ]; ///< Resize policies + + Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ]; ///< A list of dimension dependencies + + Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ]; ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top) + + float negotiatedDimensions[ Dimension::DIMENSION_COUNT ]; ///< Storage for when a dimension is negotiated but before set on actor + + float minimumSize[ Dimension::DIMENSION_COUNT ]; ///< The minimum size an actor can be + float maximumSize[ Dimension::DIMENSION_COUNT ]; ///< The maximum size an actor can be + + bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ]; ///< Has the dimension been negotiated + bool dimensionDirty[ Dimension::DIMENSION_COUNT ]; ///< Flags indicating whether the layout dimension is dirty or not + + Vector3 sizeModeFactor; ///< Factor of size used for certain SizeModes + + Vector2 preferredSize; ///< The preferred size of the actor + + SizeScalePolicy::Type sizeSetPolicy :3; ///< Policy to apply when setting size. Enough room for the enum + + bool relayoutEnabled :1; ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true) + bool insideRelayout :1; ///< Locking flag to prevent recursive relayouts on size set +}; + +namespace // unnamed namespace +{ + +// Properties + +/** + * We want to discourage the use of property strings (minimize string comparisons), + * particularly for the default properties. + * Name Type writable animatable constraint-input enum for index-checking + */ +DALI_PROPERTY_TABLE_BEGIN +DALI_PROPERTY( "parent-origin", VECTOR3, true, false, true, Dali::Actor::Property::PARENT_ORIGIN ) +DALI_PROPERTY( "parent-origin-x", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_X ) +DALI_PROPERTY( "parent-origin-y", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Y ) +DALI_PROPERTY( "parent-origin-z", FLOAT, true, false, true, Dali::Actor::Property::PARENT_ORIGIN_Z ) +DALI_PROPERTY( "anchor-point", VECTOR3, true, false, true, Dali::Actor::Property::ANCHOR_POINT ) +DALI_PROPERTY( "anchor-point-x", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_X ) +DALI_PROPERTY( "anchor-point-y", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Y ) +DALI_PROPERTY( "anchor-point-z", FLOAT, true, false, true, Dali::Actor::Property::ANCHOR_POINT_Z ) +DALI_PROPERTY( "size", VECTOR3, true, true, true, Dali::Actor::Property::SIZE ) +DALI_PROPERTY( "size-width", FLOAT, true, true, true, Dali::Actor::Property::SIZE_WIDTH ) +DALI_PROPERTY( "size-height", FLOAT, true, true, true, Dali::Actor::Property::SIZE_HEIGHT ) +DALI_PROPERTY( "size-depth", FLOAT, true, true, true, Dali::Actor::Property::SIZE_DEPTH ) +DALI_PROPERTY( "position", VECTOR3, true, true, true, Dali::Actor::Property::POSITION ) +DALI_PROPERTY( "position-x", FLOAT, true, true, true, Dali::Actor::Property::POSITION_X ) +DALI_PROPERTY( "position-y", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Y ) +DALI_PROPERTY( "position-z", FLOAT, true, true, true, Dali::Actor::Property::POSITION_Z ) +DALI_PROPERTY( "world-position", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_POSITION ) +DALI_PROPERTY( "world-position-x", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_X ) +DALI_PROPERTY( "world-position-y", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Y ) +DALI_PROPERTY( "world-position-z", FLOAT, false, false, true, Dali::Actor::Property::WORLD_POSITION_Z ) +DALI_PROPERTY( "orientation", ROTATION, true, true, true, Dali::Actor::Property::ORIENTATION ) +DALI_PROPERTY( "world-orientation", ROTATION, false, false, true, Dali::Actor::Property::WORLD_ORIENTATION ) +DALI_PROPERTY( "scale", VECTOR3, true, true, true, Dali::Actor::Property::SCALE ) +DALI_PROPERTY( "scale-x", FLOAT, true, true, true, Dali::Actor::Property::SCALE_X ) +DALI_PROPERTY( "scale-y", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Y ) +DALI_PROPERTY( "scale-z", FLOAT, true, true, true, Dali::Actor::Property::SCALE_Z ) +DALI_PROPERTY( "world-scale", VECTOR3, false, false, true, Dali::Actor::Property::WORLD_SCALE ) +DALI_PROPERTY( "visible", BOOLEAN, true, true, true, Dali::Actor::Property::VISIBLE ) +DALI_PROPERTY( "color", VECTOR4, true, true, true, Dali::Actor::Property::COLOR ) +DALI_PROPERTY( "color-red", FLOAT, true, true, true, Dali::Actor::Property::COLOR_RED ) +DALI_PROPERTY( "color-green", FLOAT, true, true, true, Dali::Actor::Property::COLOR_GREEN ) +DALI_PROPERTY( "color-blue", FLOAT, true, true, true, Dali::Actor::Property::COLOR_BLUE ) +DALI_PROPERTY( "color-alpha", FLOAT, true, true, true, Dali::Actor::Property::COLOR_ALPHA ) +DALI_PROPERTY( "world-color", VECTOR4, false, false, true, Dali::Actor::Property::WORLD_COLOR ) +DALI_PROPERTY( "world-matrix", MATRIX, false, false, true, Dali::Actor::Property::WORLD_MATRIX ) +DALI_PROPERTY( "name", STRING, true, false, false, Dali::Actor::Property::NAME ) +DALI_PROPERTY( "sensitive", BOOLEAN, true, false, false, Dali::Actor::Property::SENSITIVE ) +DALI_PROPERTY( "leave-required", BOOLEAN, true, false, false, Dali::Actor::Property::LEAVE_REQUIRED ) +DALI_PROPERTY( "inherit-orientation",BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_ORIENTATION ) +DALI_PROPERTY( "inherit-scale", BOOLEAN, true, false, false, Dali::Actor::Property::INHERIT_SCALE ) +DALI_PROPERTY( "color-mode", STRING, true, false, false, Dali::Actor::Property::COLOR_MODE ) +DALI_PROPERTY( "position-inheritance",STRING, true, false, false, Dali::Actor::Property::POSITION_INHERITANCE ) +DALI_PROPERTY( "draw-mode", STRING, true, false, false, Dali::Actor::Property::DRAW_MODE ) +DALI_PROPERTY( "size-mode-factor", VECTOR3, true, false, false, Dali::Actor::Property::SIZE_MODE_FACTOR ) +DALI_PROPERTY( "width-resize-policy",STRING, true, false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY ) +DALI_PROPERTY( "height-resize-policy",STRING, true, false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY ) +DALI_PROPERTY( "size-scale-policy", STRING, true, false, false, Dali::Actor::Property::SIZE_SCALE_POLICY ) +DALI_PROPERTY( "width-for-height", BOOLEAN, true, false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT ) +DALI_PROPERTY( "height-for-width", BOOLEAN, true, false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH ) +DALI_PROPERTY( "padding", VECTOR4, true, false, false, Dali::Actor::Property::PADDING ) +DALI_PROPERTY( "minimum-size", VECTOR2, true, false, false, Dali::Actor::Property::MINIMUM_SIZE ) +DALI_PROPERTY( "maximum-size", VECTOR2, true, false, false, Dali::Actor::Property::MAXIMUM_SIZE ) +DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX ) + +// Signals + +const char* const SIGNAL_TOUCHED = "touched"; +const char* const SIGNAL_HOVERED = "hovered"; +const char* const SIGNAL_WHEEL_EVENT = "wheel-event"; +const char* const SIGNAL_ON_STAGE = "on-stage"; +const char* const SIGNAL_OFF_STAGE = "off-stage"; + +// Actions + +const char* const ACTION_SHOW = "show"; +const char* const ACTION_HIDE = "hide"; + +BaseHandle CreateActor() +{ + return Dali::Actor::New(); +} + +TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor ); + +SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal ); +SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal ); +SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal ); +SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal ); + +TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction ); +TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction ); + +/** + * @brief Extract a given dimension from a Vector2 + * + * @param[in] values The values to extract from + * @param[in] dimension The dimension to extract + * @return Return the value for the dimension + */ +float GetDimensionValue( const Vector2& values, Dimension::Type dimension ) +{ + switch( dimension ) + { + case Dimension::WIDTH: + { + return values.width; + } + case Dimension::HEIGHT: + { + return values.height; + } + default: + { + break; + } + } + return 0.0f; +} + +/** + * @brief Extract a given dimension from a Vector3 + * + * @param[in] values The values to extract from + * @param[in] dimension The dimension to extract + * @return Return the value for the dimension + */ +float GetDimensionValue( const Vector3& values, Dimension::Type dimension ) +{ + return GetDimensionValue( values.GetVectorXY(), dimension ); +} + + +} // unnamed namespace + +ActorPtr Actor::New() +{ + ActorPtr actor( new Actor( BASIC ) ); + + // Second-phase construction + actor->Initialize(); + + return actor; +} + +const std::string& Actor::GetName() const +{ + return mName; +} + +void Actor::SetName( const std::string& name ) +{ + mName = name; + + if( NULL != mNode ) + { + // ATTENTION: string for debug purposes is not thread safe. + DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name ); + } +} + +unsigned int Actor::GetId() const +{ + return mId; +} + +void Actor::Attach( ActorAttachment& attachment ) +{ + DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" ); + + if( OnStage() ) + { + attachment.Connect(); + } + + mAttachment = ActorAttachmentPtr( &attachment ); +} + +ActorAttachmentPtr Actor::GetAttachment() +{ + return mAttachment; +} + +bool Actor::OnStage() const +{ + return mIsOnStage; +} + +Dali::Layer Actor::GetLayer() +{ + Dali::Layer layer; + + // Short-circuit for Layer derived actors + if( mIsLayer ) + { + layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag + } + + // Find the immediate Layer parent + for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() ) + { + if( parent->IsLayer() ) + { + layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag + } + } + + return layer; +} + +void Actor::Add( Actor& child ) +{ + DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" ); + DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" ); + + if( !mChildren ) + { + mChildren = new ActorContainer; + } + + Actor* const oldParent( child.mParent ); + + // child might already be ours + if( this != oldParent ) + { + // if we already have parent, unparent us first + if( oldParent ) + { + oldParent->Remove( child ); // This causes OnChildRemove callback + + // Old parent may need to readjust to missing child + if( oldParent->RelayoutDependentOnChildren() ) + { + oldParent->RelayoutRequest(); + } + } + + // Guard against Add() during previous OnChildRemove callback + if( !child.mParent ) + { + // Do this first, since user callbacks from within SetParent() may need to remove child + mChildren->push_back( ActorPtr( &child ) ); + + // SetParent asserts that child can be added + child.SetParent( this ); + + // Notification for derived classes + OnChildAdd( child ); + + // Only put in a relayout request if there is a suitable dependency + if( RelayoutDependentOnChildren() ) + { + RelayoutRequest(); + } + } + } +} + +void Actor::Remove( Actor& child ) +{ + if( (this == &child) || (!mChildren) ) + { + // no children or removing itself + return; + } + + ActorPtr removed; + + // Find the child in mChildren, and unparent it + ActorIter end = mChildren->end(); + for( ActorIter iter = mChildren->begin(); iter != end; ++iter ) + { + ActorPtr actor = (*iter); + + if( actor.Get() == &child ) + { + // Keep handle for OnChildRemove notification + removed = actor; + + // Do this first, since user callbacks from within SetParent() may need to add the child + mChildren->erase( iter ); + + DALI_ASSERT_DEBUG( actor->GetParent() == this ); + actor->SetParent( NULL ); + + break; + } + } + + if( removed ) + { + // Notification for derived classes + OnChildRemove( *(removed.Get()) ); + + // Only put in a relayout request if there is a suitable dependency + if( RelayoutDependentOnChildren() ) + { + RelayoutRequest(); + } + } +} + +void Actor::Unparent() +{ + if( mParent ) + { + // Remove this actor from the parent. The remove will put a relayout request in for + // the parent if required + mParent->Remove( *this ); + // mParent is now NULL! + } +} + +unsigned int Actor::GetChildCount() const +{ + return ( NULL != mChildren ) ? mChildren->size() : 0; +} + +ActorPtr Actor::GetChildAt( unsigned int index ) const +{ + DALI_ASSERT_ALWAYS( index < GetChildCount() ); + + return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() ); +} + +ActorPtr Actor::FindChildByName( const std::string& actorName ) +{ + ActorPtr child = 0; + if( actorName == mName ) + { + child = this; + } + else if( mChildren ) + { + ActorIter end = mChildren->end(); + for( ActorIter iter = mChildren->begin(); iter != end; ++iter ) + { + child = (*iter)->FindChildByName( actorName ); + + if( child ) + { + break; + } + } + } + return child; +} + +ActorPtr Actor::FindChildById( const unsigned int id ) +{ + ActorPtr child = 0; + if( id == mId ) + { + child = this; + } + else if( mChildren ) + { + ActorIter end = mChildren->end(); + for( ActorIter iter = mChildren->begin(); iter != end; ++iter ) + { + child = (*iter)->FindChildById( id ); + + if( child ) + { + break; + } + } + } + return child; +} + +void Actor::SetParentOrigin( const Vector3& origin ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SetParentOriginMessage( GetEventThreadServices(), *mNode, origin ); + } + + // Cache for event-thread access + if( !mParentOrigin ) + { + // not allocated, check if different from default + if( ParentOrigin::DEFAULT != origin ) + { + mParentOrigin = new Vector3( origin ); + } + } + else + { + // check if different from current costs more than just set + *mParentOrigin = origin; + } +} + +void Actor::SetParentOriginX( float x ) +{ + const Vector3& current = GetCurrentParentOrigin(); + + SetParentOrigin( Vector3( x, current.y, current.z ) ); +} + +void Actor::SetParentOriginY( float y ) +{ + const Vector3& current = GetCurrentParentOrigin(); + + SetParentOrigin( Vector3( current.x, y, current.z ) ); +} + +void Actor::SetParentOriginZ( float z ) +{ + const Vector3& current = GetCurrentParentOrigin(); + + SetParentOrigin( Vector3( current.x, current.y, z ) ); +} + +const Vector3& Actor::GetCurrentParentOrigin() const +{ + // Cached for event-thread access + return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT; +} + +void Actor::SetAnchorPoint( const Vector3& anchor ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor ); + } + + // Cache for event-thread access + if( !mAnchorPoint ) + { + // not allocated, check if different from default + if( AnchorPoint::DEFAULT != anchor ) + { + mAnchorPoint = new Vector3( anchor ); + } + } + else + { + // check if different from current costs more than just set + *mAnchorPoint = anchor; + } +} + +void Actor::SetAnchorPointX( float x ) +{ + const Vector3& current = GetCurrentAnchorPoint(); + + SetAnchorPoint( Vector3( x, current.y, current.z ) ); +} + +void Actor::SetAnchorPointY( float y ) +{ + const Vector3& current = GetCurrentAnchorPoint(); + + SetAnchorPoint( Vector3( current.x, y, current.z ) ); +} + +void Actor::SetAnchorPointZ( float z ) +{ + const Vector3& current = GetCurrentAnchorPoint(); + + SetAnchorPoint( Vector3( current.x, current.y, z ) ); +} + +const Vector3& Actor::GetCurrentAnchorPoint() const +{ + // Cached for event-thread access + return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT; +} + +void Actor::SetPosition( float x, float y ) +{ + SetPosition( Vector3( x, y, 0.0f ) ); +} + +void Actor::SetPosition( float x, float y, float z ) +{ + SetPosition( Vector3( x, y, z ) ); +} + +void Actor::SetPosition( const Vector3& position ) +{ + mTargetPosition = position; + + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty::Bake, position ); + } +} + +void Actor::SetX( float x ) +{ + mTargetPosition.x = x; + + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty::BakeX, x ); + } +} + +void Actor::SetY( float y ) +{ + mTargetPosition.y = y; + + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty::BakeY, y ); + } +} + +void Actor::SetZ( float z ) +{ + mTargetPosition.z = z; + + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty::BakeZ, z ); + } +} + +void Actor::TranslateBy( const Vector3& distance ) +{ + mTargetPosition += distance; + + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty::BakeRelative, distance ); + } +} + +const Vector3& Actor::GetCurrentPosition() const +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; copy the value from the previous update + return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex()); + } + + return Vector3::ZERO; +} + +const Vector3& Actor::GetTargetPosition() const +{ + return mTargetPosition; +} + +const Vector3& Actor::GetCurrentWorldPosition() const +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; copy the value from the previous update + return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() ); + } + + return Vector3::ZERO; +} + +void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode ) +{ + // this flag is not animatable so keep the value + mPositionInheritanceMode = mode; + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value + SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode ); + } +} + +PositionInheritanceMode Actor::GetPositionInheritanceMode() const +{ + // Cached for event-thread access + return mPositionInheritanceMode; +} + +void Actor::SetOrientation( const Radian& angle, const Vector3& axis ) +{ + Vector3 normalizedAxis( axis.x, axis.y, axis.z ); + normalizedAxis.Normalize(); + + Quaternion orientation( angle, normalizedAxis ); + + SetOrientation( orientation ); +} + +void Actor::SetOrientation( const Quaternion& orientation ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty::Bake, orientation ); + } +} + +void Actor::RotateBy( const Radian& angle, const Vector3& axis ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty::BakeRelative, Quaternion(angle, axis) ); + } +} + +void Actor::RotateBy( const Quaternion& relativeRotation ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty::BakeRelative, relativeRotation ); + } +} + +const Quaternion& Actor::GetCurrentOrientation() const +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; copy the value from the previous update + return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex()); + } + + return Quaternion::IDENTITY; +} + +const Quaternion& Actor::GetCurrentWorldOrientation() const +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; copy the value from the previous update + return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() ); + } + + return Quaternion::IDENTITY; +} + +void Actor::SetScale( float scale ) +{ + SetScale( Vector3( scale, scale, scale ) ); +} + +void Actor::SetScale( float x, float y, float z ) +{ + SetScale( Vector3( x, y, z ) ); +} + +void Actor::SetScale( const Vector3& scale ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty::Bake, scale ); + } +} + +void Actor::SetScaleX( float x ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty::BakeX, x ); + } +} + +void Actor::SetScaleY( float y ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty::BakeY, y ); + } +} + +void Actor::SetScaleZ( float z ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty::BakeZ, z ); + } +} + +void Actor::ScaleBy(const Vector3& relativeScale) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty::BakeRelativeMultiply, relativeScale ); + } +} + +const Vector3& Actor::GetCurrentScale() const +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; copy the value from the previous update + return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex()); + } + + return Vector3::ONE; +} + +const Vector3& Actor::GetCurrentWorldScale() const +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; copy the value from the previous update + return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() ); + } + + return Vector3::ONE; +} + +void Actor::SetInheritScale( bool inherit ) +{ + // non animateable so keep local copy + mInheritScale = inherit; + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value + SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit ); + } +} + +bool Actor::IsScaleInherited() const +{ + return mInheritScale; +} + +Matrix Actor::GetCurrentWorldMatrix() const +{ + if( NULL != mNode ) + { + // World matrix is no longer updated unless there is something observing the node. + // Need to calculate it from node's world position, orientation and scale: + BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex(); + Matrix worldMatrix(false); + worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ), + mNode->GetWorldOrientation( updateBufferIndex ), + mNode->GetWorldPosition( updateBufferIndex ) ); + return worldMatrix; + } + + return Matrix::IDENTITY; +} + +void Actor::SetVisible( bool visible ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty::Bake, visible ); + } +} + +bool Actor::IsVisible() const +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; copy the value from the previous update + return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() ); + } + + return true; +} + +void Actor::SetOpacity( float opacity ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty::BakeW, opacity ); + } +} + +float Actor::GetCurrentOpacity() const +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; copy the value from the previous update + return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex()); + } + + return 1.0f; +} + +const Vector4& Actor::GetCurrentWorldColor() const +{ + if( NULL != mNode ) + { + return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() ); + } + + return Color::WHITE; +} + +void Actor::SetColor( const Vector4& color ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty::Bake, color ); + } +} + +void Actor::SetColorRed( float red ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty::BakeX, red ); + } +} + +void Actor::SetColorGreen( float green ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty::BakeY, green ); + } +} + +void Actor::SetColorBlue( float blue ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty::BakeZ, blue ); + } +} + +const Vector4& Actor::GetCurrentColor() const +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; copy the value from the previous update + return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex()); + } + + return Color::WHITE; +} + +void Actor::SetInheritOrientation( bool inherit ) +{ + // non animateable so keep local copy + mInheritOrientation = inherit; + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value + SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit ); + } +} + +bool Actor::IsOrientationInherited() const +{ + return mInheritOrientation; +} + +void Actor::SetSizeModeFactor( const Vector3& factor ) +{ + EnsureRelayoutData(); + + mRelayoutData->sizeModeFactor = factor; +} + +const Vector3& Actor::GetSizeModeFactor() const +{ + if ( mRelayoutData ) + { + return mRelayoutData->sizeModeFactor; + } + + return GetDefaultSizeModeFactor(); +} + +void Actor::SetColorMode( ColorMode colorMode ) +{ + // non animateable so keep local copy + mColorMode = colorMode; + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value + SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode ); + } +} + +ColorMode Actor::GetColorMode() const +{ + // we have cached copy + return mColorMode; +} + +void Actor::SetSize( float width, float height ) +{ + SetSize( Vector2( width, height ) ); +} + +void Actor::SetSize( float width, float height, float depth ) +{ + SetSize( Vector3( width, height, depth ) ); +} + +void Actor::SetSize( const Vector2& size ) +{ + SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) ); +} + +void Actor::SetSizeInternal( const Vector2& size ) +{ + SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) ); +} + +float Actor::CalculateSizeZ( const Vector2& size ) const +{ + return std::min( size.width, size.height ); +} + +void Actor::SetSize( const Vector3& size ) +{ + if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout ) + { + SetPreferredSize( size.GetVectorXY() ); + } + else + { + SetSizeInternal( size ); + } +} + +void Actor::SetSizeInternal( const Vector3& size ) +{ + // dont allow recursive loop + DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" ); + // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one + if( ( NULL != mNode )&& + ( ( fabsf( mTargetSize.width - size.width ) > Math::MACHINE_EPSILON_1 )|| + ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )|| + ( fabsf( mTargetSize.depth - size.depth ) > Math::MACHINE_EPSILON_1 ) ) ) + { + mTargetSize = size; + + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty::Bake, mTargetSize ); + + // Notification for derived classes + mInsideOnSizeSet = true; + OnSizeSet( mTargetSize ); + mInsideOnSizeSet = false; + + // Raise a relayout request if the flag is not locked + if( mRelayoutData && !mRelayoutData->insideRelayout ) + { + RelayoutRequest(); + } + } +} + +void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize ) +{ + mTargetSize = targetSize; + + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); +} + +void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property ) +{ + if ( Dali::Actor::Property::SIZE_WIDTH == property ) + { + mTargetSize.width = targetSize; + } + else if ( Dali::Actor::Property::SIZE_HEIGHT == property ) + { + mTargetSize.height = targetSize; + } + // Notify deriving classes + OnSizeAnimation( animation, mTargetSize ); +} + +void Actor::SetWidth( float width ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty::BakeX, width ); + } +} + +void Actor::SetHeight( float height ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty::BakeY, height ); + } +} + +void Actor::SetDepth( float depth ) +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value & base value + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty::BakeZ, depth ); + } +} + +const Vector3& Actor::GetTargetSize() const +{ + return mTargetSize; +} + +const Vector3& Actor::GetCurrentSize() const +{ + if( NULL != mNode ) + { + // mNode is being used in a separate thread; copy the value from the previous update + return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() ); + } + + return Vector3::ZERO; +} + +Vector3 Actor::GetNaturalSize() const +{ + // It is up to deriving classes to return the appropriate natural size + return Vector3( 0.0f, 0.0f, 0.0f ); +} + +void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) +{ + EnsureRelayoutData(); + + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + mRelayoutData->resizePolicies[ i ] = policy; + } + } + + if( policy == ResizePolicy::DIMENSION_DEPENDENCY ) + { + if( dimension & Dimension::WIDTH ) + { + SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT ); + } + + if( dimension & Dimension::HEIGHT ) + { + SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH ); + } + } + + // If calling SetResizePolicy, assume we want relayout enabled + SetRelayoutEnabled( true ); + + OnSetResizePolicy( policy, dimension ); + + // Trigger relayout on this control + RelayoutRequest(); +} + +ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const +{ + if ( mRelayoutData ) + { + // If more than one dimension is requested, just return the first one found + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( ( dimension & ( 1 << i ) ) ) + { + return mRelayoutData->resizePolicies[ i ]; + } + } + } + + return ResizePolicy::DEFAULT; +} + +void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy ) +{ + EnsureRelayoutData(); + + mRelayoutData->sizeSetPolicy = policy; +} + +SizeScalePolicy::Type Actor::GetSizeScalePolicy() const +{ + if ( mRelayoutData ) + { + return mRelayoutData->sizeSetPolicy; + } + + return DEFAULT_SIZE_SCALE_POLICY; +} + +void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency ) +{ + EnsureRelayoutData(); + + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + mRelayoutData->dimensionDependencies[ i ] = dependency; + } + } +} + +Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const +{ + if ( mRelayoutData ) + { + // If more than one dimension is requested, just return the first one found + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( ( dimension & ( 1 << i ) ) ) + { + return mRelayoutData->dimensionDependencies[ i ]; + } + } + } + + return Dimension::ALL_DIMENSIONS; // Default +} + +void Actor::SetRelayoutEnabled( bool relayoutEnabled ) +{ + // If relayout data has not been allocated yet and the client is requesting + // to disable it, do nothing + if( mRelayoutData || relayoutEnabled ) + { + EnsureRelayoutData(); + + mRelayoutData->relayoutEnabled = relayoutEnabled; + } +} + +bool Actor::IsRelayoutEnabled() const +{ + // Assume that if relayout data has not been allocated yet then + // relayout is disabled + return mRelayoutData && mRelayoutData->relayoutEnabled; +} + +void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension ) +{ + EnsureRelayoutData(); + + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + mRelayoutData->dimensionDirty[ i ] = dirty; + } + } +} + +bool Actor::IsLayoutDirty( Dimension::Type dimension ) const +{ + if ( mRelayoutData ) + { + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] ) + { + return true; + } + } + } + + return false; +} + +bool Actor::RelayoutPossible( Dimension::Type dimension ) const +{ + return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension ); +} + +bool Actor::RelayoutRequired( Dimension::Type dimension ) const +{ + return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension ); +} + +unsigned int Actor::AddRenderer( Renderer& renderer ) +{ + //TODO: MESH_REWORK : Add support for multiple renderers + if ( ! mAttachment ) + { + mAttachment = RendererAttachment::New( GetEventThreadServices(), *mNode, renderer ); + if( mIsOnStage ) + { + mAttachment->Connect(); + } + } + + return 0; +} + +unsigned int Actor::GetRendererCount() const +{ + //TODO: MESH_REWORK : Add support for multiple renderers + RendererAttachment* attachment = dynamic_cast(mAttachment.Get()); + return attachment ? 1u : 0u; +} + +Renderer& Actor::GetRendererAt( unsigned int index ) +{ + //TODO: MESH_REWORK : Add support for multiple renderers + DALI_ASSERT_DEBUG( index == 0 && "Only one renderer is supported." ); + + //TODO: MESH_REWORK : Temporary code + RendererAttachment* attachment = dynamic_cast(mAttachment.Get()); + DALI_ASSERT_ALWAYS( attachment && "Actor doesn't have a renderer" ); + + return attachment->GetRenderer(); +} + +void Actor::RemoveRenderer( Renderer& renderer ) +{ + //TODO: MESH_REWORK : Add support for multiple renderers + mAttachment = NULL; +} + +void Actor::RemoveRenderer( unsigned int index ) +{ + //TODO: MESH_REWORK : Add support for multiple renderers + mAttachment = NULL; +} + +void Actor::SetOverlay( bool enable ) +{ + // Setting STENCIL will override OVERLAY_2D + if( DrawMode::STENCIL != mDrawMode ) + { + SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL ); + } +} + +bool Actor::IsOverlay() const +{ + return ( DrawMode::OVERLAY_2D == mDrawMode ); +} + +void Actor::SetDrawMode( DrawMode::Type drawMode ) +{ + // this flag is not animatable so keep the value + mDrawMode = drawMode; + if( NULL != mNode ) + { + // mNode is being used in a separate thread; queue a message to set the value + SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode ); + } +} + +DrawMode::Type Actor::GetDrawMode() const +{ + return mDrawMode; +} + +bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const +{ + // only valid when on-stage + StagePtr stage = Stage::GetCurrent(); + if( stage && OnStage() ) + { + const RenderTaskList& taskList = stage->GetRenderTaskList(); + + Vector2 converted( screenX, screenY ); + + // do a reverse traversal of all lists (as the default onscreen one is typically the last one) + const int taskCount = taskList.GetTaskCount(); + for( int i = taskCount - 1; i >= 0; --i ) + { + Dali::RenderTask task = taskList.GetTask( i ); + if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) ) + { + // found a task where this conversion was ok so return + return true; + } + } + } + return false; +} + +bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const +{ + bool retval = false; + // only valid when on-stage + if( OnStage() ) + { + CameraActor* camera = renderTask.GetCameraActor(); + if( camera ) + { + Viewport viewport; + renderTask.GetViewport( viewport ); + + // need to translate coordinates to render tasks coordinate space + Vector2 converted( screenX, screenY ); + if( renderTask.TranslateCoordinates( converted ) ) + { + retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y ); + } + } + } + return retval; +} + +bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const +{ + // Early-out if mNode is NULL + if( !OnStage() ) + { + return false; + } + + BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() ); + + // Calculate the ModelView matrix + Matrix modelView( false/*don't init*/); + // need to use the components as world matrix is only updated for actors that need it + modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) ); + Matrix::Multiply( modelView, modelView, viewMatrix ); + + // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects + Matrix invertedMvp( false/*don't init*/); + Matrix::Multiply( invertedMvp, modelView, projectionMatrix ); + bool success = invertedMvp.Invert(); + + // Convert to GL coordinates + Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f ); + + Vector4 nearPos; + if( success ) + { + success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos ); + } + + Vector4 farPos; + if( success ) + { + screenPos.z = 1.0f; + success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos ); + } + + if( success ) + { + Vector4 local; + if( XyPlaneIntersect( nearPos, farPos, local ) ) + { + Vector3 size = GetCurrentSize(); + localX = local.x + size.x * 0.5f; + localY = local.y + size.y * 0.5f; + } + else + { + success = false; + } + } + + return success; +} + +bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const +{ + /* + http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection + + Mathematical Formulation + + Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if + + ( p - c ) dot ( p - c ) = r^2 + + Given a ray with a point of origin 'o', and a direction vector 'd': + + ray(t) = o + td, t >= 0 + + we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p' + + (o + td - c ) dot ( o + td - c ) = r^2 + + To solve for t we first expand the above into a more recognisable quadratic equation form + + ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0 + + or + + At2 + Bt + C = 0 + + where + + A = d dot d + B = 2( o - c ) dot d + C = ( o - c ) dot ( o - c ) - r^2 + + which can be solved using a standard quadratic formula. + + Note that in the absence of positive, real, roots, the ray does not intersect the sphere. + + Practical Simplification + + In a renderer, we often differentiate between world space and object space. In the object space + of a sphere it is centred at origin, meaning that if we first transform the ray from world space + into object space, the mathematical solution presented above can be simplified significantly. + + If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if + + p dot p = r^2 + + and we can find the t at which the (transformed) ray intersects the sphere by + + ( o + td ) dot ( o + td ) = r^2 + + According to the reasoning above, we expand the above quadratic equation into the general form + + At2 + Bt + C = 0 + + which now has coefficients: + + A = d dot d + B = 2( d dot o ) + C = o dot o - r^2 + */ + + // Early out if mNode is NULL + if( !mNode ) + { + return false; + } + + BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() ); + + // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed. + const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) ); + Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z ); + + // Compute the radius is not needed, square radius it's enough. + const Vector3& size( mNode->GetSize( bufferIndex ) ); + + // Scale the sphere. + const Vector3& scale( mNode->GetWorldScale( bufferIndex ) ); + + const float width = size.width * scale.width; + const float height = size.height * scale.height; + + float squareSphereRadius = 0.5f * ( width * width + height * height ); + + float a = rayDir.Dot( rayDir ); // a + float b2 = rayDir.Dot( rayOriginLocal ); // b/2 + float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius; // c + + return ( b2 * b2 - a * c ) >= 0.f; +} + +bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const +{ + bool hit = false; + + if( OnStage() && + NULL != mNode ) + { + // Transforms the ray to the local reference system. + // Calculate the inverse of Model matrix + Matrix invModelMatrix( false/*don't init*/); + + BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() ); + // need to use the components as world matrix is only updated for actors that need it + invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) ); + + Vector4 rayOriginLocal( invModelMatrix * rayOrigin ); + Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() ); + + // Test with the actor's XY plane (Normal = 0 0 1 1). + + float a = -rayOriginLocal.z; + float b = rayDirLocal.z; + + if( fabsf( b ) > Math::MACHINE_EPSILON_1 ) + { + // Ray travels distance * rayDirLocal to intersect with plane. + distance = a / b; + + const Vector3& size = mNode->GetSize( bufferIndex ); + + hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f; + hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f; + + // Test with the actor's geometry. + hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y ); + } + } + + return hit; +} + +void Actor::SetLeaveRequired( bool required ) +{ + mLeaveRequired = required; +} + +bool Actor::GetLeaveRequired() const +{ + return mLeaveRequired; +} + +void Actor::SetKeyboardFocusable( bool focusable ) +{ + mKeyboardFocusable = focusable; +} + +bool Actor::IsKeyboardFocusable() const +{ + return mKeyboardFocusable; +} + +bool Actor::GetTouchRequired() const +{ + return !mTouchedSignal.Empty() || mDerivedRequiresTouch; +} + +bool Actor::GetHoverRequired() const +{ + return !mHoveredSignal.Empty() || mDerivedRequiresHover; +} + +bool Actor::GetWheelEventRequired() const +{ + return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent; +} + +bool Actor::IsHittable() const +{ + return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected(); +} + +ActorGestureData& Actor::GetGestureData() +{ + // Likely scenario is that once gesture-data is created for this actor, the actor will require + // that gesture for its entire life-time so no need to destroy it until the actor is destroyed + if( NULL == mGestureData ) + { + mGestureData = new ActorGestureData; + } + return *mGestureData; +} + +bool Actor::IsGestureRequred( Gesture::Type type ) const +{ + return mGestureData && mGestureData->IsGestureRequred( type ); +} + +bool Actor::EmitTouchEventSignal( const TouchEvent& event ) +{ + bool consumed = false; + + if( !mTouchedSignal.Empty() ) + { + Dali::Actor handle( this ); + consumed = mTouchedSignal.Emit( handle, event ); + } + + if( !consumed ) + { + // Notification for derived classes + consumed = OnTouchEvent( event ); + } + + return consumed; +} + +bool Actor::EmitHoverEventSignal( const HoverEvent& event ) +{ + bool consumed = false; + + if( !mHoveredSignal.Empty() ) + { + Dali::Actor handle( this ); + consumed = mHoveredSignal.Emit( handle, event ); + } + + if( !consumed ) + { + // Notification for derived classes + consumed = OnHoverEvent( event ); + } + + return consumed; +} + +bool Actor::EmitWheelEventSignal( const WheelEvent& event ) +{ + bool consumed = false; + + if( !mWheelEventSignal.Empty() ) + { + Dali::Actor handle( this ); + consumed = mWheelEventSignal.Emit( handle, event ); + } + + if( !consumed ) + { + // Notification for derived classes + consumed = OnWheelEvent( event ); + } + + return consumed; +} + +Dali::Actor::TouchSignalType& Actor::TouchedSignal() +{ + return mTouchedSignal; +} + +Dali::Actor::HoverSignalType& Actor::HoveredSignal() +{ + return mHoveredSignal; +} + +Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal() +{ + return mWheelEventSignal; +} + +Dali::Actor::OnStageSignalType& Actor::OnStageSignal() +{ + return mOnStageSignal; +} + +Dali::Actor::OffStageSignalType& Actor::OffStageSignal() +{ + return mOffStageSignal; +} + +Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal() +{ + return mOnRelayoutSignal; +} + +bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) +{ + bool connected( true ); + Actor* actor = dynamic_cast< Actor* >( object ); + + if( 0 == signalName.compare( SIGNAL_TOUCHED ) ) + { + actor->TouchedSignal().Connect( tracker, functor ); + } + else if( 0 == signalName.compare( SIGNAL_HOVERED ) ) + { + actor->HoveredSignal().Connect( tracker, functor ); + } + else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) ) + { + actor->WheelEventSignal().Connect( tracker, functor ); + } + else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) ) + { + actor->OnStageSignal().Connect( tracker, functor ); + } + else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) ) + { + actor->OffStageSignal().Connect( tracker, functor ); + } + else + { + // signalName does not match any signal + connected = false; + } + + return connected; +} + +Actor::Actor( DerivedType derivedType ) +: mParent( NULL ), + mChildren( NULL ), + mNode( NULL ), + mParentOrigin( NULL ), + mAnchorPoint( NULL ), + mRelayoutData( NULL ), + mGestureData( NULL ), + mAttachment(), + mTargetSize( 0.0f, 0.0f, 0.0f ), + mName(), + mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved + mDepth( 0u ), + mIsRoot( ROOT_LAYER == derivedType ), + mIsRenderable( RENDERABLE == derivedType ), + mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ), + mIsOnStage( false ), + mSensitive( true ), + mLeaveRequired( false ), + mKeyboardFocusable( false ), + mDerivedRequiresTouch( false ), + mDerivedRequiresHover( false ), + mDerivedRequiresWheelEvent( false ), + mOnStageSignalled( false ), + mInsideOnSizeSet( false ), + mInheritOrientation( true ), + mInheritScale( true ), + mDrawMode( DrawMode::NORMAL ), + mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ), + mColorMode( Node::DEFAULT_COLOR_MODE ) +{ +} + +void Actor::Initialize() +{ + // Node creation + SceneGraph::Node* node = CreateNode(); + + AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph + mNode = node; // Keep raw-pointer to Node + + OnInitialize(); + + GetEventThreadServices().RegisterObject( this ); +} + +Actor::~Actor() +{ + // Remove mParent pointers from children even if we're destroying core, + // to guard against GetParent() & Unparent() calls from CustomActor destructors. + if( mChildren ) + { + ActorConstIter endIter = mChildren->end(); + for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter ) + { + (*iter)->SetParent( NULL ); + } + } + delete mChildren; + + // Guard to allow handle destruction after Core has been destroyed + if( EventThreadServices::IsCoreRunning() ) + { + if( NULL != mNode ) + { + DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode ); + mNode = NULL; // Node is about to be destroyed + } + + GetEventThreadServices().UnregisterObject( this ); + } + + // Cleanup optional gesture data + delete mGestureData; + + // Cleanup optional parent origin and anchor + delete mParentOrigin; + delete mAnchorPoint; + + // Delete optional relayout data + if( mRelayoutData ) + { + delete mRelayoutData; + } +} + +void Actor::ConnectToStage( unsigned int parentDepth, int index ) +{ + // This container is used instead of walking the Actor hierachy. + // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks. + ActorContainer connectionList; + + + // This stage is atomic i.e. not interrupted by user callbacks + RecursiveConnectToStage( connectionList, parentDepth+1, index ); + + // Notify applications about the newly connected actors. + const ActorIter endIter = connectionList.end(); + for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter ) + { + (*iter)->NotifyStageConnection(); + } + + RelayoutRequest(); +} + +void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index ) +{ + DALI_ASSERT_ALWAYS( !OnStage() ); + + mIsOnStage = true; + mDepth = depth; + + ConnectToSceneGraph( index ); + + // Notification for internal derived classes + OnStageConnectionInternal(); + + // This stage is atomic; avoid emitting callbacks until all Actors are connected + connectionList.push_back( ActorPtr( this ) ); + + // Recursively connect children + if( mChildren ) + { + ActorConstIter endIter = mChildren->end(); + for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter ) + { + (*iter)->RecursiveConnectToStage( connectionList, depth+1 ); + } + } +} + +/** + * This method is called when the Actor is connected to the Stage. + * The parent must have added its Node to the scene-graph. + * The child must connect its Node to the parent's Node. + * This is resursive; the child calls ConnectToStage() for its children. + */ +void Actor::ConnectToSceneGraph( int index ) +{ + DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL ); + + if( NULL != mNode ) + { + // Reparent Node in next Update + ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index ); + } + + // Notify attachment + if( mAttachment ) + { + mAttachment->Connect(); + } + + // Request relayout on all actors that are added to the scenegraph + RelayoutRequest(); + + // Notification for Object::Observers + OnSceneObjectAdd(); +} + +void Actor::NotifyStageConnection() +{ + // Actors can be removed (in a callback), before the on-stage stage is reported. + // The actor may also have been reparented, in which case mOnStageSignalled will be true. + if( OnStage() && !mOnStageSignalled ) + { + // Notification for external (CustomActor) derived classes + OnStageConnectionExternal( mDepth ); + + if( !mOnStageSignal.Empty() ) + { + Dali::Actor handle( this ); + mOnStageSignal.Emit( handle ); + } + + // Guard against Remove during callbacks + if( OnStage() ) + { + mOnStageSignalled = true; // signal required next time Actor is removed + } + } +} + +void Actor::DisconnectFromStage() +{ + // This container is used instead of walking the Actor hierachy. + // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks. + ActorContainer disconnectionList; + + // This stage is atomic i.e. not interrupted by user callbacks + RecursiveDisconnectFromStage( disconnectionList ); + + // Notify applications about the newly disconnected actors. + const ActorIter endIter = disconnectionList.end(); + for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter ) + { + (*iter)->NotifyStageDisconnection(); + } +} + +void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList ) +{ + DALI_ASSERT_ALWAYS( OnStage() ); + + // Recursively disconnect children + if( mChildren ) + { + ActorConstIter endIter = mChildren->end(); + for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter ) + { + (*iter)->RecursiveDisconnectFromStage( disconnectionList ); + } + } + + // This stage is atomic; avoid emitting callbacks until all Actors are disconnected + disconnectionList.push_back( ActorPtr( this ) ); + + // Notification for internal derived classes + OnStageDisconnectionInternal(); + + DisconnectFromSceneGraph(); + + mIsOnStage = false; +} + +/** + * This method is called by an actor or its parent, before a node removal message is sent. + * This is recursive; the child calls DisconnectFromStage() for its children. + */ +void Actor::DisconnectFromSceneGraph() +{ + // Notification for Object::Observers + OnSceneObjectRemove(); + + // Notify attachment + if( mAttachment ) + { + mAttachment->Disconnect(); + } +} + +void Actor::NotifyStageDisconnection() +{ + // Actors can be added (in a callback), before the off-stage state is reported. + // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here. + // only do this step if there is a stage, i.e. Core is not being shut down + if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled ) + { + // Notification for external (CustomeActor) derived classes + OnStageDisconnectionExternal(); + + if( !mOffStageSignal.Empty() ) + { + Dali::Actor handle( this ); + mOffStageSignal.Emit( handle ); + } + + // Guard against Add during callbacks + if( !OnStage() ) + { + mOnStageSignalled = false; // signal required next time Actor is added + } + } +} + +bool Actor::IsNodeConnected() const +{ + bool connected( false ); + + if( OnStage() && ( NULL != mNode ) ) + { + if( IsRoot() || mNode->GetParent() ) + { + connected = true; + } + } + + return connected; +} + +unsigned int Actor::GetDefaultPropertyCount() const +{ + return DEFAULT_PROPERTY_COUNT; +} + +void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const +{ + indices.Reserve( DEFAULT_PROPERTY_COUNT ); + + for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) + { + indices.PushBack( i ); + } +} + +const char* Actor::GetDefaultPropertyName( Property::Index index ) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[ index ].name; + } + + return NULL; +} + +Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const +{ + Property::Index index = Property::INVALID_INDEX; + + // Look for name in default properties + for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) + { + const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ]; + if( 0 == name.compare( property->name ) ) + { + index = i; + break; + } + } + + return index; +} + +bool Actor::IsDefaultPropertyWritable( Property::Index index ) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[ index ].writable; + } + + return false; +} + +bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[ index ].animatable; + } + + return false; +} + +bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput; + } + + return false; +} + +Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[ index ].type; + } + + // index out of range...return Property::NONE + return Property::NONE; +} + +void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property ) +{ + switch( index ) + { + case Dali::Actor::Property::PARENT_ORIGIN: + { + SetParentOrigin( property.Get< Vector3 >() ); + break; + } + + case Dali::Actor::Property::PARENT_ORIGIN_X: + { + SetParentOriginX( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::PARENT_ORIGIN_Y: + { + SetParentOriginY( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::PARENT_ORIGIN_Z: + { + SetParentOriginZ( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::ANCHOR_POINT: + { + SetAnchorPoint( property.Get< Vector3 >() ); + break; + } + + case Dali::Actor::Property::ANCHOR_POINT_X: + { + SetAnchorPointX( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::ANCHOR_POINT_Y: + { + SetAnchorPointY( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::ANCHOR_POINT_Z: + { + SetAnchorPointZ( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::SIZE: + { + SetSize( property.Get< Vector3 >() ); + break; + } + + case Dali::Actor::Property::SIZE_WIDTH: + { + SetWidth( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::SIZE_HEIGHT: + { + SetHeight( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::SIZE_DEPTH: + { + SetDepth( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::POSITION: + { + SetPosition( property.Get< Vector3 >() ); + break; + } + + case Dali::Actor::Property::POSITION_X: + { + SetX( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::POSITION_Y: + { + SetY( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::POSITION_Z: + { + SetZ( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::ORIENTATION: + { + SetOrientation( property.Get< Quaternion >() ); + break; + } + + case Dali::Actor::Property::SCALE: + { + SetScale( property.Get< Vector3 >() ); + break; + } + + case Dali::Actor::Property::SCALE_X: + { + SetScaleX( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::SCALE_Y: + { + SetScaleY( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::SCALE_Z: + { + SetScaleZ( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::VISIBLE: + { + SetVisible( property.Get< bool >() ); + break; + } + + case Dali::Actor::Property::COLOR: + { + SetColor( property.Get< Vector4 >() ); + break; + } + + case Dali::Actor::Property::COLOR_RED: + { + SetColorRed( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::COLOR_GREEN: + { + SetColorGreen( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::COLOR_BLUE: + { + SetColorBlue( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::COLOR_ALPHA: + { + SetOpacity( property.Get< float >() ); + break; + } + + case Dali::Actor::Property::NAME: + { + SetName( property.Get< std::string >() ); + break; + } + + case Dali::Actor::Property::SENSITIVE: + { + SetSensitive( property.Get< bool >() ); + break; + } + + case Dali::Actor::Property::LEAVE_REQUIRED: + { + SetLeaveRequired( property.Get< bool >() ); + break; + } + + case Dali::Actor::Property::INHERIT_ORIENTATION: + { + SetInheritOrientation( property.Get< bool >() ); + break; + } + + case Dali::Actor::Property::INHERIT_SCALE: + { + SetInheritScale( property.Get< bool >() ); + break; + } + + case Dali::Actor::Property::COLOR_MODE: + { + SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) ); + break; + } + + case Dali::Actor::Property::POSITION_INHERITANCE: + { + SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) ); + break; + } + + case Dali::Actor::Property::DRAW_MODE: + { + SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) ); + break; + } + + case Dali::Actor::Property::SIZE_MODE_FACTOR: + { + SetSizeModeFactor( property.Get< Vector3 >() ); + break; + } + + case Dali::Actor::Property::WIDTH_RESIZE_POLICY: + { + ResizePolicy::Type type; + if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) ) + { + SetResizePolicy( type, Dimension::WIDTH ); + } + break; + } + + case Dali::Actor::Property::HEIGHT_RESIZE_POLICY: + { + ResizePolicy::Type type; + if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) ) + { + SetResizePolicy( type, Dimension::HEIGHT ); + } + break; + } + + case Dali::Actor::Property::SIZE_SCALE_POLICY: + { + SizeScalePolicy::Type type; + if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) ) + { + SetSizeScalePolicy( type ); + } + break; + } + + case Dali::Actor::Property::WIDTH_FOR_HEIGHT: + { + if( property.Get< bool >() ) + { + SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH ); + } + break; + } + + case Dali::Actor::Property::HEIGHT_FOR_WIDTH: + { + if( property.Get< bool >() ) + { + SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT ); + } + break; + } + + case Dali::Actor::Property::PADDING: + { + Vector4 padding = property.Get< Vector4 >(); + SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH ); + SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT ); + break; + } + + case Dali::Actor::Property::MINIMUM_SIZE: + { + Vector2 size = property.Get< Vector2 >(); + SetMinimumSize( size.x, Dimension::WIDTH ); + SetMinimumSize( size.y, Dimension::HEIGHT ); + break; + } + + case Dali::Actor::Property::MAXIMUM_SIZE: + { + Vector2 size = property.Get< Vector2 >(); + SetMaximumSize( size.x, Dimension::WIDTH ); + SetMaximumSize( size.y, Dimension::HEIGHT ); + break; + } + + default: + { + // this can happen in the case of a non-animatable default property so just do nothing + break; + } + } +} + +// TODO: This method needs to be removed +void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value ) +{ + switch( entry.type ) + { + case Property::BOOLEAN: + { + const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + // property is being used in a separate thread; queue a message to set the property + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::Bake, value.Get() ); + + break; + } + + case Property::INTEGER: + { + const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + // property is being used in a separate thread; queue a message to set the property + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::Bake, value.Get() ); + + break; + } + + case Property::FLOAT: + { + const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + // property is being used in a separate thread; queue a message to set the property + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::Bake, value.Get() ); + + break; + } + + case Property::VECTOR2: + { + const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + // property is being used in a separate thread; queue a message to set the property + if(entry.componentIndex == 0) + { + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeX, value.Get() ); + } + else if(entry.componentIndex == 1) + { + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeY, value.Get() ); + } + else + { + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::Bake, value.Get() ); + } + + break; + } + + case Property::VECTOR3: + { + const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + // property is being used in a separate thread; queue a message to set the property + if(entry.componentIndex == 0) + { + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeX, value.Get() ); + } + else if(entry.componentIndex == 1) + { + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeY, value.Get() ); + } + else if(entry.componentIndex == 2) + { + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeZ, value.Get() ); + } + else + { + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::Bake, value.Get() ); + } + + break; + } + + case Property::VECTOR4: + { + const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + // property is being used in a separate thread; queue a message to set the property + if(entry.componentIndex == 0) + { + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeX, value.Get() ); + } + else if(entry.componentIndex == 1) + { + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeY, value.Get() ); + } + else if(entry.componentIndex == 2) + { + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeZ, value.Get() ); + } + else if(entry.componentIndex == 3) + { + SceneGraph::NodePropertyComponentMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::BakeW, value.Get() ); + } + else + { + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty::Bake, value.Get() ); + } + + break; + } + + case Property::ROTATION: + { + const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + // property is being used in a separate thread; queue a message to set the property + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty::Bake, value.Get() ); + + break; + } + + case Property::MATRIX: + { + const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + // property is being used in a separate thread; queue a message to set the property + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty::Bake, value.Get() ); + + break; + } + + case Property::MATRIX3: + { + const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() ); + DALI_ASSERT_DEBUG( NULL != property ); + + // property is being used in a separate thread; queue a message to set the property + SceneGraph::NodePropertyMessage::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty::Bake, value.Get() ); + + break; + } + + default: + { + DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here + break; + } + } +} + +Property::Value Actor::GetDefaultProperty( Property::Index index ) const +{ + Property::Value value; + + switch( index ) + { + case Dali::Actor::Property::PARENT_ORIGIN: + { + value = GetCurrentParentOrigin(); + break; + } + + case Dali::Actor::Property::PARENT_ORIGIN_X: + { + value = GetCurrentParentOrigin().x; + break; + } + + case Dali::Actor::Property::PARENT_ORIGIN_Y: + { + value = GetCurrentParentOrigin().y; + break; + } + + case Dali::Actor::Property::PARENT_ORIGIN_Z: + { + value = GetCurrentParentOrigin().z; + break; + } + + case Dali::Actor::Property::ANCHOR_POINT: + { + value = GetCurrentAnchorPoint(); + break; + } + + case Dali::Actor::Property::ANCHOR_POINT_X: + { + value = GetCurrentAnchorPoint().x; + break; + } + + case Dali::Actor::Property::ANCHOR_POINT_Y: + { + value = GetCurrentAnchorPoint().y; + break; + } + + case Dali::Actor::Property::ANCHOR_POINT_Z: + { + value = GetCurrentAnchorPoint().z; + break; + } + + case Dali::Actor::Property::SIZE: + { + value = GetCurrentSize(); + break; + } + + case Dali::Actor::Property::SIZE_WIDTH: + { + value = GetCurrentSize().width; + break; + } + + case Dali::Actor::Property::SIZE_HEIGHT: + { + value = GetCurrentSize().height; + break; + } + + case Dali::Actor::Property::SIZE_DEPTH: + { + value = GetCurrentSize().depth; + break; + } + + case Dali::Actor::Property::POSITION: + { + value = GetCurrentPosition(); + break; + } + + case Dali::Actor::Property::POSITION_X: + { + value = GetCurrentPosition().x; + break; + } + + case Dali::Actor::Property::POSITION_Y: + { + value = GetCurrentPosition().y; + break; + } + + case Dali::Actor::Property::POSITION_Z: + { + value = GetCurrentPosition().z; + break; + } + + case Dali::Actor::Property::WORLD_POSITION: + { + value = GetCurrentWorldPosition(); + break; + } + + case Dali::Actor::Property::WORLD_POSITION_X: + { + value = GetCurrentWorldPosition().x; + break; + } + + case Dali::Actor::Property::WORLD_POSITION_Y: + { + value = GetCurrentWorldPosition().y; + break; + } + + case Dali::Actor::Property::WORLD_POSITION_Z: + { + value = GetCurrentWorldPosition().z; + break; + } + + case Dali::Actor::Property::ORIENTATION: + { + value = GetCurrentOrientation(); + break; + } + + case Dali::Actor::Property::WORLD_ORIENTATION: + { + value = GetCurrentWorldOrientation(); + break; + } + + case Dali::Actor::Property::SCALE: + { + value = GetCurrentScale(); + break; + } + + case Dali::Actor::Property::SCALE_X: + { + value = GetCurrentScale().x; + break; + } + + case Dali::Actor::Property::SCALE_Y: + { + value = GetCurrentScale().y; + break; + } + + case Dali::Actor::Property::SCALE_Z: + { + value = GetCurrentScale().z; + break; + } + + case Dali::Actor::Property::WORLD_SCALE: + { + value = GetCurrentWorldScale(); + break; + } + + case Dali::Actor::Property::VISIBLE: + { + value = IsVisible(); + break; + } + + case Dali::Actor::Property::COLOR: + { + value = GetCurrentColor(); + break; + } + + case Dali::Actor::Property::COLOR_RED: + { + value = GetCurrentColor().r; + break; + } + + case Dali::Actor::Property::COLOR_GREEN: + { + value = GetCurrentColor().g; + break; + } + + case Dali::Actor::Property::COLOR_BLUE: + { + value = GetCurrentColor().b; + break; + } + + case Dali::Actor::Property::COLOR_ALPHA: + { + value = GetCurrentColor().a; + break; + } + + case Dali::Actor::Property::WORLD_COLOR: + { + value = GetCurrentWorldColor(); + break; + } + + case Dali::Actor::Property::WORLD_MATRIX: + { + value = GetCurrentWorldMatrix(); + break; + } + + case Dali::Actor::Property::NAME: + { + value = GetName(); + break; + } + + case Dali::Actor::Property::SENSITIVE: + { + value = IsSensitive(); + break; + } + + case Dali::Actor::Property::LEAVE_REQUIRED: + { + value = GetLeaveRequired(); + break; + } + + case Dali::Actor::Property::INHERIT_ORIENTATION: + { + value = IsOrientationInherited(); + break; + } + + case Dali::Actor::Property::INHERIT_SCALE: + { + value = IsScaleInherited(); + break; + } + + case Dali::Actor::Property::COLOR_MODE: + { + value = Scripting::GetColorMode( GetColorMode() ); + break; + } + + case Dali::Actor::Property::POSITION_INHERITANCE: + { + value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() ); + break; + } + + case Dali::Actor::Property::DRAW_MODE: + { + value = Scripting::GetDrawMode( GetDrawMode() ); + break; + } + + case Dali::Actor::Property::SIZE_MODE_FACTOR: + { + value = GetSizeModeFactor(); + break; + } + + case Dali::Actor::Property::WIDTH_RESIZE_POLICY: + { + value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ); + break; + } + + case Dali::Actor::Property::HEIGHT_RESIZE_POLICY: + { + value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount ); + break; + } + + case Dali::Actor::Property::SIZE_SCALE_POLICY: + { + value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount ); + break; + } + + case Dali::Actor::Property::WIDTH_FOR_HEIGHT: + { + value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT ); + break; + } + + case Dali::Actor::Property::HEIGHT_FOR_WIDTH: + { + value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH ); + break; + } + + case Dali::Actor::Property::PADDING: + { + Vector2 widthPadding = GetPadding( Dimension::WIDTH ); + Vector2 heightPadding = GetPadding( Dimension::HEIGHT ); + value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y ); + break; + } + + case Dali::Actor::Property::MINIMUM_SIZE: + { + value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) ); + break; + } + + case Dali::Actor::Property::MAXIMUM_SIZE: + { + value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) ); + break; + } + + default: + { + DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here + break; + } + } + + return value; +} + +const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const +{ + return mNode; +} + +const SceneGraph::PropertyOwner* Actor::GetSceneObject() const +{ + // This method should only return an object connected to the scene-graph + return OnStage() ? mNode : NULL; +} + +const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const +{ + DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" ); + + const PropertyBase* property( NULL ); + + // This method should only return a property of an object connected to the scene-graph + if( !OnStage() ) + { + return property; + } + + if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) + { + AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index ); + DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" ); + + property = animatable->GetSceneGraphProperty(); + } + else if ( index >= DEFAULT_PROPERTY_MAX_COUNT ) + { + CustomPropertyMetadata* custom = FindCustomProperty( index ); + DALI_ASSERT_ALWAYS( custom && "Property index is invalid" ); + + property = custom->GetSceneGraphProperty(); + } + else if( NULL != mNode ) + { + switch( index ) + { + case Dali::Actor::Property::SIZE: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::SIZE_WIDTH: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::SIZE_HEIGHT: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::SIZE_DEPTH: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::POSITION: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::POSITION_X: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::POSITION_Y: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::POSITION_Z: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::ORIENTATION: + property = &mNode->mOrientation; + break; + + case Dali::Actor::Property::SCALE: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::SCALE_X: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::SCALE_Y: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::SCALE_Z: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::VISIBLE: + property = &mNode->mVisible; + break; + + case Dali::Actor::Property::COLOR: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_RED: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_GREEN: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_BLUE: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_ALPHA: + property = &mNode->mColor; + break; + + default: + break; + } + } + + return property; +} + +const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const +{ + const PropertyInputImpl* property( NULL ); + + // This method should only return a property of an object connected to the scene-graph + if( !OnStage() ) + { + return property; + } + + if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) + { + AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index ); + DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" ); + + property = animatable->GetSceneGraphProperty(); + } + else if ( index >= DEFAULT_PROPERTY_MAX_COUNT ) + { + CustomPropertyMetadata* custom = FindCustomProperty( index ); + DALI_ASSERT_ALWAYS( custom && "Property index is invalid" ); + property = custom->GetSceneGraphProperty(); + } + else if( NULL != mNode ) + { + switch( index ) + { + case Dali::Actor::Property::PARENT_ORIGIN: + property = &mNode->mParentOrigin; + break; + + case Dali::Actor::Property::PARENT_ORIGIN_X: + property = &mNode->mParentOrigin; + break; + + case Dali::Actor::Property::PARENT_ORIGIN_Y: + property = &mNode->mParentOrigin; + break; + + case Dali::Actor::Property::PARENT_ORIGIN_Z: + property = &mNode->mParentOrigin; + break; + + case Dali::Actor::Property::ANCHOR_POINT: + property = &mNode->mAnchorPoint; + break; + + case Dali::Actor::Property::ANCHOR_POINT_X: + property = &mNode->mAnchorPoint; + break; + + case Dali::Actor::Property::ANCHOR_POINT_Y: + property = &mNode->mAnchorPoint; + break; + + case Dali::Actor::Property::ANCHOR_POINT_Z: + property = &mNode->mAnchorPoint; + break; + + case Dali::Actor::Property::SIZE: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::SIZE_WIDTH: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::SIZE_HEIGHT: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::SIZE_DEPTH: + property = &mNode->mSize; + break; + + case Dali::Actor::Property::POSITION: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::POSITION_X: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::POSITION_Y: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::POSITION_Z: + property = &mNode->mPosition; + break; + + case Dali::Actor::Property::WORLD_POSITION: + property = &mNode->mWorldPosition; + break; + + case Dali::Actor::Property::WORLD_POSITION_X: + property = &mNode->mWorldPosition; + break; + + case Dali::Actor::Property::WORLD_POSITION_Y: + property = &mNode->mWorldPosition; + break; + + case Dali::Actor::Property::WORLD_POSITION_Z: + property = &mNode->mWorldPosition; + break; + + case Dali::Actor::Property::ORIENTATION: + property = &mNode->mOrientation; + break; + + case Dali::Actor::Property::WORLD_ORIENTATION: + property = &mNode->mWorldOrientation; + break; + + case Dali::Actor::Property::SCALE: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::SCALE_X: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::SCALE_Y: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::SCALE_Z: + property = &mNode->mScale; + break; + + case Dali::Actor::Property::WORLD_SCALE: + property = &mNode->mWorldScale; + break; + + case Dali::Actor::Property::VISIBLE: + property = &mNode->mVisible; + break; + + case Dali::Actor::Property::COLOR: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_RED: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_GREEN: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_BLUE: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::COLOR_ALPHA: + property = &mNode->mColor; + break; + + case Dali::Actor::Property::WORLD_COLOR: + property = &mNode->mWorldColor; + break; + + case Dali::Actor::Property::WORLD_MATRIX: + property = &mNode->mWorldMatrix; + break; + + default: + break; + } + } + + return property; +} + +int Actor::GetPropertyComponentIndex( Property::Index index ) const +{ + int componentIndex( Property::INVALID_COMPONENT_INDEX ); + + if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) + { + // check whether the animatable property is registered already, if not then register one. + AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index); + if( animatableProperty ) + { + componentIndex = animatableProperty->componentIndex; + } + } + else + { + switch( index ) + { + case Dali::Actor::Property::PARENT_ORIGIN_X: + case Dali::Actor::Property::ANCHOR_POINT_X: + case Dali::Actor::Property::SIZE_WIDTH: + case Dali::Actor::Property::POSITION_X: + case Dali::Actor::Property::WORLD_POSITION_X: + case Dali::Actor::Property::SCALE_X: + case Dali::Actor::Property::COLOR_RED: + { + componentIndex = 0; + break; + } + + case Dali::Actor::Property::PARENT_ORIGIN_Y: + case Dali::Actor::Property::ANCHOR_POINT_Y: + case Dali::Actor::Property::SIZE_HEIGHT: + case Dali::Actor::Property::POSITION_Y: + case Dali::Actor::Property::WORLD_POSITION_Y: + case Dali::Actor::Property::SCALE_Y: + case Dali::Actor::Property::COLOR_GREEN: + { + componentIndex = 1; + break; + } + + case Dali::Actor::Property::PARENT_ORIGIN_Z: + case Dali::Actor::Property::ANCHOR_POINT_Z: + case Dali::Actor::Property::SIZE_DEPTH: + case Dali::Actor::Property::POSITION_Z: + case Dali::Actor::Property::WORLD_POSITION_Z: + case Dali::Actor::Property::SCALE_Z: + case Dali::Actor::Property::COLOR_BLUE: + { + componentIndex = 2; + break; + } + + case Dali::Actor::Property::COLOR_ALPHA: + { + componentIndex = 3; + break; + } + + default: + { + // Do nothing + break; + } + } + } + + return componentIndex; +} + +void Actor::SetParent( Actor* parent, int index ) +{ + if( parent ) + { + DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" ); + + mParent = parent; + + if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction + parent->OnStage() ) + { + // Instruct each actor to create a corresponding node in the scene graph + ConnectToStage( parent->GetHierarchyDepth(), index ); + } + } + else // parent being set to NULL + { + DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" ); + + mParent = NULL; + + if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction + OnStage() ) + { + DALI_ASSERT_ALWAYS( mNode != NULL ); + + if( NULL != mNode ) + { + // Disconnect the Node & its children from the scene-graph. + DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode ); + } + + // Instruct each actor to discard pointers to the scene-graph + DisconnectFromStage(); + } + } +} + +SceneGraph::Node* Actor::CreateNode() const +{ + return Node::New(); +} + +bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ ) +{ + bool done = false; + Actor* actor = dynamic_cast< Actor* >( object ); + + if( actor ) + { + if( 0 == actionName.compare( ACTION_SHOW ) ) + { + actor->SetVisible( true ); + done = true; + } + else if( 0 == actionName.compare( ACTION_HIDE ) ) + { + actor->SetVisible( false ); + done = true; + } + } + + return done; +} + +void Actor::EnsureRelayoutData() +{ + // Assign relayout data. + if( !mRelayoutData ) + { + mRelayoutData = new RelayoutData(); + } +} + +bool Actor::RelayoutDependentOnParent( Dimension::Type dimension ) +{ + // Check if actor is dependent on parent + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( ( dimension & ( 1 << i ) ) ) + { + const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) ); + if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT ) + { + return true; + } + } + } + + return false; +} + +bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension ) +{ + // Check if actor is dependent on children + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( ( dimension & ( 1 << i ) ) ) + { + const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) ); + switch( resizePolicy ) + { + case ResizePolicy::FIT_TO_CHILDREN: + case ResizePolicy::USE_NATURAL_SIZE: // i.e. For things that calculate their size based on children + { + return true; + } + + default: + { + break; + } + } + } + } + + return false; +} + +bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension ) +{ + return Actor::RelayoutDependentOnChildren( dimension ); +} + +bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension ) +{ + // Check each possible dimension and see if it is dependent on the input one + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension; + } + } + + return false; +} + +void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension ) +{ + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension; + } + } +} + +float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const +{ + // If more than one dimension is requested, just return the first one found + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( ( dimension & ( 1 << i ) ) ) + { + return mRelayoutData->negotiatedDimensions[ i ]; + } + } + + return 0.0f; // Default +} + +void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension ) +{ + EnsureRelayoutData(); + + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + mRelayoutData->dimensionPadding[ i ] = padding; + } + } +} + +Vector2 Actor::GetPadding( Dimension::Type dimension ) const +{ + if ( mRelayoutData ) + { + // If more than one dimension is requested, just return the first one found + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( ( dimension & ( 1 << i ) ) ) + { + return mRelayoutData->dimensionPadding[ i ]; + } + } + } + + return GetDefaultDimensionPadding(); +} + +void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension ) +{ + EnsureRelayoutData(); + + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + mRelayoutData->dimensionNegotiated[ i ] = negotiated; + } + } +} + +bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const +{ + if ( mRelayoutData ) + { + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] ) + { + return true; + } + } + } + + return false; +} + +float Actor::GetHeightForWidthBase( float width ) +{ + float height = 0.0f; + + const Vector3 naturalSize = GetNaturalSize(); + if( naturalSize.width > 0.0f ) + { + height = naturalSize.height * width / naturalSize.width; + } + else // we treat 0 as 1:1 aspect ratio + { + height = width; + } + + return height; +} + +float Actor::GetWidthForHeightBase( float height ) +{ + float width = 0.0f; + + const Vector3 naturalSize = GetNaturalSize(); + if( naturalSize.height > 0.0f ) + { + width = naturalSize.width * height / naturalSize.height; + } + else // we treat 0 as 1:1 aspect ratio + { + width = height; + } + + return width; +} + +float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension ) +{ + // Fill to parent, taking size mode factor into account + switch( child.GetResizePolicy( dimension ) ) + { + case ResizePolicy::FILL_TO_PARENT: + { + return GetLatestSize( dimension ); + } + + case ResizePolicy::SIZE_RELATIVE_TO_PARENT: + { + return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension ); + } + + case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT: + { + return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension ); + } + + default: + { + return GetLatestSize( dimension ); + } + } +} + +float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension ) +{ + // Can be overridden in derived class + return CalculateChildSizeBase( child, dimension ); +} + +float Actor::GetHeightForWidth( float width ) +{ + // Can be overridden in derived class + return GetHeightForWidthBase( width ); +} + +float Actor::GetWidthForHeight( float height ) +{ + // Can be overridden in derived class + return GetWidthForHeightBase( height ); +} + +float Actor::GetLatestSize( Dimension::Type dimension ) const +{ + return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension ); +} + +float Actor::GetRelayoutSize( Dimension::Type dimension ) const +{ + Vector2 padding = GetPadding( dimension ); + + return GetLatestSize( dimension ) + padding.x + padding.y; +} + +float Actor::NegotiateFromParent( Dimension::Type dimension ) +{ + Actor* parent = GetParent(); + if( parent ) + { + Vector2 padding( GetPadding( dimension ) ); + Vector2 parentPadding( parent->GetPadding( dimension ) ); + return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y; + } + + return 0.0f; +} + +float Actor::NegotiateFromChildren( Dimension::Type dimension ) +{ + float maxDimensionPoint = 0.0f; + + for( unsigned int i = 0, count = GetChildCount(); i < count; ++i ) + { + ActorPtr child = GetChildAt( i ); + + if( !child->RelayoutDependentOnParent( dimension ) ) + { + // Calculate the min and max points that the children range across + float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension ); + float dimensionSize = child->GetRelayoutSize( dimension ); + maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize ); + } + } + + return maxDimensionPoint; +} + +float Actor::GetSize( Dimension::Type dimension ) const +{ + return GetDimensionValue( GetTargetSize(), dimension ); +} + +float Actor::GetNaturalSize( Dimension::Type dimension ) const +{ + return GetDimensionValue( GetNaturalSize(), dimension ); +} + +float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize ) +{ + switch( GetResizePolicy( dimension ) ) + { + case ResizePolicy::USE_NATURAL_SIZE: + { + return GetNaturalSize( dimension ); + } + + case ResizePolicy::FIXED: + { + return GetDimensionValue( GetPreferredSize(), dimension ); + } + + case ResizePolicy::USE_ASSIGNED_SIZE: + { + return GetDimensionValue( maximumSize, dimension ); + } + + case ResizePolicy::FILL_TO_PARENT: + case ResizePolicy::SIZE_RELATIVE_TO_PARENT: + case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT: + { + return NegotiateFromParent( dimension ); + } + + case ResizePolicy::FIT_TO_CHILDREN: + { + return NegotiateFromChildren( dimension ); + } + + case ResizePolicy::DIMENSION_DEPENDENCY: + { + const Dimension::Type dimensionDependency = GetDimensionDependency( dimension ); + + // Custom rules + if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT ) + { + return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) ); + } + + if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH ) + { + return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) ); + } + + break; + } + + default: + { + break; + } + } + + return 0.0f; // Default +} + +float Actor::ClampDimension( float size, Dimension::Type dimension ) +{ + const float minSize = GetMinimumSize( dimension ); + const float maxSize = GetMaximumSize( dimension ); + + return std::max( minSize, std::min( size, maxSize ) ); +} + +void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack ) +{ + // Check if it needs to be negotiated + if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) ) + { + // Check that we havn't gotten into an infinite loop + ActorDimensionPair searchActor = ActorDimensionPair( this, dimension ); + bool recursionFound = false; + for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it ) + { + if( *it == searchActor ) + { + recursionFound = true; + break; + } + } + + if( !recursionFound ) + { + // Record the path that we have taken + recursionStack.push_back( ActorDimensionPair( this, dimension ) ); + + // Dimension dependency check + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i ); + + if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) ) + { + NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack ); + } + } + + // Parent dependency check + Actor* parent = GetParent(); + if( parent && RelayoutDependentOnParent( dimension ) ) + { + parent->NegotiateDimension( dimension, allocatedSize, recursionStack ); + } + + // Children dependency check + if( RelayoutDependentOnChildren( dimension ) ) + { + for( unsigned int i = 0, count = GetChildCount(); i < count; ++i ) + { + ActorPtr child = GetChildAt( i ); + + // Only relayout child first if it is not dependent on this actor + if( !child->RelayoutDependentOnParent( dimension ) ) + { + child->NegotiateDimension( dimension, allocatedSize, recursionStack ); + } + } + } + + // For deriving classes + OnCalculateRelayoutSize( dimension ); + + // All dependencies checked, calculate the size and set negotiated flag + const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension ); + + SetNegotiatedDimension( newSize, dimension ); + SetLayoutNegotiated( true, dimension ); + + // For deriving classes + OnLayoutNegotiated( newSize, dimension ); + + // This actor has been successfully processed, pop it off the recursion stack + recursionStack.pop_back(); + } + else + { + // TODO: Break infinite loop + SetLayoutNegotiated( true, dimension ); + } + } +} + +void Actor::NegotiateDimensions( const Vector2& allocatedSize ) +{ + // Negotiate all dimensions that require it + ActorDimensionStack recursionStack; + + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i ); + + // Negotiate + NegotiateDimension( dimension, allocatedSize, recursionStack ); + } +} + +Vector2 Actor::ApplySizeSetPolicy( const Vector2 size ) +{ + switch( mRelayoutData->sizeSetPolicy ) + { + case SizeScalePolicy::USE_SIZE_SET: + { + return size; + } + + case SizeScalePolicy::FIT_WITH_ASPECT_RATIO: + { + // Scale size to fit within the original size bounds, keeping the natural size aspect ratio + const Vector3 naturalSize = GetNaturalSize(); + if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f ) + { + const float sizeRatio = size.width / size.height; + const float naturalSizeRatio = naturalSize.width / naturalSize.height; + + if( naturalSizeRatio < sizeRatio ) + { + return Vector2( naturalSizeRatio * size.height, size.height ); + } + else if( naturalSizeRatio > sizeRatio ) + { + return Vector2( size.width, size.width / naturalSizeRatio ); + } + else + { + return size; + } + } + + break; + } + + case SizeScalePolicy::FILL_WITH_ASPECT_RATIO: + { + // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds. + const Vector3 naturalSize = GetNaturalSize(); + if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f ) + { + const float sizeRatio = size.width / size.height; + const float naturalSizeRatio = naturalSize.width / naturalSize.height; + + if( naturalSizeRatio < sizeRatio ) + { + return Vector2( size.width, size.width / naturalSizeRatio ); + } + else if( naturalSizeRatio > sizeRatio ) + { + return Vector2( naturalSizeRatio * size.height, size.height ); + } + else + { + return size; + } + } + } + + default: + { + break; + } + } + + return size; +} + +void Actor::SetNegotiatedSize( RelayoutContainer& container ) +{ + // Do the set actor size + Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) ); + + // Adjust for size set policy + negotiatedSize = ApplySizeSetPolicy( negotiatedSize ); + + // Lock the flag to stop recursive relayouts on set size + mRelayoutData->insideRelayout = true; + SetSize( negotiatedSize ); + mRelayoutData->insideRelayout = false; + + // Clear flags for all dimensions + SetLayoutDirty( false ); + + // Give deriving classes a chance to respond + OnRelayout( negotiatedSize, container ); + + if( !mOnRelayoutSignal.Empty() ) + { + Dali::Actor handle( this ); + mOnRelayoutSignal.Emit( handle ); + } +} + +void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container ) +{ + // Do the negotiation + NegotiateDimensions( allocatedSize ); + + // Set the actor size + SetNegotiatedSize( container ); + + // Negotiate down to children + const Vector2 newBounds = GetTargetSize().GetVectorXY(); + + for( unsigned int i = 0, count = GetChildCount(); i < count; ++i ) + { + ActorPtr child = GetChildAt( i ); + + // Only relayout if required + if( child->RelayoutRequired() ) + { + container.Add( Dali::Actor( child.Get() ), newBounds ); + } + } +} + +void Actor::RelayoutRequest( Dimension::Type dimension ) +{ + Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get(); + if( relayoutController ) + { + Dali::Actor self( this ); + relayoutController->RequestRelayout( self, dimension ); + } +} + +void Actor::OnCalculateRelayoutSize( Dimension::Type dimension ) +{ +} + +void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension ) +{ +} + +void Actor::SetPreferredSize( const Vector2& size ) +{ + EnsureRelayoutData(); + + if( size.width > 0.0f ) + { + SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH ); + } + + if( size.height > 0.0f ) + { + SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT ); + } + + mRelayoutData->preferredSize = size; + + RelayoutRequest(); +} + +Vector2 Actor::GetPreferredSize() const +{ + if ( mRelayoutData ) + { + return mRelayoutData->preferredSize; + } + + return GetDefaultPreferredSize(); +} + +void Actor::SetMinimumSize( float size, Dimension::Type dimension ) +{ + EnsureRelayoutData(); + + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + mRelayoutData->minimumSize[ i ] = size; + } + } + + RelayoutRequest(); +} + +float Actor::GetMinimumSize( Dimension::Type dimension ) const +{ + if ( mRelayoutData ) + { + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + return mRelayoutData->minimumSize[ i ]; + } + } + } + + return 0.0f; // Default +} + +void Actor::SetMaximumSize( float size, Dimension::Type dimension ) +{ + EnsureRelayoutData(); + + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + mRelayoutData->maximumSize[ i ] = size; + } + } + + RelayoutRequest(); +} + +float Actor::GetMaximumSize( Dimension::Type dimension ) const +{ + if ( mRelayoutData ) + { + for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i ) + { + if( dimension & ( 1 << i ) ) + { + return mRelayoutData->maximumSize[ i ]; + } + } + } + + return FLT_MAX; // Default +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/actors/actor-impl.h b/dali/internal/event/actors/actor-impl.h new file mode 100644 index 0000000..9a5e971 --- /dev/null +++ b/dali/internal/event/actors/actor-impl.h @@ -0,0 +1,1856 @@ +#ifndef __DALI_INTERNAL_ACTOR_H__ +#define __DALI_INTERNAL_ACTOR_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// EXTERNAL INCLUDES +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +struct KeyEvent; +struct TouchEvent; +struct HoverEvent; +struct WheelEvent; + +namespace Internal +{ + +class Actor; +class ActorGestureData; +class Animation; +class RenderTask; +class Renderer; + +typedef std::vector< ActorPtr > ActorContainer; +typedef ActorContainer::iterator ActorIter; +typedef ActorContainer::const_iterator ActorConstIter; + +/** + * Actor is the primary object which Dali applications interact with. + * UI controls can be built by combining multiple actors. + * Multi-Touch events are received through signals emitted by the actor tree. + * + * An Actor is a proxy for a Node in the scene graph. + * When an Actor is added to the Stage, it creates a node and attaches it to the scene graph. + * The scene-graph can be updated in a separate thread, so the attachment is done using an asynchronous message. + * When a tree of Actors is detached from the Stage, a message is sent to destroy the associated nodes. + */ +class Actor : public Object +{ +public: + + /** + * @brief Struct to hold an actor and a dimension + */ + struct ActorDimensionPair + { + /** + * @brief Constructor + * + * @param[in] newActor The actor to assign + * @param[in] newDimension The dimension to assign + */ + ActorDimensionPair( Actor* newActor, Dimension::Type newDimension ) + : actor( newActor ), + dimension( newDimension ) + { + } + + /** + * @brief Equality operator + * + * @param[in] lhs The left hand side argument + * @param[in] rhs The right hand side argument + */ + bool operator== ( const ActorDimensionPair& rhs ) + { + return ( actor == rhs.actor ) && ( dimension == rhs.dimension ); + } + + Actor* actor; ///< The actor to hold + Dimension::Type dimension; ///< The dimension to hold + }; + + typedef std::vector< ActorDimensionPair > ActorDimensionStack; + +public: + + /** + * Create a new actor. + * @return A smart-pointer to the newly allocated Actor. + */ + static ActorPtr New(); + + /** + * Retrieve the name of the actor. + * @return The name. + */ + const std::string& GetName() const; + + /** + * Set the name of the actor. + * @param[in] name The new name. + */ + void SetName( const std::string& name ); + + /** + * @copydoc Dali::Actor::GetId + */ + unsigned int GetId() const; + + // Attachments + + /** + * Attach an object to an actor. + * @pre The actor does not already have an attachment. + * @param[in] attachment The object to attach. + */ + void Attach( ActorAttachment& attachment ); + + /** + * Retreive the object attached to an actor. + * @return The attachment. + */ + ActorAttachmentPtr GetAttachment(); + + // Containment + + /** + * Query whether an actor is the root actor, which is owned by the Stage. + * @return True if the actor is a root actor. + */ + bool IsRoot() const + { + return mIsRoot; + } + + /** + * Query whether the actor is connected to the Stage. + */ + bool OnStage() const; + + /** + * Query whether the actor is a RenderableActor derived type. + * @return True if the actor is renderable. + */ + bool IsRenderable() const + { + // inlined as this is called a lot in hit testing + return mIsRenderable; + } + + /** + * Query whether the actor is of class Dali::Layer + * @return True if the actor is a layer. + */ + bool IsLayer() const + { + // inlined as this is called a lot in hit testing + return mIsLayer; + } + + /** + * Gets the layer in which the actor is present + * @return The layer, which will be uninitialized if the actor is off-stage. + */ + Dali::Layer GetLayer(); + + /** + * Adds a child Actor to this Actor. + * @pre The child actor is not the same as the parent actor. + * @pre The child actor does not already have a parent. + * @param [in] child The child. + * @post The child will be referenced by its parent. + */ + void Add( Actor& child ); + + /** + * Removes a child Actor from this Actor. + * @param [in] child The child. + * @post The child will be unreferenced. + */ + void Remove( Actor& child ); + + /** + * @copydoc Dali::Actor::Unparent + */ + void Unparent(); + + /** + * Retrieve the number of children held by the actor. + * @return The number of children + */ + unsigned int GetChildCount() const; + + /** + * @copydoc Dali::Actor::GetChildAt + */ + ActorPtr GetChildAt( unsigned int index ) const; + + /** + * Retrieve a reference to Actor's children. + * @note Not for public use. + * @return A reference to the container of children. + */ + ActorContainer& GetChildrenInternal() + { + return *mChildren; + } + + /** + * @copydoc Dali::Actor::FindChildByName + */ + ActorPtr FindChildByName( const std::string& actorName ); + + /** + * @copydoc Dali::Actor::FindChildById + */ + ActorPtr FindChildById( const unsigned int id ); + + /** + * Retrieve the parent of an Actor. + * @return The parent actor, or NULL if the Actor does not have a parent. + */ + Actor* GetParent() const + { + return mParent; + } + + /** + * Sets the size of an actor. + * ActorAttachments attached to the actor, can be scaled to fit within this area. + * This does not interfere with the actors scale factor. + * @param [in] width The new width. + * @param [in] height The new height. + */ + void SetSize( float width, float height ); + + /** + * Sets the size of an actor. + * ActorAttachments attached to the actor, can be scaled to fit within this area. + * This does not interfere with the actors scale factor. + * @param [in] width The size of the actor along the x-axis. + * @param [in] height The size of the actor along the y-axis. + * @param [in] depth The size of the actor along the z-axis. + */ + void SetSize( float width, float height, float depth ); + + /** + * Sets the size of an actor. + * ActorAttachments attached to the actor, can be scaled to fit within this area. + * This does not interfere with the actors scale factor. + * @param [in] size The new size. + */ + void SetSize( const Vector2& size ); + + /** + * Sets the update size for an actor. + * + * @param[in] size The size to set. + */ + void SetSizeInternal( const Vector2& size ); + + /** + * Sets the size of an actor. + * ActorAttachments attached to the actor, can be scaled to fit within this area. + * This does not interfere with the actors scale factor. + * @param [in] size The new size. + */ + void SetSize( const Vector3& size ); + + /** + * Sets the update size for an actor. + * + * @param[in] size The size to set. + */ + void SetSizeInternal( const Vector3& size ); + + /** + * Set the width component of the Actor's size. + * @param [in] width The new width component. + */ + void SetWidth( float width ); + + /** + * Set the height component of the Actor's size. + * @param [in] height The new height component. + */ + void SetHeight( float height ); + + /** + * Set the depth component of the Actor's size. + * @param [in] depth The new depth component. + */ + void SetDepth( float depth ); + + /** + * Retrieve the Actor's size from event side. + * This size will be the size set or if animating then the target size. + * @return The Actor's size. + */ + const Vector3& GetTargetSize() const; + + /** + * Retrieve the Actor's size from update side. + * This size will be the size set or animating but will be a frame behind. + * @return The Actor's size. + */ + const Vector3& GetCurrentSize() const; + + /** + * Return the natural size of the actor + * + * @return The actor's natural size + */ + virtual Vector3 GetNaturalSize() const; + + /** + * Set the origin of an actor, within its parent's area. + * This is expressed in 2D unit coordinates, such that (0.0, 0.0, 0.5) is the top-left corner of the parent, + * and (1.0, 1.0, 0.5) is the bottom-right corner. + * The default parent-origin is top-left (0.0, 0.0, 0.5). + * An actor position is the distance between this origin, and the actors anchor-point. + * @param [in] origin The new parent-origin. + */ + void SetParentOrigin( const Vector3& origin ); + + /** + * Set the x component of the parent-origin + * @param [in] x The new x value. + */ + void SetParentOriginX( float x ); + + /** + * Set the y component of the parent-origin + * @param [in] y The new y value. + */ + void SetParentOriginY( float y ); + + /** + * Set the z component of the parent-origin + * @param [in] z The new z value. + */ + void SetParentOriginZ( float z ); + + /** + * Retrieve the parent-origin of an actor. + * @return The parent-origin. + */ + const Vector3& GetCurrentParentOrigin() const; + + /** + * Set the anchor-point of an actor. This is expressed in 2D unit coordinates, such that + * (0.0, 0.0, 0.5) is the top-left corner of the actor, and (1.0, 1.0, 0.5) is the bottom-right corner. + * The default anchor point is top-left (0.0, 0.0, 0.5). + * An actor position is the distance between its parent-origin, and this anchor-point. + * An actor's rotation is centered around its anchor-point. + * @param [in] anchorPoint The new anchor-point. + */ + void SetAnchorPoint( const Vector3& anchorPoint ); + + /** + * Set the x component of the anchor-point. + * @param [in] x The new x value. + */ + void SetAnchorPointX( float x ); + + /** + * Set the y component of the anchor-point. + * @param [in] y The new y value. + */ + void SetAnchorPointY( float y ); + + /** + * Set the z component of the anchor-point. + * @param [in] z The new z value. + */ + void SetAnchorPointZ( float z ); + + /** + * Retrieve the anchor-point of an actor. + * @return The anchor-point. + */ + const Vector3& GetCurrentAnchorPoint() const; + + /** + * Sets the position of the Actor. + * The coordinates are relative to the Actor's parent. + * The Actor's z position will be set to 0.0f. + * @param [in] x The new x position + * @param [in] y The new y position + */ + void SetPosition( float x, float y ); + + /** + * Sets the position of the Actor. + * The coordinates are relative to the Actor's parent. + * @param [in] x The new x position + * @param [in] y The new y position + * @param [in] z The new z position + */ + void SetPosition( float x, float y, float z ); + + /** + * Sets the position of the Actor. + * The coordinates are relative to the Actor's parent. + * @param [in] position The new position. + */ + void SetPosition( const Vector3& position ); + + /** + * Set the position of an actor along the X-axis. + * @param [in] x The new x position + */ + void SetX( float x ); + + /** + * Set the position of an actor along the Y-axis. + * @param [in] y The new y position. + */ + void SetY( float y ); + + /** + * Set the position of an actor along the Z-axis. + * @param [in] z The new z position + */ + void SetZ( float z ); + + /** + * Translate an actor relative to its existing position. + * @param[in] distance The actor will move by this distance. + */ + void TranslateBy( const Vector3& distance ); + + /** + * Retrieve the position of the Actor. + * The coordinates are relative to the Actor's parent. + * @return the Actor's position. + */ + const Vector3& GetCurrentPosition() const; + + /** + * Retrieve the target position of the Actor. + * The coordinates are relative to the Actor's parent. + * @return the Actor's position. + */ + const Vector3& GetTargetPosition() const; + + /** + * @copydoc Dali::Actor::GetCurrentWorldPosition() + */ + const Vector3& GetCurrentWorldPosition() const; + + /** + * @copydoc Dali::Actor::SetPositionInheritanceMode() + */ + void SetPositionInheritanceMode( PositionInheritanceMode mode ); + + /** + * @copydoc Dali::Actor::GetPositionInheritanceMode() + */ + PositionInheritanceMode GetPositionInheritanceMode() const; + + /** + * Sets the orientation of the Actor. + * @param [in] angleRadians The new orientation angle in radians. + * @param [in] axis The new axis of orientation. + */ + void SetOrientation( const Radian& angleRadians, const Vector3& axis ); + + /** + * Sets the orientation of the Actor. + * @param [in] orientation The new orientation. + */ + void SetOrientation( const Quaternion& orientation ); + + /** + * Rotate an actor around its existing rotation axis. + * @param[in] angleRadians The angle to the rotation to combine with the existing rotation. + * @param[in] axis The axis of the rotation to combine with the existing rotation. + */ + void RotateBy( const Radian& angleRadians, const Vector3& axis ); + + /** + * Apply a relative rotation to an actor. + * @param[in] relativeRotation The rotation to combine with the actors existing rotation. + */ + void RotateBy( const Quaternion& relativeRotation ); + + /** + * Retreive the Actor's orientation. + * @return the orientation. + */ + const Quaternion& GetCurrentOrientation() const; + + /** + * Set whether a child actor inherits it's parent's orientation. Default is to inherit. + * Switching this off means that using SetOrientation() sets the actor's world orientation. + * @param[in] inherit - true if the actor should inherit orientation, false otherwise. + */ + void SetInheritOrientation( bool inherit ); + + /** + * Returns whether the actor inherit's it's parent's orientation. + * @return true if the actor inherit's it's parent orientation, false if it uses world orientation. + */ + bool IsOrientationInherited() const; + + /** + * Sets the factor of the parents size used for the child actor. + * Note: Only used if ResizePolicy is ResizePolicy::SIZE_RELATIVE_TO_PARENT or ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT. + * @param[in] factor The vector to multiply the parents size by to get the childs size. + */ + void SetSizeModeFactor( const Vector3& factor ); + + /** + * Gets the factor of the parents size used for the child actor. + * Note: Only used if ResizePolicy is ResizePolicy::SIZE_RELATIVE_TO_PARENT or ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT. + * @return The vector being used to multiply the parents size by to get the childs size. + */ + const Vector3& GetSizeModeFactor() const; + + /** + * @copydoc Dali::Actor::GetCurrentWorldOrientation() + */ + const Quaternion& GetCurrentWorldOrientation() const; + + /** + * Sets a scale factor applied to an actor. + * @param [in] scale The scale factor applied on all axes. + */ + void SetScale( float scale ); + + /** + * Sets a scale factor applied to an actor. + * @param [in] scaleX The scale factor applied along the x-axis. + * @param [in] scaleY The scale factor applied along the y-axis. + * @param [in] scaleZ The scale factor applied along the z-axis. + */ + void SetScale( float scaleX, float scaleY, float scaleZ ); + + /** + * Sets a scale factor applied to an actor. + * @param [in] scale A vector representing the scale factor for each axis. + */ + void SetScale( const Vector3& scale ); + + /** + * Set the x component of the scale factor. + * @param [in] x The new x value. + */ + void SetScaleX( float x ); + + /** + * Set the y component of the scale factor. + * @param [in] y The new y value. + */ + void SetScaleY( float y ); + + /** + * Set the z component of the scale factor. + * @param [in] z The new z value. + */ + void SetScaleZ( float z ); + + /** + * Apply a relative scale to an actor. + * @param[in] relativeScale The scale to combine with the actors existing scale. + */ + void ScaleBy( const Vector3& relativeScale ); + + /** + * Retrieve the scale factor applied to an actor. + * @return A vector representing the scale factor for each axis. + */ + const Vector3& GetCurrentScale() const; + + /** + * @copydoc Dali::Actor::GetCurrentWorldScale() + */ + const Vector3& GetCurrentWorldScale() const; + + /** + * @copydoc Dali::Actor::SetInheritScale() + */ + void SetInheritScale( bool inherit ); + + /** + * @copydoc Dali::Actor::IsScaleInherited() + */ + bool IsScaleInherited() const; + + /** + * @copydoc Dali::Actor::GetCurrentWorldMatrix() + */ + Matrix GetCurrentWorldMatrix() const; + + // Visibility + + /** + * Sets the visibility flag of an actor. + * @param [in] visible The new visibility flag. + */ + void SetVisible( bool visible ); + + /** + * Retrieve the visibility flag of an actor. + * @return The visibility flag. + */ + bool IsVisible() const; + + /** + * Sets the opacity of an actor. + * @param [in] opacity The new opacity. + */ + void SetOpacity( float opacity ); + + /** + * Retrieve the actor's opacity. + * @return The actor's opacity. + */ + float GetCurrentOpacity() const; + + /** + * Sets whether an actor should emit touch or hover signals; see SignalTouch() and SignalHover(). + * An actor is sensitive by default, which means that as soon as an application connects to the SignalTouch(), + * the touch event signal will be emitted, and as soon as an application connects to the SignalHover(), the + * hover event signal will be emitted. + * + * If the application wishes to temporarily disable the touch or hover event signal emission, then they can do so by calling: + * @code + * actor.SetSensitive(false); + * @endcode + * + * Then, to re-enable the touch or hover event signal emission, the application should call: + * @code + * actor.SetSensitive(true); + * @endcode + * + * @see SignalTouch() and SignalHover(). + * @note If an actor's sensitivity is set to false, then it's children will not emit a touch or hover event signal either. + * @param[in] sensitive true to enable emission of the touch or hover event signals, false otherwise. + */ + void SetSensitive( bool sensitive ) + { + mSensitive = sensitive; + } + + /** + * Query whether an actor emits touch or hover event signals. + * @see SetSensitive(bool) + * @return true, if emission of touch or hover event signals is enabled, false otherwise. + */ + bool IsSensitive() const + { + return mSensitive; + } + + /** + * @copydoc Dali::Actor::SetDrawMode + */ + void SetDrawMode( DrawMode::Type drawMode ); + + /** + * @copydoc Dali::Actor::GetDrawMode + */ + DrawMode::Type GetDrawMode() const; + + /** + * @copydoc Dali::Actor::SetOverlay + */ + void SetOverlay( bool enable ); + + /** + * @copydoc Dali::Actor::IsOverlay + */ + bool IsOverlay() const; + + /** + * Sets the actor's color. The final color of actor depends on its color mode. + * This final color is applied to the drawable elements of an actor. + * @param [in] color The new color. + */ + void SetColor( const Vector4& color ); + + /** + * Set the red component of the color. + * @param [in] red The new red component. + */ + void SetColorRed( float red ); + + /** + * Set the green component of the color. + * @param [in] green The new green component. + */ + void SetColorGreen( float green ); + + /** + * Set the blue component of the scale factor. + * @param [in] blue The new blue value. + */ + void SetColorBlue( float blue ); + + /** + * Retrieve the actor's color. + * @return The color. + */ + const Vector4& GetCurrentColor() const; + + /** + * Sets the actor's color mode. + * Color mode specifies whether Actor uses its own color or inherits its parent color + * @param [in] colorMode to use. + */ + void SetColorMode( ColorMode colorMode ); + + /** + * Returns the actor's color mode. + * @return currently used colorMode. + */ + ColorMode GetColorMode() const; + + /** + * @copydoc Dali::Actor::GetCurrentWorldColor() + */ + const Vector4& GetCurrentWorldColor() const; + + /** + * @copydoc Dali::Actor::GetHierarchyDepth() + */ + int GetHierarchyDepth() const + { + if( mIsOnStage ) + { + return static_cast(mDepth); + } + + return -1; + } + +public: + + // Size negotiation virtual functions + + /** + * @brief Called after the size negotiation has been finished for this control. + * + * The control is expected to assign this given size to itself/its children. + * + * Should be overridden by derived classes if they need to layout + * actors differently after certain operations like add or remove + * actors, resize or after changing specific properties. + * + * Note! As this function is called from inside the size negotiation algorithm, you cannot + * call RequestRelayout (the call would just be ignored) + * + * @param[in] size The allocated size. + * @param[in,out] container The control should add actors to this container that it is not able + * to allocate a size for. + */ + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ) + { + } + + /** + * @brief Notification for deriving classes when the resize policy is set + * + * @param[in] policy The policy being set + * @param[in] dimension The dimension the policy is being set for + */ + virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) {} + + /** + * @brief Virtual method to notify deriving classes that relayout dependencies have been + * met and the size for this object is about to be calculated for the given dimension + * + * @param dimension The dimension that is about to be calculated + */ + virtual void OnCalculateRelayoutSize( Dimension::Type dimension ); + + /** + * @brief Virtual method to notify deriving classes that the size for a dimension + * has just been negotiated + * + * @param[in] size The new size for the given dimension + * @param[in] dimension The dimension that was just negotiated + */ + virtual void OnLayoutNegotiated( float size, Dimension::Type dimension ); + + /** + * @brief Determine if this actor is dependent on it's children for relayout + * + * @param dimension The dimension(s) to check for + * @return Return if the actor is dependent on it's children + */ + virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ); + + /** + * @brief Determine if this actor is dependent on it's children for relayout. + * + * Called from deriving classes + * + * @param dimension The dimension(s) to check for + * @return Return if the actor is dependent on it's children + */ + virtual bool RelayoutDependentOnChildrenBase( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ); + + /** + * @brief Calculate the size for a child + * + * @param[in] child The child actor to calculate the size for + * @param[in] dimension The dimension to calculate the size for. E.g. width or height. + * @return Return the calculated size for the given dimension + */ + virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension ); + + /** + * @brief This method is called during size negotiation when a height is required for a given width. + * + * Derived classes should override this if they wish to customize the height returned. + * + * @param width to use. + * @return the height based on the width. + */ + virtual float GetHeightForWidth( float width ); + + /** + * @brief This method is called during size negotiation when a width is required for a given height. + * + * Derived classes should override this if they wish to customize the width returned. + * + * @param height to use. + * @return the width based on the width. + */ + virtual float GetWidthForHeight( float height ); + +public: + + // Size negotiation + + /** + * @brief Called by the RelayoutController to negotiate the size of an actor. + * + * The size allocated by the the algorithm is passed in which the + * actor must adhere to. A container is passed in as well which + * the actor should populate with actors it has not / or does not + * need to handle in its size negotiation. + * + * @param[in] size The allocated size. + * @param[in,out] container The container that holds actors that are fed back into the + * RelayoutController algorithm. + */ + void NegotiateSize( const Vector2& size, RelayoutContainer& container ); + + /** + * @copydoc Dali::Actor::SetResizePolicy() + */ + void SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension = Dimension::ALL_DIMENSIONS ); + + /** + * @copydoc Dali::Actor::GetResizePolicy() + */ + ResizePolicy::Type GetResizePolicy( Dimension::Type dimension ) const; + + /** + * @copydoc Dali::Actor::SetSizeScalePolicy() + */ + void SetSizeScalePolicy( SizeScalePolicy::Type policy ); + + /** + * @copydoc Dali::Actor::GetSizeScalePolicy() + */ + SizeScalePolicy::Type GetSizeScalePolicy() const; + + /** + * @copydoc Dali::Actor::SetDimensionDependency() + */ + void SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency ); + + /** + * @copydoc Dali::Actor::GetDimensionDependency() + */ + Dimension::Type GetDimensionDependency( Dimension::Type dimension ) const; + + /** + * @brief Set the size negotiation relayout enabled on this actor + * + * @param[in] relayoutEnabled Boolean to enable or disable relayout + */ + void SetRelayoutEnabled( bool relayoutEnabled ); + + /** + * @brief Return if relayout is enabled + * + * @return Return if relayout is enabled or not for this actor + */ + bool IsRelayoutEnabled() const; + + /** + * @brief Mark an actor as having it's layout dirty + * + * @param dirty Whether to mark actor as dirty or not + * @param dimension The dimension(s) to mark as dirty + */ + void SetLayoutDirty( bool dirty, Dimension::Type dimension = Dimension::ALL_DIMENSIONS ); + + /** + * @brief Return if any of an actor's dimensions are marked as dirty + * + * @param dimension The dimension(s) to check + * @return Return if any of the requested dimensions are dirty + */ + bool IsLayoutDirty( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) const; + + /** + * @brief Returns if relayout is enabled and the actor is not dirty + * + * @return Return if it is possible to relayout the actor + */ + bool RelayoutPossible( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) const; + + /** + * @brief Returns if relayout is enabled and the actor is dirty + * + * @return Return if it is required to relayout the actor + */ + bool RelayoutRequired( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) const; + + /** + * @brief Request a relayout, which means performing a size negotiation on this actor, its parent and children (and potentially whole scene) + * + * This method is automatically called from OnStageConnection(), OnChildAdd(), + * OnChildRemove(), SetSizePolicy(), SetMinimumSize() and SetMaximumSize(). + * + * This method can also be called from a derived class every time it needs a different size. + * At the end of event processing, the relayout process starts and + * all controls which requested Relayout will have their sizes (re)negotiated. + * + * @note RelayoutRequest() can be called multiple times; the size negotiation is still + * only performed once, i.e. there is no need to keep track of this in the calling side. + */ + void RelayoutRequest( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ); + + /** + * @brief Determine if this actor is dependent on it's parent for relayout + * + * @param dimension The dimension(s) to check for + * @return Return if the actor is dependent on it's parent + */ + bool RelayoutDependentOnParent( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ); + + /** + * @brief Determine if this actor has another dimension depedent on the specified one + * + * @param dimension The dimension to check for + * @param dependentDimension The dimension to check for dependency with + * @return Return if the actor is dependent on this dimension + */ + bool RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension ); + + /** + * Negotiate sizes for a control in all dimensions + * + * @param[in] allocatedSize The size constraint that the control must respect + */ + void NegotiateDimensions( const Vector2& allocatedSize ); + + /** + * Negotiate size for a specific dimension + * + * The algorithm adopts a recursive dependency checking approach. Meaning, that wherever dependencies + * are found, e.g. an actor dependent on its parent, the dependency will be calculated first with NegotiatedDimension and + * LayoutDimensionNegotiated flags being filled in on the actor. + * + * @post All actors that exist in the dependency chain connected to the given actor will have had their NegotiatedDimensions + * calculated and set as well as the LayoutDimensionNegotiated flags. + * + * @param[in] dimension The dimension to negotiate on + * @param[in] allocatedSize The size constraint that the actor must respect + */ + void NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack ); + + /** + * @brief Calculate the size of a dimension + * + * @param[in] dimension The dimension to calculate the size for + * @param[in] maximumSize The upper bounds on the size + * @return Return the calculated size for the dimension + */ + float CalculateSize( Dimension::Type dimension, const Vector2& maximumSize ); + + /** + * @brief Clamp a dimension given the relayout constraints on this actor + * + * @param[in] size The size to constrain + * @param[in] dimension The dimension the size exists in + * @return Return the clamped size + */ + float ClampDimension( float size, Dimension::Type dimension ); + + /** + * Negotiate a dimension based on the size of the parent + * + * @param[in] dimension The dimension to negotiate on + * @return Return the negotiated size + */ + float NegotiateFromParent( Dimension::Type dimension ); + + /** + * Negotiate a dimension based on the size of the parent. Fitting inside. + * + * @param[in] dimension The dimension to negotiate on + * @return Return the negotiated size + */ + float NegotiateFromParentFit( Dimension::Type dimension ); + + /** + * Negotiate a dimension based on the size of the parent. Flooding the whole space. + * + * @param[in] dimension The dimension to negotiate on + * @return Return the negotiated size + */ + float NegotiateFromParentFlood( Dimension::Type dimension ); + + /** + * @brief Negotiate a dimension based on the size of the children + * + * @param[in] dimension The dimension to negotiate on + * @return Return the negotiated size + */ + float NegotiateFromChildren( Dimension::Type dimension ); + + /** + * Set the negotiated dimension value for the given dimension(s) + * + * @param negotiatedDimension The value to set + * @param dimension The dimension(s) to set the value for + */ + void SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension = Dimension::ALL_DIMENSIONS ); + + /** + * Return the value of negotiated dimension for the given dimension + * + * @param dimension The dimension to retrieve + * @return Return the value of the negotiated dimension + */ + float GetNegotiatedDimension( Dimension::Type dimension ) const; + + /** + * @brief Set the padding for a dimension + * + * @param[in] padding Padding for the dimension. X = start (e.g. left, bottom), y = end (e.g. right, top) + * @param[in] dimension The dimension to set + */ + void SetPadding( const Vector2& padding, Dimension::Type dimension ); + + /** + * Return the value of padding for the given dimension + * + * @param dimension The dimension to retrieve + * @return Return the value of padding for the dimension + */ + Vector2 GetPadding( Dimension::Type dimension ) const; + + /** + * Return the actor size for a given dimension + * + * @param[in] dimension The dimension to retrieve the size for + * @return Return the size for the given dimension + */ + float GetSize( Dimension::Type dimension ) const; + + /** + * Return the natural size of the actor for a given dimension + * + * @param[in] dimension The dimension to retrieve the size for + * @return Return the natural size for the given dimension + */ + float GetNaturalSize( Dimension::Type dimension ) const; + + /** + * @brief Return the amount of size allocated for relayout + * + * May include padding + * + * @param[in] dimension The dimension to retrieve + * @return Return the size + */ + float GetRelayoutSize( Dimension::Type dimension ) const; + + /** + * @brief If the size has been negotiated return that else return normal size + * + * @param[in] dimension The dimension to retrieve + * @return Return the size + */ + float GetLatestSize( Dimension::Type dimension ) const; + + /** + * Apply the negotiated size to the actor + * + * @param[in] container The container to fill with actors that require further relayout + */ + void SetNegotiatedSize( RelayoutContainer& container ); + + /** + * @brief Flag the actor as having it's layout dimension negotiated. + * + * @param[in] negotiated The status of the flag to set. + * @param[in] dimension The dimension to set the flag for + */ + void SetLayoutNegotiated( bool negotiated, Dimension::Type dimension = Dimension::ALL_DIMENSIONS ); + + /** + * @brief Test whether the layout dimension for this actor has been negotiated or not. + * + * @param[in] dimension The dimension to determine the value of the flag for + * @return Return if the layout dimension is negotiated or not. + */ + bool IsLayoutNegotiated( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) const; + + /** + * @brief provides the Actor implementation of GetHeightForWidth + * @param width to use. + * @return the height based on the width. + */ + float GetHeightForWidthBase( float width ); + + /** + * @brief provides the Actor implementation of GetWidthForHeight + * @param height to use. + * @return the width based on the height. + */ + float GetWidthForHeightBase( float height ); + + /** + * @brief Calculate the size for a child + * + * @param[in] child The child actor to calculate the size for + * @param[in] dimension The dimension to calculate the size for. E.g. width or height. + * @return Return the calculated size for the given dimension + */ + float CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension ); + + /** + * @brief Set the preferred size for size negotiation + * + * @param[in] size The preferred size to set + */ + void SetPreferredSize( const Vector2& size ); + + /** + * @brief Return the preferred size used for size negotiation + * + * @return Return the preferred size + */ + Vector2 GetPreferredSize() const; + + /** + * @copydoc Dali::Actor::SetMinimumSize + */ + void SetMinimumSize( float size, Dimension::Type dimension = Dimension::ALL_DIMENSIONS ); + + /** + * @copydoc Dali::Actor::GetMinimumSize + */ + float GetMinimumSize( Dimension::Type dimension ) const; + + /** + * @copydoc Dali::Actor::SetMaximumSize + */ + void SetMaximumSize( float size, Dimension::Type dimension = Dimension::ALL_DIMENSIONS ); + + /** + * @copydoc Dali::Actor::GetMaximumSize + */ + float GetMaximumSize( Dimension::Type dimension ) const; + + /** + * @copydoc Dali::Actor::AddRenderer() + */ + unsigned int AddRenderer( Renderer& renderer ); + + /** + * @copydoc Dali::Actor::GetRendererCount() + */ + unsigned int GetRendererCount() const; + + /** + * @copydoc Dali::Actor::GetRendererAt() + */ + Renderer& GetRendererAt( unsigned int index ); + + /** + * @copydoc Dali::Actor::RemoveRenderer() + */ + void RemoveRenderer( Renderer& renderer ); + + /** + * @copydoc Dali::Actor::RemoveRenderer() + */ + void RemoveRenderer( unsigned int index ); + +public: + + /** + * Converts screen coordinates into the actor's coordinate system. + * @note The actor coordinates are relative to the top-left (0.0, 0.0, 0.5) + * @param[out] localX On return, the X-coordinate relative to the actor. + * @param[out] localY On return, the Y-coordinate relative to the actor. + * @param[in] screenX The screen X-coordinate. + * @param[in] screenY The screen Y-coordinate. + * @return True if the conversion succeeded. + */ + bool ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const; + + /** + * Converts screen coordinates into the actor's coordinate system. + * @note The actor coordinates are relative to the top-left (0.0, 0.0, 0.5) + * @param[in] renderTask The render-task used to display the actor. + * @param[out] localX On return, the X-coordinate relative to the actor. + * @param[out] localY On return, the Y-coordinate relative to the actor. + * @param[in] screenX The screen X-coordinate. + * @param[in] screenY The screen Y-coordinate. + * @return True if the conversion succeeded. + */ + bool ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const; + + /** + * Converts from the actor's coordinate system to screen coordinates. + * @note The actor coordinates are relative to the top-left (0.0, 0.0, 0.5) + * @param[in] viewMatrix The view-matrix + * @param[in] projectionMatrix The projection-matrix + * @param[in] viewport The view-port + * @param[out] localX On return, the X-coordinate relative to the actor. + * @param[out] localY On return, the Y-coordinate relative to the actor. + * @param[in] screenX The screen X-coordinate. + * @param[in] screenY The screen Y-coordinate. + * @return True if the conversion succeeded. + */ + bool ScreenToLocal( const Matrix& viewMatrix, + const Matrix& projectionMatrix, + const Viewport& viewport, + float& localX, + float& localY, + float screenX, + float screenY ) const; + + /** + * Performs a ray-sphere test with the given pick-ray and the actor's bounding sphere. + * @note The actor coordinates are relative to the top-left (0.0, 0.0, 0.5) + * @param[in] rayOrigin The ray origin in the world's reference system. + * @param[in] rayDir The ray director vector in the world's reference system. + * @return True if the ray intersects the actor's bounding sphere. + */ + bool RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const; + + /** + * Performs a ray-actor test with the given pick-ray and the actor's geometry. + * @note The actor coordinates are relative to the top-left (0.0, 0.0, 0.5) + * @param[in] rayOrigin The ray origin in the world's reference system. + * @param[in] rayDir The ray director vector in the world's reference system. + * @param[out] hitPointLocal The hit point in the Actor's local reference system. + * @param[out] distance The distance from the hit point to the camera. + * @return True if the ray intersects the actor's geometry. + */ + bool RayActorTest( const Vector4& rayOrigin, + const Vector4& rayDir, + Vector4& hitPointLocal, + float& distance ) const; + + /** + * Sets whether the actor should receive a notification when touch or hover motion events leave + * the boundary of the actor. + * + * @note By default, this is set to false as most actors do not require this. + * @note Need to connect to the SignalTouch or SignalHover to actually receive this event. + * + * @param[in] required Should be set to true if a Leave event is required + */ + void SetLeaveRequired( bool required ); + + /** + * This returns whether the actor requires touch or hover events whenever touch or hover motion events leave + * the boundary of the actor. + * @return true if a Leave event is required, false otherwise. + */ + bool GetLeaveRequired() const; + + /** + * @copydoc Dali::Actor::SetKeyboardFocusable() + */ + void SetKeyboardFocusable( bool focusable ); + + /** + * @copydoc Dali::Actor::IsKeyboardFocusable() + */ + bool IsKeyboardFocusable() const; + + /** + * Query whether the application or derived actor type requires touch events. + * @return True if touch events are required. + */ + bool GetTouchRequired() const; + + /** + * Query whether the application or derived actor type requires hover events. + * @return True if hover events are required. + */ + bool GetHoverRequired() const; + + /** + * Query whether the application or derived actor type requires wheel events. + * @return True if wheel events are required. + */ + bool GetWheelEventRequired() const; + + /** + * Query whether the actor is actually hittable. This method checks whether the actor is + * sensitive, has the visibility flag set to true and is not fully transparent. + * @return true, if it can be hit, false otherwise. + */ + bool IsHittable() const; + + // Gestures + + /** + * Retrieve the gesture data associated with this actor. The first call to this method will + * allocate space for the ActorGestureData so this should only be called if an actor really does + * require gestures. + * @return Reference to the ActorGestureData for this actor. + * @note Once the gesture-data is created for an actor it is likely that gestures are required + * throughout the actor's lifetime so it will only be deleted when the actor is destroyed. + */ + ActorGestureData& GetGestureData(); + + /** + * Queries whether the actor requires the gesture type. + * @param[in] type The gesture type. + */ + bool IsGestureRequred( Gesture::Type type ) const; + + // Signals + + /** + * Used by the EventProcessor to emit touch event signals. + * @param[in] event The touch event. + * @return True if the event was consumed. + */ + bool EmitTouchEventSignal( const TouchEvent& event ); + + /** + * Used by the EventProcessor to emit hover event signals. + * @param[in] event The hover event. + * @return True if the event was consumed. + */ + bool EmitHoverEventSignal( const HoverEvent& event ); + + /** + * Used by the EventProcessor to emit wheel event signals. + * @param[in] event The wheel event. + * @return True if the event was consumed. + */ + bool EmitWheelEventSignal( const WheelEvent& event ); + + /** + * @copydoc Dali::Actor::TouchedSignal() + */ + Dali::Actor::TouchSignalType& TouchedSignal(); + + /** + * @copydoc Dali::Actor::HoveredSignal() + */ + Dali::Actor::HoverSignalType& HoveredSignal(); + + /** + * @copydoc Dali::Actor::WheelEventSignal() + */ + Dali::Actor::WheelEventSignalType& WheelEventSignal(); + + /** + * @copydoc Dali::Actor::OnStageSignal() + */ + Dali::Actor::OnStageSignalType& OnStageSignal(); + + /** + * @copydoc Dali::Actor::OffStageSignal() + */ + Dali::Actor::OffStageSignalType& OffStageSignal(); + + /** + * @copydoc Dali::Actor::OnRelayoutSignal() + */ + Dali::Actor::OnRelayoutSignalType& OnRelayoutSignal(); + + /** + * Connects a callback function with the object's signals. + * @param[in] object The object providing the signal. + * @param[in] tracker Used to disconnect the signal. + * @param[in] signalName The signal to connect to. + * @param[in] functor A newly allocated FunctorDelegate. + * @return True if the signal was connected. + * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor. + */ + static bool DoConnectSignal( BaseObject* object, + ConnectionTrackerInterface* tracker, + const std::string& signalName, + FunctorDelegate* functor ); + + /** + * Performs actions as requested using the action name. + * @param[in] object The object on which to perform the action. + * @param[in] actionName The action to perform. + * @param[in] attributes The attributes with which to perfrom this action. + * @return true if the action was done. + */ + static bool DoAction( BaseObject* object, + const std::string& actionName, + const Property::Map& attributes ); + +public: + // For Animation + + /** + * This should only be called by Animation, when the actors SIZE property is animated. + * + * @param[in] animation The animation that resized the actor + * @param[in] targetSize The new target size of the actor + */ + void NotifySizeAnimation( Animation& animation, const Vector3& targetSize ); + + /** + * This should only be called by Animation, when the actors SIZE_WIDTH or SIZE_HEIGHT property is animated. + * + * @param[in] animation The animation that resized the actor + * @param[in] targetSize The new target size of the actor + */ + void NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property ); + + /** + * For use in derived classes. + * This should only be called by Animation, when the actor is resized using Animation::Resize(). + */ + virtual void OnSizeAnimation( Animation& animation, const Vector3& targetSize ) + { + } + +protected: + + enum DerivedType + { + BASIC, RENDERABLE, LAYER, ROOT_LAYER + }; + + /** + * Protected Constructor. See Actor::New(). + * The second-phase construction Initialize() member should be called immediately after this. + * @param[in] derivedType The derived type of actor (if any). + */ + Actor( DerivedType derivedType ); + + /** + * Second-phase constructor. Must be called immediately after creating a new Actor; + */ + void Initialize( void ); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~Actor(); + + /** + * Called on a child during Add() when the parent actor is connected to the Stage. + * @param[in] stage The stage. + * @param[in] parentDepth The depth of the parent in the hierarchy + * @param[in] index If set, it is only used for positioning the actor within the parent's child list. + */ + void ConnectToStage( unsigned int parentDepth, int index = -1 ); + + /** + * Helper for ConnectToStage, to recursively connect a tree of actors. + * This is atomic i.e. not interrupted by user callbacks. + * @param[in] index If set, it is only used for positioning the actor within the parent's child list. + * @param[in] depth The depth in the hierarchy of the actor + * @param[out] connectionList On return, the list of connected actors which require notification. + */ + void RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index = -1 ); + + /** + * Connect the Node associated with this Actor to the scene-graph. + * @param[in] index If set, it is only used for positioning the actor within the parent's child list. + */ + void ConnectToSceneGraph( int index = -1 ); + + /** + * Helper for ConnectToStage, to notify a connected actor through the public API. + */ + void NotifyStageConnection(); + + /** + * Called on a child during Remove() when the actor was previously on the Stage. + */ + void DisconnectFromStage(); + + /** + * Helper for DisconnectFromStage, to recursively disconnect a tree of actors. + * This is atomic i.e. not interrupted by user callbacks. + * @param[out] disconnectionList On return, the list of disconnected actors which require notification. + */ + void RecursiveDisconnectFromStage( ActorContainer& disconnectionList ); + + /** + * Disconnect the Node associated with this Actor from the scene-graph. + */ + void DisconnectFromSceneGraph(); + + /** + * Helper for DisconnectFromStage, to notify a disconnected actor through the public API. + */ + void NotifyStageDisconnection(); + + /** + * When the Actor is OnStage, checks whether the corresponding Node is connected to the scene graph. + * @return True if the Actor is OnStage & has a Node connected to the scene graph. + */ + bool IsNodeConnected() const; + + /** + * Calculate the size of the z dimension for a 2D size + * + * @param[in] size The 2D size (X, Y) to calculate Z from + * + * @return Return the Z dimension for this size + */ + float CalculateSizeZ( const Vector2& size ) const; + +public: + // Default property extensions from Object + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyCount() + */ + virtual unsigned int GetDefaultPropertyCount() const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices() + */ + virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyName() + */ + virtual const char* GetDefaultPropertyName( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex() + */ + virtual Property::Index GetDefaultPropertyIndex( const std::string& name ) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable() + */ + virtual bool IsDefaultPropertyWritable( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable() + */ + virtual bool IsDefaultPropertyAnimatable( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput() + */ + virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyType() + */ + virtual Property::Type GetDefaultPropertyType( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::SetDefaultProperty() + */ + virtual void SetDefaultProperty( Property::Index index, const Property::Value& propertyValue ); + + /** + * @copydoc Dali::Internal::Object::SetSceneGraphProperty() + */ + virtual void SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value ); + + /** + * @copydoc Dali::Internal::Object::GetDefaultProperty() + */ + virtual Property::Value GetDefaultProperty( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetPropertyOwner() + */ + virtual const SceneGraph::PropertyOwner* GetPropertyOwner() const; + + /** + * @copydoc Dali::Internal::Object::GetSceneObject() + */ + virtual const SceneGraph::PropertyOwner* GetSceneObject() const; + + /** + * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty() + */ + virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty() + */ + virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetPropertyComponentIndex() + */ + virtual int GetPropertyComponentIndex( Property::Index index ) const; + +private: + + // Undefined + Actor(); + + // Undefined + Actor( const Actor& ); + + // Undefined + Actor& operator=( const Actor& rhs ); + + /** + * Set the actors parent. + * @param[in] parent The new parent. + * @param[in] index If set, it is only used for positioning the actor within the parent's child list. + */ + void SetParent( Actor* parent, int index = -1 ); + + /** + * Helper to create a Node for this Actor. + * To be overriden in derived classes. + * @return A newly allocated node. + */ + virtual SceneGraph::Node* CreateNode() const; + + /** + * For use in derived classes, called after Initialize() + */ + virtual void OnInitialize() + { + } + + /** + * For use in internal derived classes. + * This is called during ConnectToStage(), after the actor has finished adding its node to the scene-graph. + * The derived class must not modify the actor hierachy (Add/Remove children) during this callback. + */ + virtual void OnStageConnectionInternal() + { + } + + /** + * For use in internal derived classes. + * This is called during DisconnectFromStage(), before the actor removes its node from the scene-graph. + * The derived class must not modify the actor hierachy (Add/Remove children) during this callback. + */ + virtual void OnStageDisconnectionInternal() + { + } + + /** + * For use in external (CustomActor) derived classes. + * This is called after the atomic ConnectToStage() traversal has been completed. + */ + virtual void OnStageConnectionExternal( int depth ) + { + } + + /** + * For use in external (CustomActor) derived classes. + * This is called after the atomic DisconnectFromStage() traversal has been completed. + */ + virtual void OnStageDisconnectionExternal() + { + } + + /** + * For use in derived classes; this is called after Add() has added a child. + * @param[in] child The child that was added. + */ + virtual void OnChildAdd( Actor& child ) + { + } + + /** + * For use in derived classes; this is called after Remove() has removed a child. + * @param[in] child The child that was removed. + */ + virtual void OnChildRemove( Actor& child ) + { + } + + /** + * For use in derived classes. + * This is called after SizeSet() has been called. + */ + virtual void OnSizeSet( const Vector3& targetSize ) + { + } + + /** + * For use in derived classes. + * This is only called if mDerivedRequiresTouch is true, and the touch-signal was not consumed. + * @param[in] event The touch event. + * @return True if the event should be consumed. + */ + virtual bool OnTouchEvent( const TouchEvent& event ) + { + return false; + } + + /** + * For use in derived classes. + * This is only called if mDerivedRequiresHover is true, and the hover-signal was not consumed. + * @param[in] event The hover event. + * @return True if the event should be consumed. + */ + virtual bool OnHoverEvent( const HoverEvent& event ) + { + return false; + } + + /** + * For use in derived classes. + * This is only called if the wheel signal was not consumed. + * @param[in] event The wheel event. + * @return True if the event should be consumed. + */ + virtual bool OnWheelEvent( const WheelEvent& event ) + { + return false; + } + + /** + * @brief Ensure the relayout data is allocated + */ + void EnsureRelayoutData(); + + /** + * @brief Apply the size set policy to the input size + * + * @param[in] size The size to apply the policy to + * @return Return the adjusted size + */ + Vector2 ApplySizeSetPolicy( const Vector2 size ); + +protected: + + Actor* mParent; ///< Each actor (except the root) can have one parent + ActorContainer* mChildren; ///< Container of referenced actors + const SceneGraph::Node* mNode; ///< Not owned + Vector3* mParentOrigin; ///< NULL means ParentOrigin::DEFAULT. ParentOrigin is non-animatable + Vector3* mAnchorPoint; ///< NULL means AnchorPoint::DEFAULT. AnchorPoint is non-animatable + + struct RelayoutData; + RelayoutData* mRelayoutData; ///< Struct to hold optional collection of relayout variables + + ActorGestureData* mGestureData; ///< Optional Gesture data. Only created when actor requires gestures + + ActorAttachmentPtr mAttachment; ///< Optional referenced attachment + + // Signals + Dali::Actor::TouchSignalType mTouchedSignal; + Dali::Actor::HoverSignalType mHoveredSignal; + Dali::Actor::WheelEventSignalType mWheelEventSignal; + Dali::Actor::OnStageSignalType mOnStageSignal; + Dali::Actor::OffStageSignalType mOffStageSignal; + Dali::Actor::OnRelayoutSignalType mOnRelayoutSignal; + + Vector3 mTargetSize; ///< Event-side storage for size (not a pointer as most actors will have a size) + Vector3 mTargetPosition; ///< Event-side storage for position (not a pointer as most actors will have a position) + + std::string mName; ///< Name of the actor + unsigned int mId; ///< A unique ID to identify the actor starting from 1, and 0 is reserved + + unsigned short mDepth :12; ///< Cached: The depth in the hierarchy of the actor. Only 4096 levels of depth are supported + const bool mIsRoot : 1; ///< Flag to identify the root actor + const bool mIsRenderable : 1; ///< Flag to identify that this is a renderable actor + const bool mIsLayer : 1; ///< Flag to identify that this is a layer + bool mIsOnStage : 1; ///< Flag to identify whether the actor is on-stage + bool mSensitive : 1; ///< Whether the actor emits touch event signals + bool mLeaveRequired : 1; ///< Whether a touch event signal is emitted when the a touch leaves the actor's bounds + bool mKeyboardFocusable : 1; ///< Whether the actor should be focusable by keyboard navigation + bool mDerivedRequiresTouch : 1; ///< Whether the derived actor type requires touch event signals + bool mDerivedRequiresHover : 1; ///< Whether the derived actor type requires hover event signals + bool mDerivedRequiresWheelEvent : 1; ///< Whether the derived actor type requires wheel event signals + bool mOnStageSignalled : 1; ///< Set to true before OnStageConnection signal is emitted, and false before OnStageDisconnection + bool mInsideOnSizeSet : 1; ///< Whether we are inside OnSizeSet + bool mInheritOrientation : 1; ///< Cached: Whether the parent's orientation should be inherited. + bool mInheritScale : 1; ///< Cached: Whether the parent's scale should be inherited. + DrawMode::Type mDrawMode : 2; ///< Cached: How the actor and its children should be drawn + PositionInheritanceMode mPositionInheritanceMode : 2; ///< Cached: Determines how position is inherited + ColorMode mColorMode : 2; ///< Cached: Determines whether mWorldColor is inherited + +private: + + static ActorContainer mNullChildren; ///< Empty container (shared by all actors, returned by GetChildren() const) + static unsigned int mActorCounter; ///< A counter to track the actor instance creation + +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Internal::Actor& GetImplementation( Dali::Actor& actor ) +{ + DALI_ASSERT_ALWAYS( actor && "Actor handle is empty" ); + + BaseObject& handle = actor.GetBaseObject(); + + return static_cast< Internal::Actor& >( handle ); +} + +inline const Internal::Actor& GetImplementation( const Dali::Actor& actor ) +{ + DALI_ASSERT_ALWAYS( actor && "Actor handle is empty" ); + + const BaseObject& handle = actor.GetBaseObject(); + + return static_cast< const Internal::Actor& >( handle ); +} + +} // namespace Dali + +#endif // __DALI_INTERNAL_ACTOR_H__ diff --git a/dali/internal/event/actors/camera-actor-impl.cpp b/dali/internal/event/actors/camera-actor-impl.cpp new file mode 100644 index 0000000..7ee2ef1 --- /dev/null +++ b/dali/internal/event/actors/camera-actor-impl.cpp @@ -0,0 +1,802 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include +#include // for strcmp + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace +{ + +// Properties + +/** + * We want to discourage the use of property strings (minimize string comparisons), + * particularly for the default properties. + * Name Type writable animatable constraint-input enum for index-checking + */ +DALI_PROPERTY_TABLE_BEGIN +DALI_PROPERTY( "type", STRING, true, false, true, Dali::CameraActor::Property::TYPE ) +DALI_PROPERTY( "projection-mode", STRING, true, false, true, Dali::CameraActor::Property::PROJECTION_MODE ) +DALI_PROPERTY( "field-of-view", FLOAT, true, false, true, Dali::CameraActor::Property::FIELD_OF_VIEW ) +DALI_PROPERTY( "aspect-ratio", FLOAT, true, false, true, Dali::CameraActor::Property::ASPECT_RATIO ) +DALI_PROPERTY( "near-plane-distance", FLOAT, true, false, true, Dali::CameraActor::Property::NEAR_PLANE_DISTANCE ) +DALI_PROPERTY( "far-plane-distance", FLOAT, true, false, true, Dali::CameraActor::Property::FAR_PLANE_DISTANCE ) +DALI_PROPERTY( "left-plane-distance", FLOAT, true, false, true, Dali::CameraActor::Property::LEFT_PLANE_DISTANCE ) +DALI_PROPERTY( "right-plane-distance", FLOAT, true, false, true, Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE ) +DALI_PROPERTY( "top-plane-distance", FLOAT, true, false, true, Dali::CameraActor::Property::TOP_PLANE_DISTANCE ) +DALI_PROPERTY( "bottom-plane-distance", FLOAT, true, false, true, Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE ) +DALI_PROPERTY( "target-position", VECTOR3, true, false, true, Dali::CameraActor::Property::TARGET_POSITION ) +DALI_PROPERTY( "projection-matrix", MATRIX, false, false, true, Dali::CameraActor::Property::PROJECTION_MATRIX ) +DALI_PROPERTY( "view-matrix", MATRIX, false, false, true, Dali::CameraActor::Property::VIEW_MATRIX ) +DALI_PROPERTY( "invert-y-axis", BOOLEAN, true, false, true, Dali::CameraActor::Property::INVERT_Y_AXIS ) +DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX ) + +// calculate the far plane distance for a 16bit depth buffer with 4 bits per unit precision +void CalculateClippingAndZ( float width, float height, float& nearClippingPlane, float& farClippingPlane, float& cameraZ ) +{ + nearClippingPlane = std::max( width, height ); + farClippingPlane = nearClippingPlane + static_cast( 0xFFFF >> 4 ); + cameraZ = 2.0f * nearClippingPlane; +} + +BaseHandle Create() +{ + return Dali::CameraActor::New(); +} + +TypeRegistration mType( typeid( Dali::CameraActor ), typeid( Dali::Actor ), Create ); + +/** + * Builds the picking ray in the world reference system from an orthographic camera + * The ray origin is the screen coordinate in the near plane translated to a parallel + * plane at the camera origin. The ray direction is the direction the camera is facing + * (i.e. Z=-1 in view space). + */ +void BuildOrthoPickingRay( const Matrix& viewMatrix, + const Matrix& projectionMatrix, + const Viewport& viewport, + float screenX, + float screenY, + Vector4& rayOrigin, + Vector4& rayDir, + float nearPlaneDistance ) +{ + // inv( modelMatrix ) inv( viewMatrix ) inv( projectionMatrix ) normalize + // <----------------- <----------------- <-------------- <------------- + // Local World Camera Normalized Screen + // reference reference reference clip coordinates + // system system system coordinates + // -----------------> -----------------> --------------> -------------> + // modelMatrix viewMatrix projectionMatrix viewport + + // Transforms the touch point from the screen reference system to the world reference system. + Matrix invViewProjection( false ); // Don't initialize. + Matrix::Multiply( invViewProjection, viewMatrix, projectionMatrix ); + if( !invViewProjection.Invert() ) + { + DALI_ASSERT_DEBUG( false ); + } + + Vector4 near( screenX - viewport.x, viewport.height - (screenY - viewport.y), 0.f, 1.f ); + if( !Unproject( near, invViewProjection, viewport.width, viewport.height, rayOrigin ) ) + { + DALI_ASSERT_DEBUG( false ); + } + + Matrix invView = viewMatrix; + if( !invView.Invert() ) + { + DALI_ASSERT_DEBUG( false ); + } + + Vector4 cameraOrigin = invView * Vector4( 0.f, 0.f, 0.f, 1.f ); + Vector4 nearPlaneOrigin = invView * Vector4( 0.0f, 0.0f, -nearPlaneDistance, 1.0f); + + // Vector pointing from the camera to the near plane + rayDir = cameraOrigin - nearPlaneOrigin; + rayOrigin -= rayDir; + rayDir.Normalize(); + rayDir.w = 1.0f; +} + +} // namespace + +CameraActorPtr CameraActor::New( const Size& size ) +{ + CameraActorPtr actor(new CameraActor()); + + // Second-phase construction + + actor->Initialize(); + + actor->SetName("DefaultCamera"); + + // Create the attachment + actor->mCameraAttachment = CameraAttachment::New( actor->GetEventThreadServices(), *actor->mNode ); + + actor->Attach(*actor->mCameraAttachment); + + actor->SetPerspectiveProjection( size ); + + // By default Actors face in the positive Z direction in world space + // CameraActors should face in the negative Z direction, towards the other actors + actor->SetOrientation( Quaternion( Dali::ANGLE_180, Vector3::YAXIS ) ); + + return actor; +} + +void CameraActor::OnInitialize() +{ +} + +CameraActor::CameraActor() +: Actor( Actor::BASIC ) +{ +} + +CameraActor::~CameraActor() +{ +} + +void CameraActor::SetType( Dali::Camera::Type type ) +{ + mCameraAttachment->SetType(type); +} + +Dali::Camera::Type CameraActor::GetType() const +{ + return mCameraAttachment->GetType(); +} + +void CameraActor::SetProjectionMode( Dali::Camera::ProjectionMode mode ) +{ + mCameraAttachment->SetProjectionMode(mode); +} + +Dali::Camera::ProjectionMode CameraActor::GetProjectionMode() const +{ + return mCameraAttachment->GetProjectionMode(); +} + +void CameraActor::SetFieldOfView( float fieldOfView ) +{ + mCameraAttachment->SetFieldOfView(fieldOfView); +} + +float CameraActor::GetFieldOfView( ) const +{ + return mCameraAttachment->GetFieldOfView(); +} + +void CameraActor::SetAspectRatio( float aspectRatio ) +{ + mCameraAttachment->SetAspectRatio(aspectRatio); +} + +float CameraActor::GetAspectRatio( ) const +{ + return mCameraAttachment->GetAspectRatio(); +} + +void CameraActor::SetNearClippingPlane( float nearClippingPlane ) +{ + mCameraAttachment->SetNearClippingPlane(nearClippingPlane); +} + +float CameraActor::GetNearClippingPlane( ) const +{ + return mCameraAttachment->GetNearClippingPlane(); +} + +void CameraActor::SetFarClippingPlane( float farClippingPlane ) +{ + mCameraAttachment->SetFarClippingPlane(farClippingPlane); +} + +float CameraActor::GetFarClippingPlane( ) const +{ + return mCameraAttachment->GetFarClippingPlane(); +} + +void CameraActor::SetTargetPosition(const Vector3& target) +{ + mCameraAttachment->SetTargetPosition(target); +} + +Vector3 CameraActor::GetTargetPosition() const +{ + return mCameraAttachment->GetTargetPosition(); +} + +void CameraActor::SetInvertYAxis(bool invertYAxis) +{ + mCameraAttachment->SetInvertYAxis(invertYAxis); +} + +bool CameraActor::GetInvertYAxis() const +{ + return mCameraAttachment->GetInvertYAxis(); +} + +void CameraActor::SetPerspectiveProjection( const Size& size, const Vector2& stereoBias /* = Vector2::ZERO */ ) +{ + float width = size.width; + float height = size.height; + + if( Size::ZERO == size ) + { + StagePtr stage = Stage::GetCurrent(); + if( stage ) + { + const Size& stageSize = stage->GetSize(); + + width = stageSize.width; + height = stageSize.height; + } + } + + if( ( width < Math::MACHINE_EPSILON_1000 ) || ( height < Math::MACHINE_EPSILON_1000 ) ) + { + // On the stage initialization this method is called but the size has not been set. + // There is no point to set any value if width or height is zero. + return; + } + + float nearClippingPlane; + float farClippingPlane; + float cameraZ; + CalculateClippingAndZ( width, height, nearClippingPlane, farClippingPlane, cameraZ ); + + // calculate the position of the camera to have the desired aspect ratio + const float fieldOfView = 2.0f * std::atan( height * 0.5f / cameraZ ); + + // unless it is too small, we want at least as much space to the back as we have torwards the front + const float minClippingFarPlane = 2.f * nearClippingPlane; + if ( farClippingPlane < minClippingFarPlane ) + { + farClippingPlane = minClippingFarPlane; + } + + const float aspectRatio = width / height; + + SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION); + SetFieldOfView( fieldOfView ); + SetNearClippingPlane( nearClippingPlane ); + SetFarClippingPlane( farClippingPlane ); + SetAspectRatio( aspectRatio ); + mCameraAttachment->SetStereoBias( stereoBias ); + SetZ( cameraZ ); +} + + +void CameraActor::SetOrthographicProjection( const Vector2& size ) +{ + // Choose near, far and Z parameters to match the SetPerspectiveProjection above. + float nearClippingPlane; + float farClippingPlane; + float cameraZ; + CalculateClippingAndZ( size.width, size.height, nearClippingPlane, farClippingPlane, cameraZ ); + SetOrthographicProjection( -size.x*0.5f, size.x*0.5f, size.y*0.5f, -size.y*0.5f, + nearClippingPlane, farClippingPlane ); + SetZ( cameraZ ); +} + +void CameraActor::SetOrthographicProjection( float left, float right, float top, float bottom, float near, float far ) +{ + mCameraAttachment->SetLeftClippingPlane(left); + mCameraAttachment->SetRightClippingPlane(right); + mCameraAttachment->SetTopClippingPlane(top); + mCameraAttachment->SetBottomClippingPlane(bottom); + SetNearClippingPlane( near ); + SetFarClippingPlane( far ); + SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION); +} + +bool CameraActor::BuildPickingRay( const Vector2& screenCoordinates, + const Viewport& viewport, + Vector4& rayOrigin, + Vector4& rayDirection ) +{ + bool success = true; + if( GetProjectionMode() == Dali::Camera::PERSPECTIVE_PROJECTION ) + { + // Build a picking ray in the world reference system. + // ray starts from the camera world position + rayOrigin = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() ); + rayOrigin.w = 1.0f; + + // Transform the touch point from the screen coordinate system to the world coordinates system. + Vector4 near( screenCoordinates.x - viewport.x, viewport.height - (screenCoordinates.y - viewport.y), 0.f, 1.f ); + if( !Unproject( near, mCameraAttachment->GetInverseViewProjectionMatrix(), viewport.width, viewport.height, near ) ) + { + // unproject failed so no picking ray possible + success = false; + } + + // Compute the ray's director vector. + rayDirection.x = near.x - rayOrigin.x; + rayDirection.y = near.y - rayOrigin.y; + rayDirection.z = near.z - rayOrigin.z; + rayDirection.Normalize(); + rayDirection.w = 1.f; + } + else + { + float nearPlaneDistance = GetNearClippingPlane(); + BuildOrthoPickingRay( GetViewMatrix(), + GetProjectionMatrix(), + viewport, screenCoordinates.x, + screenCoordinates.y, + rayOrigin, + rayDirection, + nearPlaneDistance ); + } + + return success; +} + +const Matrix& CameraActor::GetViewMatrix() const +{ + if ( OnStage() ) + { + return mCameraAttachment->GetViewMatrix(); + } + else + { + return Matrix::IDENTITY; + } +} + +const Matrix& CameraActor::GetProjectionMatrix() const +{ + if ( OnStage() ) + { + return mCameraAttachment->GetProjectionMatrix(); + } + else + { + return Matrix::IDENTITY; + } +} + +unsigned int CameraActor::GetDefaultPropertyCount() const +{ + return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT; +} + +void CameraActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const +{ + Actor::GetDefaultPropertyIndices( indices ); // Actor class properties + + indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT ); + + int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index ) + { + indices.PushBack( index ); + } +} + +bool CameraActor::IsDefaultPropertyWritable( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::IsDefaultPropertyWritable( index ); + } + + return DEFAULT_PROPERTY_DETAILS[index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX].writable; +} + +bool CameraActor::IsDefaultPropertyAnimatable( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::IsDefaultPropertyAnimatable( index ); + } + + return DEFAULT_PROPERTY_DETAILS[index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX].animatable; +} + +bool CameraActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::IsDefaultPropertyAConstraintInput( index ); + } + + return DEFAULT_PROPERTY_DETAILS[index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX].constraintInput; +} + +Property::Type CameraActor::GetDefaultPropertyType( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::GetDefaultPropertyType( index ); + } + else + { + index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + + if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) + { + return DEFAULT_PROPERTY_DETAILS[index].type; + } + else + { + // index out-of-bounds + return Property::NONE; + } + } +} + +const char* CameraActor::GetDefaultPropertyName( Property::Index index ) const +{ + if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT) + { + return Actor::GetDefaultPropertyName(index); + } + else + { + index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + + if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) + { + return DEFAULT_PROPERTY_DETAILS[index].name; + } + return NULL; + } +} + +Property::Index CameraActor::GetDefaultPropertyIndex(const std::string& name) const +{ + Property::Index index = Property::INVALID_INDEX; + + // Look for name in current class' default properties + for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) + { + if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_DETAILS[i].name ) ) // dont want to convert rhs to string + { + index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + break; + } + } + + // If not found, check in base class + if( Property::INVALID_INDEX == index ) + { + index = Actor::GetDefaultPropertyIndex( name ); + } + + return index; +} + +void CameraActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue ) +{ + if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT) + { + Actor::SetDefaultProperty(index, propertyValue); + } + else + { + DALI_ASSERT_DEBUG(mCameraAttachment && "where is the camera?"); + switch(index) + { + case Dali::CameraActor::Property::TYPE: + { + std::string s( propertyValue.Get() ); + if(s == "LOOK_AT_TARGET") + { + mCameraAttachment->SetType(Dali::Camera::LOOK_AT_TARGET); + } + else if(s == "FREE_LOOK") + { + mCameraAttachment->SetType(Dali::Camera::FREE_LOOK); + } + else + { + DALI_LOG_WARNING("Unknown camera type\n"); + } + break; + } + case Dali::CameraActor::Property::PROJECTION_MODE: + { + std::string s(propertyValue.Get()); + if(s == "PERSPECTIVE_PROJECTION") + { + mCameraAttachment->SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION); + } + else if(s == "ORTHOGRAPHIC_PROJECTION") + { + mCameraAttachment->SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION); + } + else + { + DALI_LOG_WARNING("Unknown projection mode\n"); + } + break; + } + case Dali::CameraActor::Property::FIELD_OF_VIEW: + { + mCameraAttachment->SetFieldOfView(propertyValue.Get()); + break; + } + case Dali::CameraActor::Property::ASPECT_RATIO: + { + mCameraAttachment->SetAspectRatio(propertyValue.Get()); + break; + } + case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE: + { + mCameraAttachment->SetLeftClippingPlane(propertyValue.Get()); + break; + } + case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE: + { + mCameraAttachment->SetRightClippingPlane(propertyValue.Get()); + break; + } + case Dali::CameraActor::Property::TOP_PLANE_DISTANCE: + { + mCameraAttachment->SetTopClippingPlane(propertyValue.Get()); + break; + } + case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE: + { + mCameraAttachment->SetBottomClippingPlane(propertyValue.Get()); + break; + } + case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE: + { + mCameraAttachment->SetNearClippingPlane(propertyValue.Get()); + break; + } + case Dali::CameraActor::Property::FAR_PLANE_DISTANCE: + { + mCameraAttachment->SetFarClippingPlane(propertyValue.Get()); + break; + } + case Dali::CameraActor::Property::TARGET_POSITION: + { + mCameraAttachment->SetTargetPosition(propertyValue.Get()); + break; + } + case Dali::CameraActor::Property::PROJECTION_MATRIX: + { + DALI_LOG_WARNING("projection-matrix property is not animatable \n"); + break; + } + case Dali::CameraActor::Property::VIEW_MATRIX: + { + DALI_LOG_WARNING("view-matrix property is not animatable \n"); + break; + } + case Dali::CameraActor::Property::INVERT_Y_AXIS: + { + mCameraAttachment->SetInvertYAxis(propertyValue.Get()); + break; + } + default: + { + DALI_LOG_WARNING("Unknown property (%d)\n", index); + break; + } + } // switch(index) + + } // else +} + +Property::Value CameraActor::GetDefaultProperty( Property::Index index ) const +{ + Property::Value ret; + if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT) + { + ret = Actor::GetDefaultProperty(index); + } + else + { + DALI_ASSERT_DEBUG(mCameraAttachment && "where is the camera?"); + switch(index) + { + case Dali::CameraActor::Property::TYPE: + { + if(mCameraAttachment->GetType() == Dali::Camera::LOOK_AT_TARGET) + { + ret = "LOOK_AT_TARGET"; + } + else if(mCameraAttachment->GetType() == Dali::Camera::FREE_LOOK) + { + ret = "FREE_LOOK"; + } + else + { + ret = ""; + DALI_ASSERT_DEBUG("Unknown camera type\n"); + } + break; + } + case Dali::CameraActor::Property::PROJECTION_MODE: + { + if(mCameraAttachment->GetProjectionMode() == Dali::Camera::PERSPECTIVE_PROJECTION) + { + ret = "PERSPECTIVE_PROJECTION"; + } + else if(mCameraAttachment->GetProjectionMode() == Dali::Camera::ORTHOGRAPHIC_PROJECTION) + { + ret = "ORTHOGRAPHIC_PROJECTION"; + } + else + { + ret = ""; + DALI_ASSERT_DEBUG("Unknown projection mode\n"); + } + break; + } + case Dali::CameraActor::Property::FIELD_OF_VIEW: + { + ret = mCameraAttachment->GetFieldOfView(); + break; + } + case Dali::CameraActor::Property::ASPECT_RATIO: + { + ret = mCameraAttachment->GetAspectRatio(); + break; + } + case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE: + { + ret = mCameraAttachment->GetLeftClippingPlane(); + break; + } + case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE: + { + ret = mCameraAttachment->GetRightClippingPlane(); + break; + } + case Dali::CameraActor::Property::TOP_PLANE_DISTANCE: + { + ret = mCameraAttachment->GetTopClippingPlane(); + break; + } + case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE: + { + ret = mCameraAttachment->GetBottomClippingPlane(); + break; + } + case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE: + { + ret = mCameraAttachment->GetNearClippingPlane(); + break; + } + case Dali::CameraActor::Property::FAR_PLANE_DISTANCE: + { + ret = mCameraAttachment->GetFarClippingPlane(); + break; + } + case Dali::CameraActor::Property::TARGET_POSITION: + { + ret = mCameraAttachment->GetTargetPosition(); + break; + } + case Dali::CameraActor::Property::PROJECTION_MATRIX: + { + ret = mCameraAttachment->GetProjectionMatrix(); + break; + } + case Dali::CameraActor::Property::VIEW_MATRIX: + { + ret = mCameraAttachment->GetViewMatrix(); + break; + } + case Dali::CameraActor::Property::INVERT_Y_AXIS: + { + ret = mCameraAttachment->GetInvertYAxis(); + break; + } + default: + { + DALI_LOG_WARNING("Unknown property (%d)\n", index); + break; + } + } // switch(index) + } + + return ret; +} + +const SceneGraph::PropertyBase* CameraActor::GetSceneObjectAnimatableProperty( Property::Index index ) const +{ + DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" ); + + const SceneGraph::PropertyBase* property( NULL ); + + // This method should only return a property of an object connected to the scene-graph + if ( !OnStage() ) + { + return property; + } + + // let actor handle animatable properties, we have no animatable properties + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + property = Actor::GetSceneObjectAnimatableProperty(index); + } + + return property; +} + +const PropertyInputImpl* CameraActor::GetSceneObjectInputProperty( Property::Index index ) const +{ + const PropertyInputImpl* property( NULL ); + + // This method should only return a property of an object connected to the scene-graph + if ( !OnStage() ) + { + return property; + } + + // if its an actor default property or a custom property (actor already handles custom properties) + if( ( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) || ( index >= DEFAULT_PROPERTY_MAX_COUNT ) ) + { + property = Actor::GetSceneObjectInputProperty(index); + } + else + { + switch( index ) + { + case Dali::CameraActor::Property::PROJECTION_MATRIX: + { + property = mCameraAttachment->GetProjectionMatrixProperty(); + break; + } + case Dali::CameraActor::Property::VIEW_MATRIX: + { + property = mCameraAttachment->GetViewMatrixProperty(); + break; + } + default: + DALI_LOG_WARNING("Not an input property (%d)\n", index); + break; + } + } + + return property; +} + + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/actors/camera-actor-impl.h b/dali/internal/event/actors/camera-actor-impl.h new file mode 100644 index 0000000..3cd8d59 --- /dev/null +++ b/dali/internal/event/actors/camera-actor-impl.h @@ -0,0 +1,288 @@ +#ifndef __DALI_INTERNAL_CAMERA_ACTOR_H__ +#define __DALI_INTERNAL_CAMERA_ACTOR_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUES +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * An actor with a conveniently pre-attached CameraAttachment. + */ +class CameraActor : public Actor +{ +public: + + /** + * Create an initialised camera actor. + * + * Sets the default camera perspective projection for the given canvas size. @see SetPerspectiveProjection(). + * + * @param[in] size The canvas size. + * + * @return A smart-pointer to a newly allocated camera actor. + */ + static CameraActorPtr New( const Size& size ); + + /** + * @copydoc Dali::Actor::OnInitialize + */ + void OnInitialize(); + + /** + * Retrieve the camera attachment. + * @return The attachment. + */ + CameraAttachment& GetCameraAttachment() + { + return *mCameraAttachment; + } + + /** + * @copydoc Dali::CameraActor::SetType + */ + void SetType( Dali::Camera::Type type ); + + /** + * @copydoc Dali::CameraActor::GetType + */ + Dali::Camera::Type GetType() const; + + /** + * @copydoc Dali::CameraActor::SetProjectionMode + */ + void SetProjectionMode( Dali::Camera::ProjectionMode mode ); + + /** + * @copydoc Dali::CameraActor::GetProjectionMode + */ + Dali::Camera::ProjectionMode GetProjectionMode() const; + + /** + * @copydoc Dali::CameraActor::SetFieldOfView + */ + void SetFieldOfView( float fieldOfView ); + + /** + * @copydoc Dali::CameraActor::GetFieldOfView + */ + float GetFieldOfView( ) const; + + /** + * @copydoc Dali::CameraActor::SetAspectRatio + */ + void SetAspectRatio( float aspectRatio ); + + /** + * @copydoc Dali::CameraActor::GetAspectRatio + */ + float GetAspectRatio( ) const; + + /** + * @copydoc Dali::CameraActor::SetNearClippingPlane + */ + void SetNearClippingPlane( float nearClippingPlane ); + + /** + * @copydoc Dali::CameraActor::GetNearClippingPlane + */ + float GetNearClippingPlane( ) const; + + /** + * @copydoc Dali::CameraActor::SetFarClippingPlane + */ + void SetFarClippingPlane( float farClippingPlane ); + + /** + * @copydoc Dali::CameraActor::GetFarClippingPlane + */ + float GetFarClippingPlane( ) const; + + /** + * @copydoc Dali::CameraActor::SetTargetPosition + */ + void SetTargetPosition( const Vector3& targetPosition ); + + /** + * @copydoc Dali::CameraActor::GetTargetPosition + */ + Vector3 GetTargetPosition() const; + + /** + * @copydoc Dali::CameraActor::SetInvertYAxis + */ + void SetInvertYAxis(bool invertYAxis); + + /** + * @copydoc Dali::CameraActor::GetCurrentInvertYAxis + */ + bool GetInvertYAxis() const; + + /** + * @copydoc Dali::CameraActor::SetPerspectiveProjection() + * @param[in] stereoBias The frustum horizontal and vertical offset for stereoscopic cameras + */ + void SetPerspectiveProjection( const Size& size, const Vector2& stereoBias = Vector2::ZERO ); + + /** + * @copydoc Dali::CameraActor::SetOrthographicProjection(const Vector2& size); + */ + void SetOrthographicProjection( const Vector2& size ); + + /** + * @copydoc Dali::CameraActor::SetOrthographicProjection(float left, float right, float top, float bottom, float near, float far); + */ + void SetOrthographicProjection( float left, float right, float top, float bottom, float near, float far ); + + /** + * Build a picking ray with this camera and given screen coordinates + * @param [in] screenCoordinates the ray passed through + * @param [in] viewport to use + * @param [out] rayOrigin for the picking ray + * @param [out] rayDirection for the picking ray + * @return true if the building was successful, false if its not possible (camera is not valid for hit testing) + */ + bool BuildPickingRay( const Vector2& screenCoordinates, const Viewport& viewport, Vector4& rayOrigin, Vector4& rayDirection ); + + /** + * Retrieve the view-matrix; This will only be valid when the actor is on-stage. + * @return The view-matrix. + */ + const Matrix& GetViewMatrix() const; + + /** + * Retrieve the projection-matrix; This will only be valid when the actor is on-stage. + * @return The projection-matrix. + */ + const Matrix& GetProjectionMatrix() const; + +public: // properties + + /** + * copydoc Dali::Internal::Object + */ + virtual unsigned int GetDefaultPropertyCount() const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices() + */ + virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const; + + /** + * copydoc Dali::Internal::Object + */ + virtual bool IsDefaultPropertyAnimatable( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput() + */ + virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const; + + /** + * copydoc Dali::Internal::Object + */ + virtual Property::Type GetDefaultPropertyType( Property::Index index ) const; + + /** + * copydoc Dali::Internal::Object + */ + virtual const char* GetDefaultPropertyName( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex() + */ + virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const; + + /** + * copydoc Dali::Internal::Object + */ + virtual void SetDefaultProperty( Property::Index index, const Property::Value& propertyValue ); + + /** + * copydoc Dali::Internal::Object + */ + virtual Property::Value GetDefaultProperty( Property::Index index ) const; + + /** + * copydoc Dali::Internal::Object + */ + virtual bool IsDefaultPropertyWritable( Property::Index index ) const ; + + /** + * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty() + */ + virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty() + */ + virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const; + +protected: + + /** + * Protected constructor; see also CameraActor::New() + */ + CameraActor(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~CameraActor(); + +private: + + CameraAttachmentPtr mCameraAttachment; + +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Internal::CameraActor& GetImplementation(Dali::CameraActor& camera) +{ + DALI_ASSERT_ALWAYS(camera && "Camera handle is empty"); + + BaseObject& handle = camera.GetBaseObject(); + + return static_cast(handle); +} + +inline const Internal::CameraActor& GetImplementation(const Dali::CameraActor& camera) +{ + DALI_ASSERT_ALWAYS(camera && "Camera handle is empty"); + + const BaseObject& handle = camera.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Dali + +#endif // __DALI_INTERNAL_CAMERA_ACTOR_H__ diff --git a/dali/internal/event/actors/custom-actor-internal.cpp b/dali/internal/event/actors/custom-actor-internal.cpp new file mode 100644 index 0000000..acfd82c --- /dev/null +++ b/dali/internal/event/actors/custom-actor-internal.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ + +namespace Internal +{ + +CustomActorPtr CustomActor::New(CustomActorImpl& extension) +{ + CustomActorPtr actor(new CustomActor(extension)); + + // Second-phase construction + extension.Initialize(*actor); + actor->Initialize(); + + return actor; +} + +CustomActor::CustomActor(CustomActorImpl& extension) +: Actor( Actor::BASIC ), + mImpl( &extension ) +{ + mDerivedRequiresTouch = extension.RequiresTouchEvents(); + mDerivedRequiresHover = extension.RequiresHoverEvents(); + mDerivedRequiresWheelEvent = extension.RequiresWheelEvents(); + SetRelayoutEnabled( extension.IsRelayoutEnabled() ); +} + +CustomActor::~CustomActor() +{ +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/actors/custom-actor-internal.h b/dali/internal/event/actors/custom-actor-internal.h new file mode 100644 index 0000000..f4bef9f --- /dev/null +++ b/dali/internal/event/actors/custom-actor-internal.h @@ -0,0 +1,273 @@ +#ifndef __DALI_INTERNAL_CUSTOM_ACTOR_H__ +#define __DALI_INTERNAL_CUSTOM_ACTOR_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +class CustomActor : public Actor +{ +public: + + /** + * Create a new custom actor. + * @return A smart-pointer to the newly allocated Actor. + */ + static CustomActorPtr New(CustomActorImpl& extension); + + /** + * Retrieve the custom actor implementation. + * @return The implementation, or an invalid pointer if no implementation was set. + */ + CustomActorImpl& GetImplementation() + { + return *mImpl; + } + + /** + * Retrieve the custom actor implementation. + * @return The implementation, or an invalid pointer if no implementation was set. + */ + const CustomActorImpl& GetImplementation() const + { + return *mImpl; + } + +protected: + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~CustomActor(); + +private: + + /** + * @copydoc Internal::Actor::OnStageConnectionExternal + */ + virtual void OnStageConnectionExternal( int depth ) + { + mImpl->OnStageConnection( depth ); + } + + /** + * @copydoc Internal::Actor::OnStageDisconnectionExternal + */ + virtual void OnStageDisconnectionExternal() + { + mImpl->OnStageDisconnection(); + } + + /** + * @copydoc Internal::Actor::OnChildAdd + */ + virtual void OnChildAdd(Actor& child) + { + Dali::Actor handle(&child); + mImpl->OnChildAdd(handle); + } + + /** + * @copydoc Internal::Actor::OnChildRemove + */ + virtual void OnChildRemove(Actor& child) + { + Dali::Actor handle(&child); + mImpl->OnChildRemove(handle); + } + + /** + * @copydoc Internal::Actor::OnPropertySet + */ + virtual void OnPropertySet( Property::Index index, Property::Value propertyValue ) + { + mImpl->OnPropertySet(index, propertyValue); + } + + /** + * @copydoc Internal::Actor::OnSizeSet + */ + virtual void OnSizeSet(const Vector3& targetSize) + { + mImpl->OnSizeSet(targetSize); + } + + /** + * @copydoc Internal::Actor::OnSizeAnimation + */ + virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize) + { + Dali::Animation animationHandle(&animation); + mImpl->OnSizeAnimation(animationHandle, targetSize); + } + + /** + * @copydoc Internal::Actor::OnTouchEvent + */ + virtual bool OnTouchEvent(const TouchEvent& event) + { + return mImpl->OnTouchEvent(event); + } + + /** + * @copydoc Internal::Actor::OnHoverEvent + */ + virtual bool OnHoverEvent(const HoverEvent& event) + { + return mImpl->OnHoverEvent(event); + } + + /** + * @copydoc Internal::Actor::OnKeyEvent + */ + virtual bool OnKeyEvent(const KeyEvent& event) + { + return mImpl->OnKeyEvent(event); + } + + /** + * @copydoc Internal::Actor::OnWheelEvent + */ + virtual bool OnWheelEvent(const WheelEvent& event) + { + return mImpl->OnWheelEvent(event); + } + + /** + * @copydoc Internal::Actor::OnRelayout + */ + virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ) + { + mImpl->OnRelayout( size, container ); + } + + /** + * @copydoc Internal::Actor::OnSetResizePolicy + */ + virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) + { + mImpl->OnSetResizePolicy( policy, dimension ); + } + + /** + * @copydoc Internal::Actor::GetNaturalSize + */ + virtual Vector3 GetNaturalSize() const + { + return mImpl->GetNaturalSize(); + } + + /** + * @copydoc Internal::Actor::CalculateChildSize + */ + virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension ) + { + return mImpl->CalculateChildSize( child, dimension ); + } + + /** + * @copydoc Internal::Actor::GetHeightForWidth + */ + virtual float GetHeightForWidth( float width ) + { + return mImpl->GetHeightForWidth( width ); + } + + /** + * @copydoc Internal::Actor::GetWidthForHeight + */ + virtual float GetWidthForHeight( float height ) + { + return mImpl->GetWidthForHeight( height ); + } + + /** + * @copydoc Internal::Actor::RelayoutDependentOnChildren + */ + virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) + { + return mImpl->RelayoutDependentOnChildren( dimension ); + } + + /** + * @copydoc Internal::Actor::OnCalculateRelayoutSize + */ + virtual void OnCalculateRelayoutSize( Dimension::Type dimension ) + { + return mImpl->OnCalculateRelayoutSize( dimension ); + } + + /** + * @copydoc Internal::Actor::OnLayoutNegotiated + */ + virtual void OnLayoutNegotiated( float size, Dimension::Type dimension ) + { + return mImpl->OnLayoutNegotiated( size, dimension ); + } + + /** + * Private constructor; see also CustomActor::New() + */ + CustomActor(CustomActorImpl& extension); + + // Undefined + CustomActor(const CustomActor&); + + // Undefined + CustomActor& operator=(const CustomActor& rhs); + +protected: + + CustomActorImplPtr mImpl; +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Internal::CustomActor& GetImpl(Dali::CustomActor& actor) +{ + DALI_ASSERT_ALWAYS( actor && "CustomActor handle is empty" ); + + BaseObject& handle = actor.GetBaseObject(); + + return static_cast(handle); +} + +inline const Internal::CustomActor& GetImpl(const Dali::CustomActor& actor) +{ + DALI_ASSERT_ALWAYS( actor && "CustomActor handle is empty" ); + + const BaseObject& handle = actor.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Dali + +#endif // __DALI_INTERNAL_CUSTOM_ACTOR_H__ diff --git a/dali/internal/event/actors/image-actor-impl.cpp b/dali/internal/event/actors/image-actor-impl.cpp new file mode 100644 index 0000000..5c6b028 --- /dev/null +++ b/dali/internal/event/actors/image-actor-impl.cpp @@ -0,0 +1,573 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include // for strcmp + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace +{ + +// Properties + +// Name Type writable animatable constraint-input enum for index-checking +DALI_PROPERTY_TABLE_BEGIN +DALI_PROPERTY( "pixel-area", RECTANGLE, true, false, true, Dali::ImageActor::Property::PIXEL_AREA ) +DALI_PROPERTY( "style", STRING, true, false, true, Dali::ImageActor::Property::STYLE ) +DALI_PROPERTY( "border", VECTOR4, true, false, true, Dali::ImageActor::Property::BORDER ) +DALI_PROPERTY( "image", MAP, true, false, false, Dali::ImageActor::Property::IMAGE ) +DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX ) + +BaseHandle Create() +{ + return Dali::ImageActor::New(); +} + +TypeRegistration mType( typeid( Dali::ImageActor ), typeid( Dali::Actor ), Create ); + +ImageActor::Style StyleEnum(const std::string &s) +{ + if(s == "STYLE_NINE_PATCH") + { + return Dali::ImageActor::STYLE_NINE_PATCH; + } + else if(s == "STYLE_NINE_PATCH_NO_CENTER") + { + return Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER; + } + else // if(s == "QUAD") + { + return Dali::ImageActor::STYLE_QUAD; + } +} + +std::string StyleString(const ImageActor::Style style) +{ + if(style == Dali::ImageActor::STYLE_NINE_PATCH) + { + return "STYLE_NINE_PATCH"; + } + else if(style == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER) + { + return "STYLE_NINE_PATCH_NO_CENTER"; + } + else // if(s == "QUAD") + { + return "STYLE_QUAD"; + } +} +} + +ImageActorPtr ImageActor::New() +{ + ImageActorPtr actor( new ImageActor ); + + // Second-phase construction of base class + actor->Initialize(); + + // Create the attachment + actor->mImageAttachment = ImageAttachment::New( actor->GetEventThreadServices(), *actor->mNode ); + actor->Attach( *actor->mImageAttachment ); + + return actor; +} + +void ImageActor::OnInitialize() +{ + SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS ); +} + +void ImageActor::SetImage( ImagePtr& image ) +{ + ImagePtr currentImage = mImageAttachment->GetImage(); + // early exit if it's the same image as we already have + if ( currentImage == image ) + { + return; + } + + // NOTE! image might be pointing to NULL, which is fine as in that case app wants to just remove the image + ImagePtr newImage( image ); + // if image is not NULL, check for 9 patch + if( newImage ) + { + // Automatically convert nine-patch images to cropped bitmap + NinePatchImage* ninePatchImage = NinePatchImage::DownCast( image.Get() ); + if( ninePatchImage ) + { + newImage = ninePatchImage->CreateCroppedBufferImage(); + SetStyle( Dali::ImageActor::STYLE_NINE_PATCH ); + SetNinePatchBorder( ninePatchImage->GetStretchBorders(), true ); + } + } + // set the actual image (normal or 9 patch) and natural size based on that + mImageAttachment->SetImage( newImage ); + + RelayoutRequest(); +} + +ImagePtr ImageActor::GetImage() +{ + return mImageAttachment->GetImage(); +} + +void ImageActor::SetPixelArea( const PixelArea& pixelArea ) +{ + mImageAttachment->SetPixelArea( pixelArea ); + + RelayoutRequest(); +} + +const ImageActor::PixelArea& ImageActor::GetPixelArea() const +{ + return mImageAttachment->GetPixelArea(); +} + +bool ImageActor::IsPixelAreaSet() const +{ + return mImageAttachment->IsPixelAreaSet(); +} + +void ImageActor::ClearPixelArea() +{ + mImageAttachment->ClearPixelArea(); + + RelayoutRequest(); +} + +void ImageActor::SetStyle( Style style ) +{ + mImageAttachment->SetStyle( style ); +} + +ImageActor::Style ImageActor::GetStyle() const +{ + return mImageAttachment->GetStyle(); +} + +void ImageActor::SetNinePatchBorder( const Vector4& border, bool inPixels ) +{ + mImageAttachment->SetNinePatchBorder( border, inPixels ); +} + +Vector4 ImageActor::GetNinePatchBorder() const +{ + return mImageAttachment->GetNinePatchBorder(); +} + +ImageAttachment& ImageActor::GetImageAttachment() +{ + return *mImageAttachment; +} + +RenderableAttachment& ImageActor::GetRenderableAttachment() const +{ + DALI_ASSERT_DEBUG( mImageAttachment && "ImageAttachment missing from ImageActor" ); + return *mImageAttachment; +} + +ImageActor::ImageActor() +: Actor( Actor::RENDERABLE ) +{ +} + +ImageActor::~ImageActor() +{ +} + +Vector3 ImageActor::GetNaturalSize() const +{ + Vector2 naturalSize( CalculateNaturalSize() ); + return Vector3( naturalSize.width, naturalSize.height, CalculateSizeZ( naturalSize ) ); +} + +Vector2 ImageActor::CalculateNaturalSize() const +{ + // if no image then natural size is 0 + Vector2 size( 0.0f, 0.0f ); + + ImagePtr image = mImageAttachment->GetImage(); + if( image ) + { + if( IsPixelAreaSet() ) + { + PixelArea area(GetPixelArea()); + size.width = area.width; + size.height = area.height; + } + else + { + size = image->GetNaturalSize(); + } + } + + return size; +} + +void ImageActor::OnStageConnectionInternal() +{ +} + +void ImageActor::OnStageDisconnectionInternal() +{ +} + +unsigned int ImageActor::GetDefaultPropertyCount() const +{ + return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT; +} + +void ImageActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const +{ + Actor::GetDefaultPropertyIndices( indices ); // Actor class properties + + indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT ); + + int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index ) + { + indices.PushBack( index ); + } +} + +bool ImageActor::IsDefaultPropertyWritable( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::IsDefaultPropertyWritable(index); + } + + index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) + { + return DEFAULT_PROPERTY_DETAILS[ index ].writable; + } + + return false; +} + +bool ImageActor::IsDefaultPropertyAnimatable( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::IsDefaultPropertyAnimatable( index ); + } + + index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) + { + return DEFAULT_PROPERTY_DETAILS[ index ].animatable; + } + + return false; +} + +bool ImageActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::IsDefaultPropertyAConstraintInput( index ); + } + + index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) + { + return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput; + } + + return false; +} + +Property::Type ImageActor::GetDefaultPropertyType( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::GetDefaultPropertyType( index ); + } + + index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) + { + return DEFAULT_PROPERTY_DETAILS[index].type; + } + + // index out-of-bounds + return Property::NONE; +} + +const char* ImageActor::GetDefaultPropertyName( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT) + { + return Actor::GetDefaultPropertyName(index); + } + + index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) + { + return DEFAULT_PROPERTY_DETAILS[index].name; + } + + // index out-of-bounds + return NULL; +} + +Property::Index ImageActor::GetDefaultPropertyIndex(const std::string& name) const +{ + Property::Index index = Property::INVALID_INDEX; + + // Look for name in default properties + for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) + { + const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ]; + if( 0 == strcmp( name.c_str(), property->name ) ) // Don't want to convert rhs to string + { + index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + break; + } + } + + // If not found, check in base class + if( Property::INVALID_INDEX == index ) + { + index = Actor::GetDefaultPropertyIndex( name ); + } + return index; +} + +void ImageActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue ) +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + Actor::SetDefaultProperty( index, propertyValue ); + } + else + { + switch(index) + { + case Dali::ImageActor::Property::PIXEL_AREA: + { + SetPixelArea(propertyValue.Get >()); + break; + } + case Dali::ImageActor::Property::STYLE: + { + SetStyle( StyleEnum( propertyValue.Get() ) ); + break; + } + case Dali::ImageActor::Property::BORDER: + { + SetNinePatchBorder( propertyValue.Get(), true /*in pixels*/ ); + break; + } + case Dali::ImageActor::Property::IMAGE: + { + Dali::Image img = Scripting::NewImage( propertyValue ); + if(img) + { + ImagePtr image( &GetImplementation(img) ); + SetImage( image ); + } + else + { + DALI_LOG_WARNING("Cannot create image from property value\n"); + } + break; + } + default: + { + DALI_LOG_WARNING("Unknown property (%d)\n", index); + break; + } + } // switch(index) + + } // else +} + +Property::Value ImageActor::GetDefaultProperty( Property::Index index ) const +{ + Property::Value ret; + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + ret = Actor::GetDefaultProperty( index ); + } + else + { + switch( index ) + { + case Dali::ImageActor::Property::PIXEL_AREA: + { + Rect r = GetPixelArea(); + ret = r; + break; + } + case Dali::ImageActor::Property::STYLE: + { + ret = StyleString( GetStyle() ); + break; + } + case Dali::ImageActor::Property::BORDER: + { + ret = GetNinePatchBorder(); + break; + } + case Dali::ImageActor::Property::IMAGE: + { + Property::Map map; + Scripting::CreatePropertyMap( Dali::Image( mImageAttachment->GetImage().Get() ), map ); + ret = Property::Value( map ); + break; + } + default: + { + DALI_LOG_WARNING( "Unknown property (%d)\n", index ); + break; + } + } // switch(index) + } + + return ret; +} + + +void ImageActor::SetSortModifier(float modifier) +{ + mImageAttachment->SetSortModifier( modifier ); +} + +float ImageActor::GetSortModifier() const +{ + return mImageAttachment->GetSortModifier(); +} + +void ImageActor::SetDepthIndex( int depthIndex ) +{ + mImageAttachment->SetSortModifier( depthIndex ); +} + +int ImageActor::GetDepthIndex() const +{ + return static_cast< int >( mImageAttachment->GetSortModifier() ); +} + +void ImageActor::SetCullFace(CullFaceMode mode) +{ + mImageAttachment->SetCullFace( mode ); +} + +CullFaceMode ImageActor::GetCullFace() const +{ + return mImageAttachment->GetCullFace(); +} + +void ImageActor::SetBlendMode( BlendingMode::Type mode ) +{ + mImageAttachment->SetBlendMode( mode ); +} + +BlendingMode::Type ImageActor::GetBlendMode() const +{ + return mImageAttachment->GetBlendMode(); +} + +void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba ) +{ + mImageAttachment->SetBlendFunc( srcFactorRgba, destFactorRgba, srcFactorRgba, destFactorRgba ); +} + +void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgb, BlendingFactor::Type destFactorRgb, + BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha ) +{ + mImageAttachment->SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha ); +} + +void ImageActor::GetBlendFunc( BlendingFactor::Type& srcFactorRgb, BlendingFactor::Type& destFactorRgb, + BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const +{ + mImageAttachment->GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha ); +} + +void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgba ) +{ + mImageAttachment->SetBlendEquation( equationRgba, equationRgba ); +} + +void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha ) +{ + mImageAttachment->SetBlendEquation( equationRgb, equationAlpha ); +} + +void ImageActor::GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const +{ + mImageAttachment->GetBlendEquation( equationRgb, equationAlpha ); +} + +void ImageActor::SetBlendColor( const Vector4& color ) +{ + mImageAttachment->SetBlendColor( color ); +} + +const Vector4& ImageActor::GetBlendColor() const +{ + return mImageAttachment->GetBlendColor(); +} + +void ImageActor::SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter ) +{ + mImageAttachment->SetFilterMode( minFilter, magFilter ); +} + +void ImageActor::GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const +{ + return mImageAttachment->GetFilterMode( minFilter, magFilter ); +} + +void ImageActor::SetShaderEffect(ShaderEffect& effect) +{ + mImageAttachment->SetShaderEffect( effect ); +} + +ShaderEffectPtr ImageActor::GetShaderEffect() const +{ + return mImageAttachment->GetShaderEffect(); +} + +void ImageActor::RemoveShaderEffect() +{ + return mImageAttachment->RemoveShaderEffect(); +} + + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/actors/image-actor-impl.h b/dali/internal/event/actors/image-actor-impl.h new file mode 100644 index 0000000..785216e --- /dev/null +++ b/dali/internal/event/actors/image-actor-impl.h @@ -0,0 +1,364 @@ +#ifndef __DALI_INTERNAL_IMAGE_ACTOR_H__ +#define __DALI_INTERNAL_IMAGE_ACTOR_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +class Image; + +/** + * An actor which displays an Image object. + * + * This handles image fade-in if required, waiting for the image to load. + * + * If a new image is set on the actor, then this ensures that the old image + * is displayed until the new image is ready to render to prevent flashing + * to the actor color. This will also happen if the image is reloaded. + * + * This is achieved by using two connector objects to Image: mImageNext and + * mImageAttachment's member object. The first one points to the Image object that is going to + * be displayed next, the second one to the Image that is currently being displayed. + */ +class ImageActor : public Actor +{ +public: + + typedef Dali::ImageActor::Style Style; + typedef Dali::ImageActor::PixelArea PixelArea; + + /** + * @brief Create an image actor instance. + * @return A smart-pointer to a newly allocated image actor. + */ + static ImageActorPtr New(); + + /** + * @copydoc Dali::Internal::Actor::OnInitialize + */ + void OnInitialize() ; + + /** + * @see Dali::ImageActor::SetImage() + * @param[in] ImagePtr reference to the image object to display. Reference to avoid unnecessary increment/decrement reference. + */ + void SetImage( ImagePtr& image ); + + /** + * Retrieve the image rendered by the actor's attachment. + * @return smart pointer to the image or an empty one if no image is assigned + */ + ImagePtr GetImage(); + + /** + * @copydoc Dali::ImageActor::SetPixelArea() + */ + void SetPixelArea( const PixelArea& pixelArea ); + + /** + * @copydoc Dali::ImageActor::GetPixelArea() + */ + const PixelArea& GetPixelArea() const; + + /** + * @copydoc Dali::ImageActor::IsPixelAreaSet() + */ + bool IsPixelAreaSet() const; + + /** + * @copydoc Dali::ImageActor::ClearPixelArea() + */ + void ClearPixelArea(); + + /** + * @copydoc Dali::ImageActor::SetStyle() + */ + void SetStyle( Style style ); + + /** + * @copydoc Dali::ImageActor::GetStyle() + */ + Style GetStyle() const; + + /** + * @copydoc Dali::ImageActor::SetNinePatchBorder + */ + void SetNinePatchBorder( const Vector4& border, bool inPixels = false ); + + /** + * @copydoc Dali::ImageActor::GetNinePatchBorder + */ + Vector4 GetNinePatchBorder() const; + + /** + * Retrieve the attachment which renders the image. + * @return The attachment. + */ + ImageAttachment& GetImageAttachment(); + + + /** + * @copydoc Dali::RenderableActor::SetSortModifier() + */ + void SetSortModifier(float modifier); + + /** + * @copydoc Dali::RenderableActor::GetSortModifier() + */ + float GetSortModifier() const; + + /** + * @copydoc Dali::RenderableActor::SetDepthIndex() + */ + void SetDepthIndex( int depthIndex ); + + /** + * @copydoc Dali::RenderableActor::GetDepthIndex() + */ + int GetDepthIndex() const; + + /** + * @copydoc Dali::RenderableActor::SetCullFace() + */ + void SetCullFace(CullFaceMode mode); + + /** + * @copydoc Dali::RenderableActor::GetCullFace() + */ + CullFaceMode GetCullFace() const; + + /** + * @copydoc Dali::RenderableActor::SetBlendMode() + */ + void SetBlendMode( BlendingMode::Type mode ); + + /** + * @copydoc Dali::RenderableActor::GetBlendMode() + */ + BlendingMode::Type GetBlendMode() const; + + /** + * @copydoc Dali::RenderableActor::SetBlendFunc() + */ + void SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba ); + + /** + * @copydoc Dali::RenderableActor::SetBlendFunc() + */ + void SetBlendFunc( BlendingFactor::Type srcFactorRgb, BlendingFactor::Type destFactorRgb, + BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha ); + + /** + * @copydoc Dali::RenderableActor::GetBlendFunc() + */ + void GetBlendFunc( BlendingFactor::Type& srcFactorRgb, BlendingFactor::Type& destFactorRgb, + BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const; + + /** + * @copydoc Dali::RenderableActor::SetBlendEquation() + */ + void SetBlendEquation( BlendingEquation::Type equationRgba ); + + /** + * @copydoc Dali::RenderableActor::SetBlendEquation() + */ + void SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha ); + + /** + * @copydoc Dali::RenderableActor::GetBlendEquation() + */ + void GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const; + + /** + * @copydoc Dali::RenderableActor::SetBlendColor() + */ + void SetBlendColor( const Vector4& color ); + + /** + * @copydoc Dali::RenderableActor::GetBlendColor() + */ + const Vector4& GetBlendColor() const; + + /** + * @copydoc Dali::RenderableActor::SetFilterMode() + */ + void SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter ); + + /** + * @copydoc Dali::RenderableActor::GetFilterMode() + */ + void GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const; + +public: + /** + * @copydoc Actor::SetShaderEffect + */ + virtual void SetShaderEffect(ShaderEffect& effect); + + /** + * @copydoc Actor::GetShaderEffect + */ + virtual ShaderEffectPtr GetShaderEffect() const; + + /** + * @copydoc Actor::RemoveShaderEffect + */ + virtual void RemoveShaderEffect(); + +public: // Default property extensions from Object + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyCount() + */ + virtual unsigned int GetDefaultPropertyCount() const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices() + */ + virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyName() + */ + virtual const char* GetDefaultPropertyName(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex() + */ + virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable() + */ + virtual bool IsDefaultPropertyWritable(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable() + */ + virtual bool IsDefaultPropertyAnimatable(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput() + */ + virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyType() + */ + virtual Property::Type GetDefaultPropertyType(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::SetDefaultProperty() + */ + virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue); + + /** + * @copydoc Dali::Internal::Object::GetDefaultProperty() + */ + virtual Property::Value GetDefaultProperty( Property::Index index ) const; + +public: // From Actor + + /** + * @copydoc Dali::Actor::GetNaturalSize() + */ + virtual Vector3 GetNaturalSize() const; + +private: // From RenderableActor + + /** + * @copydoc RenderableActor::GetRenderableAttachment + */ + virtual RenderableAttachment& GetRenderableAttachment() const; + +protected: + + /** + * Protected constructor; see also ImageActor::New() + */ + ImageActor(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~ImageActor(); + +private: + + /** + * Calculate the natural size of this image actor + * + * @return Return the natural size as a Vector2 + */ + Vector2 CalculateNaturalSize() const; + + /** + * From Actor; used to trigger fade-in animations. + */ + virtual void OnStageConnectionInternal(); + + /** + * From Actor; used to notify Image. + */ + virtual void OnStageDisconnectionInternal(); + +private: + + ImageAttachmentPtr mImageAttachment; ///< Used to display the image (holds a pointer to currently showed Image) + +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Internal::ImageActor& GetImplementation(Dali::ImageActor& image) +{ + DALI_ASSERT_ALWAYS(image && "Image handle is empty"); + + BaseObject& handle = image.GetBaseObject(); + + return static_cast(handle); +} + +inline const Internal::ImageActor& GetImplementation(const Dali::ImageActor& image) +{ + DALI_ASSERT_ALWAYS(image && "Image handle is empty"); + + const BaseObject& handle = image.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Dali + +#endif // __DALI_INTERNAL_IMAGE_ACTOR_H__ diff --git a/dali/internal/event/actors/layer-impl.cpp b/dali/internal/event/actors/layer-impl.cpp new file mode 100644 index 0000000..f70b3e3 --- /dev/null +++ b/dali/internal/event/actors/layer-impl.cpp @@ -0,0 +1,568 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +using Dali::Internal::SceneGraph::UpdateManager; + +namespace Dali +{ + +namespace +{ +typedef Dali::Layer::Behavior Behavior; + +DALI_ENUM_TO_STRING_TABLE_BEGIN( Behavior ) +DALI_ENUM_TO_STRING( Dali::Layer::LAYER_2D ) +DALI_ENUM_TO_STRING( Dali::Layer::LAYER_3D ) +DALI_ENUM_TO_STRING_TABLE_END( Behavior ) +} // namespace + +namespace Internal +{ + +namespace +{ + +// Properties + +// Name Type writable animatable constraint-input enum for index-checking +DALI_PROPERTY_TABLE_BEGIN +DALI_PROPERTY( "clipping-enable", BOOLEAN, true, false, true, Dali::Layer::Property::CLIPPING_ENABLE ) +DALI_PROPERTY( "clipping-box", RECTANGLE, true, false, true, Dali::Layer::Property::CLIPPING_BOX ) +DALI_PROPERTY( "behavior", STRING, true, false, false, Dali::Layer::Property::BEHAVIOR ) +DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX ) + +// Actions + +const char* const ACTION_RAISE = "raise"; +const char* const ACTION_LOWER = "lower"; +const char* const ACTION_RAISE_TO_TOP = "raise-to-top"; +const char* const ACTION_LOWER_TO_BOTTOM = "lower-to-bottom"; + +BaseHandle Create() +{ + return Dali::Layer::New(); +} + +TypeRegistration mType( typeid( Dali::Layer ), typeid( Dali::Actor ), Create ); + +TypeAction a1( mType, ACTION_RAISE, &Layer::DoAction ); +TypeAction a2( mType, ACTION_LOWER, &Layer::DoAction ); +TypeAction a3( mType, ACTION_RAISE_TO_TOP, &Layer::DoAction ); +TypeAction a4( mType, ACTION_LOWER_TO_BOTTOM, &Layer::DoAction ); + +} // unnamed namespace + + +LayerPtr Layer::New() +{ + LayerPtr layer( new Layer( Actor::LAYER ) ); + + // Second-phase construction + layer->Initialize(); + + return layer; +} + +LayerPtr Layer::NewRoot( LayerList& layerList, UpdateManager& manager, bool systemLevel ) +{ + LayerPtr root( new Layer( Actor::ROOT_LAYER ) ); + + // Second-phase construction + SceneGraph::Layer* layer = static_cast( root->CreateNode() ); + InstallRootMessage( manager, *layer, systemLevel ); // Transfer ownership to scene-graph + + // Keep a raw pointer to the layer node. + root->mNode = layer; + + // root actor is immediately considered to be on-stage + root->mIsOnStage = true; + + // The root actor will not emit a stage connection signal so set the signalled flag here as well + root->mOnStageSignalled = true; + + // layer-list must be set for the root layer + root->mLayerList = &layerList; + layerList.RegisterLayer( *root ); + + return root; +} + +Layer::Layer( Actor::DerivedType type ) +: Actor( type ), + mLayerList(NULL), + mClippingBox(0,0,0,0), + mSortFunction(Layer::ZValue), + mBehavior(Dali::Layer::LAYER_2D), + mIsClipping(false), + mDepthTestDisabled(false), + mTouchConsumed(false), + mHoverConsumed(false) +{ +} + +void Layer::OnInitialize() +{ +} + +Layer::~Layer() +{ +} + +unsigned int Layer::GetDepth() const +{ + return mLayerList ? mLayerList->GetDepth( this ) : 0u; +} + +void Layer::Raise() +{ + if ( mLayerList ) + { + mLayerList->RaiseLayer(*this); + } +} + +void Layer::Lower() +{ + if ( mLayerList ) + { + mLayerList->LowerLayer(*this); + } +} + +void Layer::RaiseAbove( const Internal::Layer& target ) +{ + // cannot raise above ourself, both have to be on stage + if( ( this != &target ) && OnStage() && target.OnStage() ) + { + // get parameters depth + const unsigned int targetDepth = target.GetDepth(); + if( GetDepth() < targetDepth ) + { + MoveAbove( target ); + } + } +} + +void Layer::LowerBelow( const Internal::Layer& target ) +{ + // cannot lower below ourself, both have to be on stage + if( ( this != &target ) && OnStage() && target.OnStage() ) + { + // get parameters depth + const unsigned int targetDepth = target.GetDepth(); + if( GetDepth() > targetDepth ) + { + MoveBelow( target ); + } + } +} + +void Layer::RaiseToTop() +{ + if ( mLayerList ) + { + mLayerList->RaiseLayerToTop(*this); + } +} + +void Layer::LowerToBottom() +{ + if ( mLayerList ) + { + mLayerList->LowerLayerToBottom(*this); + } +} + +void Layer::MoveAbove( const Internal::Layer& target ) +{ + // cannot raise above ourself, both have to be on stage + if( ( this != &target ) && mLayerList && target.OnStage() ) + { + mLayerList->MoveLayerAbove(*this, target ); + } +} + +void Layer::MoveBelow( const Internal::Layer& target ) +{ + // cannot lower below ourself, both have to be on stage + if( ( this != &target ) && mLayerList && target.OnStage() ) + { + mLayerList->MoveLayerBelow(*this, target ); + } +} + +void Layer::SetBehavior( Dali::Layer::Behavior behavior ) +{ + mBehavior = behavior; + + // notify update side object + SetBehaviorMessage( GetEventThreadServices(), GetSceneLayerOnStage(), behavior ); +} + +void Layer::SetClipping(bool enabled) +{ + if (enabled != mIsClipping) + { + mIsClipping = enabled; + + // layerNode is being used in a separate thread; queue a message to set the value + SetClippingMessage( GetEventThreadServices(), GetSceneLayerOnStage(), mIsClipping ); + } +} + +void Layer::SetClippingBox(int x, int y, int width, int height) +{ + if( ( x != mClippingBox.x ) || + ( y != mClippingBox.y ) || + ( width != mClippingBox.width ) || + ( height != mClippingBox.height ) ) + { + // Clipping box is not animatable; this is the most up-to-date value + mClippingBox.Set(x, y, width, height); + + // Convert mClippingBox to GL based coordinates (from bottom-left) + ClippingBox clippingBox( mClippingBox ); + + StagePtr stage = Stage::GetCurrent(); + if( stage ) + { + clippingBox.y = stage->GetSize().height - clippingBox.y - clippingBox.height; + + // layerNode is being used in a separate thread; queue a message to set the value + SetClippingBoxMessage( GetEventThreadServices(), GetSceneLayerOnStage(), clippingBox ); + } + } +} + +void Layer::SetDepthTestDisabled( bool disable ) +{ + if( disable != mDepthTestDisabled ) + { + mDepthTestDisabled = disable; + + // Send message ..... + // layerNode is being used in a separate thread; queue a message to set the value + SetDepthTestDisabledMessage( GetEventThreadServices(), GetSceneLayerOnStage(), mDepthTestDisabled ); + } +} + +bool Layer::IsDepthTestDisabled() const +{ + return mDepthTestDisabled || (mBehavior == Dali::Layer::LAYER_2D); +} + +void Layer::SetSortFunction(Dali::Layer::SortFunctionType function) +{ + if( function != mSortFunction ) + { + mSortFunction = function; + + // layerNode is being used in a separate thread; queue a message to set the value + SetSortFunctionMessage( GetEventThreadServices(), GetSceneLayerOnStage(), mSortFunction ); + } +} + +void Layer::SetTouchConsumed( bool consume ) +{ + mTouchConsumed = consume; +} + +bool Layer::IsTouchConsumed() const +{ + return mTouchConsumed; +} + +void Layer::SetHoverConsumed( bool consume ) +{ + mHoverConsumed = consume; +} + +bool Layer::IsHoverConsumed() const +{ + return mHoverConsumed; +} + +SceneGraph::Node* Layer::CreateNode() const +{ + return SceneGraph::Layer::New(); +} + +void Layer::OnStageConnectionInternal() +{ + if ( !mIsRoot ) + { + DALI_ASSERT_DEBUG( NULL == mLayerList ); + + // Find the ordered layer-list + // This is different for Layers added via Integration::GetSystemOverlay() + for ( Actor* parent = mParent; parent != NULL; parent = parent->GetParent() ) + { + if( parent->IsLayer() ) + { + Layer* parentLayer = static_cast< Layer* >( parent ); // cheaper than dynamic_cast + mLayerList = parentLayer->mLayerList; + } + } + } + + DALI_ASSERT_DEBUG( NULL != mLayerList ); + mLayerList->RegisterLayer( *this ); +} + +void Layer::OnStageDisconnectionInternal() +{ + mLayerList->UnregisterLayer(*this); + + // mLayerList is only valid when on-stage + mLayerList = NULL; +} + +const SceneGraph::Layer& Layer::GetSceneLayerOnStage() const +{ + DALI_ASSERT_DEBUG( mNode != NULL ); + return dynamic_cast< const SceneGraph::Layer& >( *mNode ); +} + +unsigned int Layer::GetDefaultPropertyCount() const +{ + return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT; +} + +void Layer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const +{ + Actor::GetDefaultPropertyIndices( indices ); // Actor class properties + indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT ); + + int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index ) + { + indices.PushBack( index ); + } +} + +bool Layer::IsDefaultPropertyWritable( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::IsDefaultPropertyWritable( index ); + } + + return DEFAULT_PROPERTY_DETAILS[ index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX ].writable; +} + +bool Layer::IsDefaultPropertyAnimatable( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::IsDefaultPropertyAnimatable( index ); + } + + return DEFAULT_PROPERTY_DETAILS[ index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX ].animatable; +} + +bool Layer::IsDefaultPropertyAConstraintInput( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::IsDefaultPropertyAConstraintInput( index ); + } + + return DEFAULT_PROPERTY_DETAILS[ index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX ].constraintInput; +} + +Property::Type Layer::GetDefaultPropertyType( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::GetDefaultPropertyType( index ); + } + + index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + + if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) + { + return DEFAULT_PROPERTY_DETAILS[index].type; + } + + // index out-of-bounds + return Property::NONE; +} + +const char* Layer::GetDefaultPropertyName( Property::Index index ) const +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + return Actor::GetDefaultPropertyName( index ); + } + + index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) + { + return DEFAULT_PROPERTY_DETAILS[index].name; + } + + return NULL; +} + +Property::Index Layer::GetDefaultPropertyIndex(const std::string& name) const +{ + Property::Index index = Property::INVALID_INDEX; + + // Look for name in current class' default properties + for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) + { + const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[i]; + if( 0 == name.compare( property->name ) ) // dont want to convert rhs to string + { + index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX; + break; + } + } + if( Property::INVALID_INDEX == index ) + { + // If not found, check in base class + index = Actor::GetDefaultPropertyIndex( name ); + } + + return index; +} + +void Layer::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue ) +{ + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + Actor::SetDefaultProperty( index, propertyValue ); + } + else + { + switch( index ) + { + case Dali::Layer::Property::CLIPPING_ENABLE: + { + SetClipping( propertyValue.Get() ); + break; + } + case Dali::Layer::Property::CLIPPING_BOX: + { + Rect clippingBox( propertyValue.Get >() ); + SetClippingBox( clippingBox.x, clippingBox.y, clippingBox.width, clippingBox.height ); + break; + } + case Dali::Layer::Property::BEHAVIOR: + { + Behavior behavior(Dali::Layer::LAYER_2D); + if( Scripting::GetEnumeration< Behavior >( propertyValue.Get< std::string >().c_str(), BehaviorTable, BehaviorTableCount, behavior ) ) + { + SetBehavior( behavior ); + } + break; + } + default: + { + DALI_LOG_WARNING( "Unknown property (%d)\n", index ); + break; + } + } // switch(index) + + } // else +} + +Property::Value Layer::GetDefaultProperty( Property::Index index ) const +{ + Property::Value ret; + if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) + { + ret = Actor::GetDefaultProperty( index ); + } + else + { + switch( index ) + { + case Dali::Layer::Property::CLIPPING_ENABLE: + { + ret = mIsClipping; + break; + } + case Dali::Layer::Property::CLIPPING_BOX: + { + ret = mClippingBox; + break; + } + case Dali::Layer::Property::BEHAVIOR: + { + ret = Scripting::GetLinearEnumerationName< Behavior >( GetBehavior(), BehaviorTable, BehaviorTableCount ); + break; + } + default: + { + DALI_LOG_WARNING( "Unknown property (%d)\n", index ); + break; + } + } // switch(index) + } + + return ret; +} + +bool Layer::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /*attributes*/ ) +{ + bool done = false; + Layer* layer = dynamic_cast( object ); + + if( layer ) + { + if( 0 == actionName.compare( ACTION_RAISE ) ) + { + layer->Raise(); + done = true; + } + else if( 0 == actionName.compare( ACTION_LOWER ) ) + { + layer->Lower(); + done = true; + } + else if( 0 == actionName.compare( ACTION_RAISE_TO_TOP ) ) + { + layer->RaiseToTop(); + done = true; + } + else if( 0 == actionName.compare( ACTION_LOWER_TO_BOTTOM ) ) + { + layer->LowerToBottom(); + done = true; + } + } + + return done; +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/actors/layer-impl.h b/dali/internal/event/actors/layer-impl.h new file mode 100644 index 0000000..0e97f3a --- /dev/null +++ b/dali/internal/event/actors/layer-impl.h @@ -0,0 +1,338 @@ +#ifndef __DALI_INTERNAL_LAYER_H__ +#define __DALI_INTERNAL_LAYER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +class LayerList; + +namespace SceneGraph +{ +class UpdateManager; +class Layer; +} + +typedef Dali::ClippingBox ClippingBox; + +class Layer : public Actor +{ +public: + + /** + * @copydoc Dali::Layer::ZValue(const Vector3&, float) + * + * This is the default sorting function. + * It is useful for 2D user interfaces, and it's used to sort translucent renderers. + * + * Only the Z signed distance from the camera is considererd, lower values will be drawn on top. + * + * @param[in] position position of actor in view space + * @return depth + */ + static float ZValue(const Vector3& position) + { + // inlined so we avoid a function call when sorting renderers + return position.z; + } + + /** + * Create a new Layer. + * @return A smart-pointer to the newly allocated Layer. + */ + static LayerPtr New(); + + /** + * Create a new root layer; this is typically owned by the stage. + * @param[in] layerList The layer will be added to this ordered list. + * @param[in] manager The update manager to install a root node with. + * @param[in] systemLevel True if using the SystemOverlay API; see Integration::GetSystemOverlay() for more details. + * @return A smart-pointer to the newly allocated Actor. + */ + static LayerPtr NewRoot( LayerList& layerList, SceneGraph::UpdateManager& manager, bool systemLevel ); + + /** + * @copydoc Dali::Internal::Actor::OnInitialize + */ + void OnInitialize(); + + /** + * Query the current depth of the layer + */ + unsigned int GetDepth() const; + + /** + * @copydoc Dali::Layer::Raise + */ + void Raise(); + + /** + * @copydoc Dali::Layer::Lower + */ + void Lower(); + + /** + * @copydoc Dali::Layer::RaiseAbove + */ + void RaiseAbove( const Internal::Layer& target ); + + /** + * @copydoc Dali::Layer::LowerBelow + */ + void LowerBelow( const Internal::Layer& target ); + + /** + * @copydoc Dali::Layer::RaiseToTop + */ + void RaiseToTop(); + + /** + * @copydoc Dali::Layer::LowerToBottom + */ + void LowerToBottom(); + + /** + * @copydoc Dali::Layer::MoveAbove + */ + void MoveAbove( const Internal::Layer& target ); + + /** + * @copydoc Dali::Layer::MoveAbove + */ + void MoveBelow( const Internal::Layer& target ); + + /** + * @copydoc Dali::Layer::SetClipping() + */ + void SetClipping(bool enabled); + + /** + * @copydoc Dali::Layer::IsClipping() + */ + bool IsClipping() const + { + return mIsClipping; // Actor-side has most up-to-date value + } + + /** + * @copydoc Dali::Layer::SetClippingBox() + */ + void SetClippingBox(int x, int y, int width, int height); + + /** + * @copydoc Dali::Layer::GetClippingBox() + */ + const Dali::ClippingBox& GetClippingBox() const + { + return mClippingBox; // Actor-side has most up-to-date value + } + + /** + * @copydoc Dali::Layer::SetBehavior() + */ + void SetBehavior( Dali::Layer::Behavior behavior ); + + /** + * @copydoc Dali::Layer::GetBehavior() + */ + Dali::Layer::Behavior GetBehavior() const + { + return mBehavior; + } + + /** + * @copydoc Dali::Layer::SetDepthTestDisabled() + */ + void SetDepthTestDisabled( bool disable ); + + /** + * @copydoc Dali::Layer::IsDepthTestDisabled() + */ + bool IsDepthTestDisabled() const; + + /** + * @copydoc Dali::Layer::SetSortFunction() + */ + void SetSortFunction(Dali::Layer::SortFunctionType function); + + /** + * @copydoc Dali::Layer::SetTouchConsumed() + */ + void SetTouchConsumed( bool consume ); + + /** + * @copydoc Dali::Layer::IsTouchConsumed() + */ + bool IsTouchConsumed() const; + + /** + * @copydoc Dali::Layer::SetHoverConsumed() + */ + void SetHoverConsumed( bool consume ); + + /** + * @copydoc Dali::Layer::IsHoverConsumed() + */ + bool IsHoverConsumed() const; + + /** + * Helper function to get the scene object. + * This should only be called by Stage + * @return the scene object for the layer. + */ + const SceneGraph::Layer& GetSceneLayerOnStage() const; + + /** + * @copydoc Dali::Internal::Actor::DoAction() + */ + static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes); + +public: // Default property extensions from Object + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyCount() + */ + virtual unsigned int GetDefaultPropertyCount() const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices() + */ + virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyName() + */ + virtual const char* GetDefaultPropertyName(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex() + */ + virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable() + */ + virtual bool IsDefaultPropertyWritable(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable() + */ + virtual bool IsDefaultPropertyAnimatable(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput() + */ + virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyType() + */ + virtual Property::Type GetDefaultPropertyType(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::SetDefaultProperty() + */ + virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue); + + /** + * @copydoc Dali::Internal::Object::GetDefaultProperty() + */ + virtual Property::Value GetDefaultProperty( Property::Index index ) const; + +protected: + + /** + * Construct a new layer. + * @param[in] type Either Actor::LAYER or Actor::ROOT_LAYER if this is the root actor. + */ + Layer( Actor::DerivedType type ); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~Layer(); + +private: // From Actor + + /** + * From Actor; create a node to represent the layer in the scene-graph. + * @return A newly allocated layer node. + */ + virtual SceneGraph::Node* CreateNode() const; + + /** + * From Actor. + */ + virtual void OnStageConnectionInternal(); + + /** + * From Actor. + */ + virtual void OnStageDisconnectionInternal(); + +private: + + LayerList* mLayerList; ///< Only valid when layer is on-stage + + // These properties not animatable; the actor side has the most up-to-date values + ClippingBox mClippingBox; ///< The clipping box, in window coordinates + Dali::Layer::SortFunctionType mSortFunction; ///< Used to sort semi-transparent geometry + + Dali::Layer::Behavior mBehavior; ///< Behavior of the layer + + bool mIsClipping:1; ///< True when clipping is enabled + bool mDepthTestDisabled:1; ///< Whether depth test is disabled. + bool mTouchConsumed:1; ///< Whether we should consume touch (including gesture). + bool mHoverConsumed:1; ///< Whether we should consume hover. + +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Internal::Layer& GetImplementation(Dali::Layer& layer) +{ + DALI_ASSERT_ALWAYS(layer && "Layer handle is empty"); + + BaseObject& handle = layer.GetBaseObject(); + + return static_cast(handle); +} + +inline const Internal::Layer& GetImplementation(const Dali::Layer& layer) +{ + DALI_ASSERT_ALWAYS(layer && "Layer handle is empty"); + + const BaseObject& handle = layer.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Dali + + +#endif //__DALI_INTERNAL_LAYER_H__ diff --git a/dali/internal/event/actors/layer-list.cpp b/dali/internal/event/actors/layer-list.cpp new file mode 100644 index 0000000..82be760 --- /dev/null +++ b/dali/internal/event/actors/layer-list.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include // for std::swap + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace // unnamed namespace +{ + +typedef std::vector LayerContainer; +typedef LayerContainer::iterator LayerIter; +typedef LayerContainer::reverse_iterator ReverseLayerIter; + +/** + * A private helper template to return an iterator to the layer passed in. + * @param[in] first position to start searching from + * @param[in] last position to search to + * @param[in] layer to search for + * @return iterator to layer if found + */ +template InputIterator Find( InputIterator first, InputIterator last, const Layer& layer ) +{ + for( ; first != last ; ++first ) + { + if( *first == &layer ) + { + break; + } + } + return first; +} + +} // unnamed namespace + +LayerList* LayerList::New( SceneGraph::UpdateManager& updateManager, bool systemLevel ) +{ + return new LayerList( updateManager, systemLevel ); +} + +LayerList::~LayerList() +{ +} + +unsigned int LayerList::GetLayerCount() const +{ + return mLayers.size(); +} + +Layer* LayerList::GetLayer( unsigned int depth ) const +{ + DALI_ASSERT_ALWAYS( depth < mLayers.size() ); + + return mLayers[ depth ]; +} + +unsigned int LayerList::GetDepth( const Layer* layer ) const +{ + for( unsigned int count = 0; count < mLayers.size(); ++count ) + { + if( layer == mLayers[ count ] ) + { + return count; + } + } + return 0; +} + +void LayerList::RegisterLayer(Layer& layer) +{ + DALI_ASSERT_DEBUG( mLayers.end() == Find( mLayers.begin(), mLayers.end(), layer) ); + mLayers.push_back(&layer); + + SetLayerDepths(); +} + +void LayerList::UnregisterLayer(Layer& layer) +{ + // Find the layer... + LayerIter iter = Find( mLayers.begin(), mLayers.end(), layer); + DALI_ASSERT_DEBUG(iter != mLayers.end()); + + // ...and remove it + mLayers.erase(iter); + + SetLayerDepths(); +} + +void LayerList::RaiseLayer(Layer& raiseLayer) +{ + LayerIter iter = Find( mLayers.begin(), mLayers.end(), raiseLayer); + + if (iter != mLayers.end() && + iter+1 != mLayers.end()) + { + LayerIter nextIter = iter+1; + + // Swap the pointers + std::swap(*iter, *nextIter); + + SetLayerDepths(); + } +} + +void LayerList::LowerLayer(Layer& lowerLayer) +{ + ReverseLayerIter iter = Find( mLayers.rbegin(), mLayers.rend(), lowerLayer); + + if (iter != mLayers.rend() && + iter+1 != mLayers.rend()) + { + ReverseLayerIter nextIter = iter+1; + + // Swap the pointers + std::swap(*iter, *nextIter); + + SetLayerDepths(); + } +} + +void LayerList::RaiseLayerToTop( const Layer& layer ) +{ + LayerIter iter = Find( mLayers.begin(), mLayers.end(), layer); + + if (iter != mLayers.end() && + iter+1 != mLayers.end()) + { + Layer* raised = *iter; + + copy(iter+1, mLayers.end(), iter); + mLayers.back() = raised; + + SetLayerDepths(); + } +} + +void LayerList::LowerLayerToBottom( const Layer& layer ) +{ + ReverseLayerIter iter = Find( mLayers.rbegin(), mLayers.rend(), layer); + + if (iter != mLayers.rend() && + iter+1 != mLayers.rend()) + { + Layer* lowered = *iter; + + copy(iter+1, mLayers.rend(), iter); + mLayers.front() = lowered; + + SetLayerDepths(); + } +} + +void LayerList::MoveLayerAbove( const Layer& layer, const Layer& target ) +{ + // check if it already is + if( layer.GetDepth() == ( target.GetDepth() + 1 ) ) + { + return; + } + + // find the layer to move + LayerIter iter = Find( mLayers.begin(), mLayers.end(), layer); + + if( iter != mLayers.end() ) + { + Layer* moved = *iter; + mLayers.erase( iter ); + // find target + LayerIter iterT = Find( mLayers.begin(), mLayers.end(), target); + // if target is not found there's a programming error somewhere + DALI_ASSERT_DEBUG( iterT != mLayers.end() ); + // iterT might be the last + if( ( iterT+1 ) == mLayers.end() ) + { + mLayers.push_back( moved ); + } + else + { + mLayers.insert( iterT+1, moved ); + } + + SetLayerDepths(); + } +} + +void LayerList::MoveLayerBelow( const Layer& layer, const Layer& target ) +{ + // check if it already is in correct order + if( layer.GetDepth() == ( target.GetDepth() - 1 ) ) + { + return; + } + + // find the layer to move + LayerIter iter = Find( mLayers.begin(), mLayers.end(), layer); + if( iter != mLayers.end() ) + { + Layer* moved = *iter; + mLayers.erase( iter ); + // find target + LayerIter iterT = Find( mLayers.begin(), mLayers.end(), target); + // if target is not found there's a programming error somewhere + DALI_ASSERT_DEBUG( iterT != mLayers.end() ); + mLayers.insert( iterT, moved ); + + SetLayerDepths(); + } +} + +LayerList::LayerList( SceneGraph::UpdateManager& updateManager, bool systemLevel ) +: mUpdateManager( updateManager ), + mIsSystemLevel( systemLevel ) +{ +} + +void LayerList::SetLayerDepths() +{ + // we've got a list of on-stage layers on actor side, need to get their stage + // pointers so we can send them to the update manager + std::vector< SceneGraph::Layer* > layers; + layers.reserve( mLayers.size() ); + + // Set the layers (possibly) new depth + for (LayerIter iter = mLayers.begin(); iter != mLayers.end(); ++iter) + { + SceneGraph::Layer* layerPtr = const_cast< SceneGraph::Layer* >( &( (*iter)->GetSceneLayerOnStage() ) ); + layers.push_back( layerPtr ); + } + + // Layers are being used in a separate thread; queue a message to set order + SetLayerDepthsMessage( mUpdateManager, layers, mIsSystemLevel ); +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/actors/layer-list.h b/dali/internal/event/actors/layer-list.h new file mode 100644 index 0000000..22b5bfc --- /dev/null +++ b/dali/internal/event/actors/layer-list.h @@ -0,0 +1,167 @@ +#ifndef __DALI_INTERNAL_LAYER_LIST_H__ +#define __DALI_INTERNAL_LAYER_LIST_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace SceneGraph +{ +class UpdateManager; +} + +class Layer; + +/** + * An ordered list of layers. + * Layers are not owned by the LayerList; each layer is responsible for registering & unregistering. + * This is used by the Stage, to keep track of layer depths. + * A separate LayerList is maintained for actors added via the SystemOverlay::Add(). + */ +class LayerList +{ +public: + + /** + * Create a new list of layers. + * @param[in] updateManager A reference to the update manager. + * @param[in] systemLevel True if the layers are added via the SystemOverlay API. + */ + static LayerList* New( SceneGraph::UpdateManager& updateManager, bool systemLevel ); + + /** + * Non-virtual destructor; not suitable as a base class. + */ + ~LayerList(); + + /** + * Query the number of layers. + * @return The number of layers. + */ + unsigned int GetLayerCount() const; + + /** + * Retrieve the layer at a specified depth. + * @pre depth is less than layer count; see GetLayerCount(). + * @param[in] depth The depth. + * @return The layer found at the given depth. + */ + Layer* GetLayer( unsigned int depth ) const; + + /** + * Gets the depth of a given layer + * @param layer which depth to check + */ + unsigned int GetDepth( const Layer* layer ) const; + + /** + * Register a layer with the stage. + * The stage determines the relative depth of each layer. + */ + void RegisterLayer( Layer& layer ); + + /** + * Unregister a layer from the stage + */ + void UnregisterLayer(Layer& layer); + + /** + * Increment the depth of the layer inside the stage + * @pre layer is on stage + */ + void RaiseLayer(Layer& layer); + + /** + * Decrement the depth of the layer inside the stage + * @pre layer is on stage + */ + void LowerLayer(Layer& layer); + + /** + * Raises the layer to the top of the stage + * @pre layer is on stage + * @param layer to move + */ + void RaiseLayerToTop( const Layer& layer ); + + /** + * Lowers the layer to the bottom of the stage + * @pre layer is on stage + * @param layer to move + */ + void LowerLayerToBottom( const Layer& layer ); + + /** + * Moves the layer above the target layer on the stage + * @pre layer is on stage + * @pre target is on stage + * @param layer to move + * @param target to move above of + */ + void MoveLayerAbove( const Layer& layer, const Layer& target ); + + /** + * Moves the layer below the target layer on the stage + * @pre layer is on stage + * @pre target is on stage + * @param layer to move + * @param target to move below of + */ + void MoveLayerBelow( const Layer& layer, const Layer& target ); + +private: + + /** + * Protected constructor; see also LayerList::New(). + * @param[in] updateManager to send messages. + * @param[in] systemLevel True if the layers are added via the SystemOverlay API. + */ + LayerList( SceneGraph::UpdateManager& updateManager, bool systemLevel ); + + /** + * A private helper method to set the depth for each layer. + * Layers have depth which is the same as their ordinal number in the stage container + * This method propagates any changes in the layer depths onto the scene graph side + */ + void SetLayerDepths(); + +private: + + SceneGraph::UpdateManager& mUpdateManager; + + bool mIsSystemLevel; ///< True if the layers are added via the SystemOverlay API. + + typedef std::vector LayerContainer; + + // Layers are not owned by the LayerList. + // Each layer is responsible for registering & unregistering before the end of its life-time. + LayerContainer mLayers; +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_LAYER_LIST_H__ diff --git a/dali/internal/event/animation/animation-impl.cpp b/dali/internal/event/animation/animation-impl.cpp new file mode 100644 index 0000000..0c92623 --- /dev/null +++ b/dali/internal/event/animation/animation-impl.cpp @@ -0,0 +1,936 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include +#include + +// EXTERNAL INCLUDES + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using Dali::Internal::SceneGraph::UpdateManager; +using Dali::Internal::SceneGraph::AnimatorBase; +using Dali::Internal::SceneGraph::Shader; + +namespace Dali +{ + +namespace Internal +{ + +static bool SHOW_VALUE = true; +static bool HIDE_VALUE = false; + +namespace +{ + +// Signals + +const char* const SIGNAL_FINISHED = "finished"; + +// Actions + +const char* const ACTION_PLAY = "play"; +const char* const ACTION_STOP = "stop"; +const char* const ACTION_PAUSE = "pause"; + +BaseHandle Create() +{ + return Dali::Animation::New(0.f); +} + +TypeRegistration mType( typeid( Dali::Animation ), typeid( Dali::BaseHandle ), Create ); + +SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &Animation::DoConnectSignal ); + +TypeAction action1( mType, ACTION_PLAY, &Animation::DoAction ); +TypeAction action2( mType, ACTION_STOP, &Animation::DoAction ); +TypeAction action3( mType, ACTION_PAUSE, &Animation::DoAction ); + +const Dali::Animation::EndAction DEFAULT_END_ACTION( Dali::Animation::Bake ); +const Dali::Animation::EndAction DEFAULT_DISCONNECT_ACTION( Dali::Animation::BakeFinal ); +const Dali::Animation::Interpolation DEFAULT_INTERPOLATION( Dali::Animation::Linear ); +const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION( Dali::AlphaFunction::DEFAULT ); + +} // anon namespace + + +AnimationPtr Animation::New(float durationSeconds) +{ + Stage* stage = Stage::GetCurrent(); + + if( stage ) + { + AnimationPlaylist& playlist = stage->GetAnimationPlaylist(); + + if( durationSeconds < 0.0f ) + { + DALI_LOG_WARNING("duration should be greater than 0.0f.\n"); + durationSeconds = 0.0f; + } + + AnimationPtr animation = new Animation( *stage, playlist, durationSeconds, DEFAULT_END_ACTION, DEFAULT_DISCONNECT_ACTION, DEFAULT_ALPHA_FUNCTION ); + + // Second-phase construction + animation->Initialize(); + + return animation; + } + else + { + return NULL; + } +} + +Animation::Animation( EventThreadServices& eventThreadServices, AnimationPlaylist& playlist, float durationSeconds, EndAction endAction, EndAction disconnectAction, AlphaFunction defaultAlpha ) +: mEventThreadServices( eventThreadServices ), + mPlaylist( playlist ), + mAnimation( NULL ), + mNotificationCount( 0 ), + mFinishedCallback( NULL ), + mFinishedCallbackObject( NULL ), + mDurationSeconds( durationSeconds ), + mSpeedFactor(1.0f), + mIsLooping( false ), + mPlayRange( Vector2(0.0f,1.0f)), + mEndAction( endAction ), + mDisconnectAction( disconnectAction ), + mDefaultAlpha( defaultAlpha ) +{ +} + +void Animation::Initialize() +{ + // Connect to the animation playlist + mPlaylist.AnimationCreated( *this ); + + CreateSceneObject(); + + RegisterObject(); +} + +Animation::~Animation() +{ + // Guard to allow handle destruction after Core has been destroyed + if ( Stage::IsInstalled() ) + { + // Disconnect from the animation playlist + mPlaylist.AnimationDestroyed( *this ); + + DestroySceneObject(); + + UnregisterObject(); + } +} + +void Animation::CreateSceneObject() +{ + DALI_ASSERT_DEBUG( mAnimation == NULL ); + + // Create a new animation, temporarily owned + SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mIsLooping, mEndAction, mDisconnectAction ); + + // Keep a const pointer to the animation. + mAnimation = animation; + + // Transfer animation ownership to the update manager through a message + AddAnimationMessage( mEventThreadServices.GetUpdateManager(), animation ); +} + +void Animation::DestroySceneObject() +{ + if ( mAnimation != NULL ) + { + // Remove animation using a message to the update manager + RemoveAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation ); + mAnimation = NULL; + } +} + +void Animation::SetDuration(float seconds) +{ + if( seconds < 0.0f ) + { + DALI_LOG_WARNING("duration should be greater than 0.0f.\n"); + seconds = 0.0f; + } + + // Cache for public getters + mDurationSeconds = seconds; + + // mAnimation is being used in a separate thread; queue a message to set the value + SetDurationMessage( mEventThreadServices, *mAnimation, seconds ); +} + +float Animation::GetDuration() const +{ + // This is not animatable; the cached value is up-to-date. + return mDurationSeconds; +} + +void Animation::SetLooping(bool looping) +{ + // Cache for public getters + mIsLooping = looping; + + // mAnimation is being used in a separate thread; queue a message to set the value + SetLoopingMessage( mEventThreadServices, *mAnimation, looping ); +} + +bool Animation::IsLooping() const +{ + // This is not animatable; the cached value is up-to-date. + return mIsLooping; +} + +void Animation::SetEndAction(EndAction action) +{ + // Cache for public getters + mEndAction = action; + + // mAnimation is being used in a separate thread; queue a message to set the value + SetEndActionMessage( mEventThreadServices, *mAnimation, action ); +} + +Dali::Animation::EndAction Animation::GetEndAction() const +{ + // This is not animatable; the cached value is up-to-date. + return mEndAction; +} + +void Animation::SetDisconnectAction(EndAction action) +{ + // Cache for public getters + mDisconnectAction = action; + + // mAnimation is being used in a separate thread; queue a message to set the value + SetDisconnectActionMessage( mEventThreadServices, *mAnimation, action ); +} + +Dali::Animation::EndAction Animation::GetDisconnectAction() const +{ + // This is not animatable; the cached value is up-to-date. + return mDisconnectAction; +} + +void Animation::Play() +{ + // Update the current playlist + mPlaylist.OnPlay( *this ); + + // mAnimation is being used in a separate thread; queue a Play message + PlayAnimationMessage( mEventThreadServices, *mAnimation ); +} + +void Animation::PlayFrom( float progress ) +{ + if( progress >= mPlayRange.x && progress <= mPlayRange.y ) + { + // Update the current playlist + mPlaylist.OnPlay( *this ); + + // mAnimation is being used in a separate thread; queue a Play message + PlayAnimationFromMessage( mEventThreadServices, *mAnimation, progress ); + } +} + +void Animation::Pause() +{ + // mAnimation is being used in a separate thread; queue a Pause message + PauseAnimationMessage( mEventThreadServices, *mAnimation ); +} + +void Animation::Stop() +{ + // mAnimation is being used in a separate thread; queue a Stop message + StopAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation ); +} + +void Animation::Clear() +{ + DALI_ASSERT_DEBUG(mAnimation); + + // Remove all the connectors + mConnectors.Clear(); + + // Replace the old scene-object with a new one + DestroySceneObject(); + CreateSceneObject(); + + // Reset the notification count, since the new scene-object has never been played + mNotificationCount = 0; + + // Update the current playlist + mPlaylist.OnClear( *this ); +} + +void Animation::AnimateBy(Property& target, Property::Value& relativeValue) +{ + AnimateBy(target, relativeValue, mDefaultAlpha, TimePeriod(mDurationSeconds)); +} + +void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha) +{ + AnimateBy(target, relativeValue, alpha, TimePeriod(mDurationSeconds)); +} + +void Animation::AnimateBy(Property& target, Property::Value& relativeValue, TimePeriod period) +{ + AnimateBy(target, relativeValue, mDefaultAlpha, period); +} + +void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha, TimePeriod period) +{ + Object& object = dynamic_cast( GetImplementation(target.object) ); + + ExtendDuration( period ); + + switch ( relativeValue.GetType() ) + { + case Property::BOOLEAN: + { + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new AnimateByBoolean(relativeValue.Get()), + alpha, + period ) ); + break; + } + + case Property::INTEGER: + { + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new AnimateByInteger(relativeValue.Get()), + alpha, + period ) ); + break; + } + + case Property::FLOAT: + { + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new AnimateByFloat(relativeValue.Get()), + alpha, + period ) ); + break; + } + + case Property::VECTOR2: + { + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new AnimateByVector2(relativeValue.Get()), + alpha, + period ) ); + break; + } + + case Property::VECTOR3: + { + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new AnimateByVector3(relativeValue.Get()), + alpha, + period ) ); + break; + } + + case Property::VECTOR4: + { + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new AnimateByVector4(relativeValue.Get()), + alpha, + period ) ); + break; + } + + case Property::ROTATION: + { + AngleAxis angleAxis = relativeValue.Get(); + + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new RotateByAngleAxis(angleAxis.angle, angleAxis.axis), + alpha, + period ) ); + break; + } + + default: + DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here + break; + } +} + +void Animation::AnimateTo(Property& target, Property::Value& destinationValue) +{ + AnimateTo(target, destinationValue, mDefaultAlpha, TimePeriod(mDurationSeconds)); +} + +void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha) +{ + AnimateTo(target, destinationValue, alpha, TimePeriod(mDurationSeconds)); +} + +void Animation::AnimateTo(Property& target, Property::Value& destinationValue, TimePeriod period) +{ + AnimateTo(target, destinationValue, mDefaultAlpha, period); +} + +void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period) +{ + Object& object = dynamic_cast( GetImplementation(target.object) ); + + AnimateTo( object, target.propertyIndex, target.componentIndex, destinationValue, alpha, period ); +} + +void Animation::AnimateTo(Object& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period) +{ + Property::Type type = targetObject.GetPropertyType(targetPropertyIndex); + if(componentIndex != Property::INVALID_COMPONENT_INDEX) + { + if( type == Property::VECTOR2 + || type == Property::VECTOR3 + || type == Property::VECTOR4 ) + { + type = Property::FLOAT; + } + } + DALI_ASSERT_ALWAYS( type == destinationValue.GetType() && "DestinationValue does not match Target Property type" ); + + ExtendDuration( period ); + + switch (destinationValue.GetType()) + { + case Property::BOOLEAN: + { + AddAnimatorConnector( AnimatorConnector::New( targetObject, + targetPropertyIndex, + componentIndex, + new AnimateToBoolean( destinationValue.Get() ), + alpha, + period ) ); + break; + } + + case Property::INTEGER: + { + AddAnimatorConnector( AnimatorConnector::New( targetObject, + targetPropertyIndex, + componentIndex, + new AnimateToInteger( destinationValue.Get() ), + alpha, + period ) ); + break; + } + + case Property::FLOAT: + { + if ( ( Dali::Actor::Property::SIZE_WIDTH == targetPropertyIndex )|| + ( Dali::Actor::Property::SIZE_HEIGHT == targetPropertyIndex ) ) + { + // Test whether this is actually an Actor + Actor* maybeActor = dynamic_cast( &targetObject ); + if ( maybeActor ) + { + // Notify the actor that its size is being animated + maybeActor->NotifySizeAnimation( *this, destinationValue.Get(), targetPropertyIndex ); + } + } + AddAnimatorConnector( AnimatorConnector::New( targetObject, + targetPropertyIndex, + componentIndex, + new AnimateToFloat( destinationValue.Get() ), + alpha, + period ) ); + break; + } + + case Property::VECTOR2: + { + AddAnimatorConnector( AnimatorConnector::New( targetObject, + targetPropertyIndex, + componentIndex, + new AnimateToVector2( destinationValue.Get() ), + alpha, + period ) ); + break; + } + + case Property::VECTOR3: + { + if ( Dali::Actor::Property::SIZE == targetPropertyIndex ) + { + // Test whether this is actually an Actor + Actor* maybeActor = dynamic_cast( &targetObject ); + if ( maybeActor ) + { + // Notify the actor that its size is being animated + maybeActor->NotifySizeAnimation( *this, destinationValue.Get() ); + } + } + + AddAnimatorConnector( AnimatorConnector::New( targetObject, + targetPropertyIndex, + componentIndex, + new AnimateToVector3( destinationValue.Get() ), + alpha, + period ) ); + break; + } + + case Property::VECTOR4: + { + AddAnimatorConnector( AnimatorConnector::New( targetObject, + targetPropertyIndex, + componentIndex, + new AnimateToVector4( destinationValue.Get() ), + alpha, + period ) ); + break; + } + + case Property::ROTATION: + { + AddAnimatorConnector( AnimatorConnector::New( targetObject, + targetPropertyIndex, + componentIndex, + new RotateToQuaternion( destinationValue.Get() ), + alpha, + period ) ); + break; + } + + default: + DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here + break; + } +} + +void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames) +{ + AnimateBetween(target, keyFrames, mDefaultAlpha, TimePeriod(mDurationSeconds), DEFAULT_INTERPOLATION ); +} + +void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation ) +{ + AnimateBetween(target, keyFrames, mDefaultAlpha, TimePeriod(mDurationSeconds), interpolation ); +} + +void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period) +{ + AnimateBetween(target, keyFrames, mDefaultAlpha, period, DEFAULT_INTERPOLATION); +} + +void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation) +{ + AnimateBetween(target, keyFrames, mDefaultAlpha, period, interpolation); +} + +void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha) +{ + AnimateBetween(target, keyFrames, alpha, TimePeriod(mDurationSeconds), DEFAULT_INTERPOLATION); +} + +void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation) +{ + AnimateBetween(target, keyFrames, alpha, TimePeriod(mDurationSeconds), interpolation); +} + +void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period) +{ + AnimateBetween(target, keyFrames, alpha, period, DEFAULT_INTERPOLATION); +} + +void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation) +{ + Object& object = dynamic_cast( GetImplementation(target.object) ); + + ExtendDuration( period ); + + switch(keyFrames.GetType()) + { + case Dali::Property::BOOLEAN: + { + const KeyFrameBoolean* kf; + GetSpecialization(keyFrames, kf); + KeyFrameBooleanPtr kfCopy = KeyFrameBoolean::Clone(*kf); + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new KeyFrameBooleanFunctor(kfCopy), + alpha, + period ) ); + break; + } + + case Dali::Property::INTEGER: + { + const KeyFrameInteger* kf; + GetSpecialization(keyFrames, kf); + KeyFrameIntegerPtr kfCopy = KeyFrameInteger::Clone(*kf); + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new KeyFrameIntegerFunctor(kfCopy,interpolation), + alpha, + period ) ); + break; + } + + case Dali::Property::FLOAT: + { + const KeyFrameNumber* kf; + GetSpecialization(keyFrames, kf); + KeyFrameNumberPtr kfCopy = KeyFrameNumber::Clone(*kf); + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new KeyFrameNumberFunctor(kfCopy,interpolation), + alpha, + period ) ); + break; + } + + case Dali::Property::VECTOR2: + { + const KeyFrameVector2* kf; + GetSpecialization(keyFrames, kf); + KeyFrameVector2Ptr kfCopy = KeyFrameVector2::Clone(*kf); + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new KeyFrameVector2Functor(kfCopy,interpolation), + alpha, + period ) ); + break; + } + + case Dali::Property::VECTOR3: + { + const KeyFrameVector3* kf; + GetSpecialization(keyFrames, kf); + KeyFrameVector3Ptr kfCopy = KeyFrameVector3::Clone(*kf); + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new KeyFrameVector3Functor(kfCopy,interpolation), + alpha, + period ) ); + break; + } + + case Dali::Property::VECTOR4: + { + const KeyFrameVector4* kf; + GetSpecialization(keyFrames, kf); + KeyFrameVector4Ptr kfCopy = KeyFrameVector4::Clone(*kf); + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new KeyFrameVector4Functor(kfCopy,interpolation), + alpha, + period ) ); + break; + } + + case Dali::Property::ROTATION: + { + const KeyFrameQuaternion* kf; + GetSpecialization(keyFrames, kf); + KeyFrameQuaternionPtr kfCopy = KeyFrameQuaternion::Clone(*kf); + AddAnimatorConnector( AnimatorConnector::New( object, + target.propertyIndex, + target.componentIndex, + new KeyFrameQuaternionFunctor(kfCopy), + alpha, + period ) ); + break; + } + + default: // not all property types are animateable + break; + } +} + +bool Animation::HasFinished() +{ + bool hasFinished(false); + const int playCount(mAnimation->GetPlayCount()); + + // If the play count has been incremented, then another notification is required + if (playCount > mNotificationCount) + { + // Note that only one signal is emitted, if the animation has been played repeatedly + mNotificationCount = playCount; + + hasFinished = true; + } + + return hasFinished; +} + +Dali::Animation::AnimationSignalType& Animation::FinishedSignal() +{ + return mFinishedSignal; +} + +void Animation::EmitSignalFinish() +{ + if ( !mFinishedSignal.Empty() ) + { + Dali::Animation handle( this ); + mFinishedSignal.Emit( handle ); + } + + // This callback is used internally, to avoid the overhead of using a signal. + if ( mFinishedCallback ) + { + mFinishedCallback( mFinishedCallbackObject ); + } +} + +bool Animation::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ) +{ + bool connected( true ); + Animation* animation = dynamic_cast(object); + + if( 0 == signalName.compare( SIGNAL_FINISHED ) ) + { + animation->FinishedSignal().Connect( tracker, functor ); + } + else + { + // signalName does not match any signal + connected = false; + } + + return connected; +} + +void Animation::SetFinishedCallback( FinishedCallback callback, Object* object ) +{ + mFinishedCallback = callback; + mFinishedCallbackObject = object; +} + +void Animation::AddAnimatorConnector( AnimatorConnectorBase* connector ) +{ + DALI_ASSERT_DEBUG( NULL != connector ); + + connector->SetParent(*this); + + mConnectors.PushBack( connector ); +} + +void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward ) +{ + Animate( actor, path, forward, mDefaultAlpha, TimePeriod(mDurationSeconds) ); +} + +void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha ) +{ + Animate( actor, path, forward, alpha, TimePeriod(mDurationSeconds) ); +} + +void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, TimePeriod period ) +{ + Animate( actor, path, forward, mDefaultAlpha, period ); +} + +void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period) +{ + ExtendDuration( period ); + + PathPtr pathCopy = Path::Clone(path); + + //Position animation + AddAnimatorConnector( AnimatorConnector::New( actor, + Dali::Actor::Property::POSITION, + Property::INVALID_COMPONENT_INDEX, + new PathPositionFunctor( pathCopy ), + alpha, + period ) ); + + //If forward is zero, PathRotationFunctor will always return the unit quaternion + if( forward != Vector3::ZERO ) + { + //Rotation animation + AddAnimatorConnector( AnimatorConnector::New( actor, + Dali::Actor::Property::ORIENTATION, + Property::INVALID_COMPONENT_INDEX, + new PathRotationFunctor( pathCopy, forward ), + alpha, + period ) ); + } +} + +void Animation::Show(Actor& actor, float delaySeconds) +{ + ExtendDuration( TimePeriod(delaySeconds, 0) ); + + AddAnimatorConnector( AnimatorConnector::New( actor, + Dali::Actor::Property::VISIBLE, + Property::INVALID_COMPONENT_INDEX, + new AnimateToBoolean(SHOW_VALUE), + mDefaultAlpha, + TimePeriod(delaySeconds, 0.0f/*immediate*/) ) ); +} + +void Animation::Hide(Actor& actor, float delaySeconds) +{ + ExtendDuration( TimePeriod(delaySeconds, 0) ); + + AddAnimatorConnector( AnimatorConnector::New( actor, + Dali::Actor::Property::VISIBLE, + Property::INVALID_COMPONENT_INDEX, + new AnimateToBoolean(HIDE_VALUE), + mDefaultAlpha, + TimePeriod(delaySeconds, 0.0f/*immediate*/) ) ); +} + +bool Animation::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes ) +{ + bool done = false; + Animation* animation = dynamic_cast( object ); + + if( animation ) + { + if( 0 == actionName.compare( ACTION_PLAY ) ) + { + if( Property::Value* value = attributes.Find("duration", Property::FLOAT) ) + { + animation->SetDuration( value->Get() ); + } + + animation->Play(); + done = true; + } + else if( 0 == actionName.compare( ACTION_STOP ) ) + { + animation->Stop(); + done = true; + } + else if( 0 == actionName.compare( ACTION_PAUSE ) ) + { + animation->Pause(); + done = true; + } + } + + return done; +} + +void Animation::SetCurrentProgress(float progress) +{ + if( mAnimation && progress >= mPlayRange.x && progress <= mPlayRange.y ) + { + // mAnimation is being used in a separate thread; queue a message to set the current progress + SetCurrentProgressMessage( mEventThreadServices, *mAnimation, progress ); + } +} + +float Animation::GetCurrentProgress() +{ + if( mAnimation ) + { + return mAnimation->GetCurrentProgress(); + } + + return 0.0f; +} + +void Animation::ExtendDuration( const TimePeriod& timePeriod ) +{ + float duration = timePeriod.delaySeconds + timePeriod.durationSeconds; + + if( duration > mDurationSeconds ) + { + SetDuration( duration ); + } +} + +void Animation::SetSpeedFactor( float factor ) +{ + if( mAnimation ) + { + mSpeedFactor = factor; + SetSpeedFactorMessage( mEventThreadServices, *mAnimation, factor ); + } +} + +float Animation::GetSpeedFactor() const +{ + return mSpeedFactor; +} + +void Animation::SetPlayRange( const Vector2& range) +{ + //Make sure the range specified is between 0.0 and 1.0 + if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f ) + { + Vector2 orderedRange( range ); + //If the range is not in order swap values + if( range.x > range.y ) + { + orderedRange = Vector2(range.y, range.x); + } + + // Cache for public getters + mPlayRange = orderedRange; + + // mAnimation is being used in a separate thread; queue a message to set play range + SetPlayRangeMessage( mEventThreadServices, *mAnimation, orderedRange ); + } +} + +Vector2 Animation::GetPlayRange() const +{ + return mPlayRange; +} + + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/animation/animation-impl.h b/dali/internal/event/animation/animation-impl.h new file mode 100644 index 0000000..6272042 --- /dev/null +++ b/dali/internal/event/animation/animation-impl.h @@ -0,0 +1,481 @@ +#ifndef __DALI_INTERNAL_ANIMATION_H__ +#define __DALI_INTERNAL_ANIMATION_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace SceneGraph +{ +class Animation; +class UpdateManager; +} + +class Actor; +class Animation; +class AnimationPlaylist; +class Object; +class ShaderEffect; + +typedef IntrusivePtr AnimationPtr; +typedef std::vector AnimationContainer; + +typedef AnimationContainer::iterator AnimationIter; +typedef AnimationContainer::const_iterator AnimationConstIter; + +/** + * Animation is a proxy for a SceneGraph::Animation object. + * The UpdateManager owns the Animation object, but the lifetime of the animation is + * indirectly controlled by the Animation. + */ +class Animation : public BaseObject +{ +public: + + typedef Dali::Animation::EndAction EndAction; + typedef Dali::Animation::Interpolation Interpolation; + + typedef void (*FinishedCallback)(Object* object); + + /** + * Create a new Animation object. + * @param[in] durationSeconds The duration of the animation. + * @return A smart-pointer to the newly allocated Animation. + */ + static AnimationPtr New(float durationSeconds); + + /** + * @copydoc Dali::Animation::SetDuration() + */ + void SetDuration(float seconds); + + /** + * @copydoc Dali::Animation::GetDuration() + */ + float GetDuration() const; + + /** + * @copydoc Dali::Animation::SetLooping() + */ + void SetLooping(bool looping); + + /** + * @copydoc Dali::Animation::IsLooping() + */ + bool IsLooping() const; + + /** + * @copydoc Dali::Animation::SetEndAction() + */ + void SetEndAction(EndAction action); + + /** + * @copydoc Dali::Animation::GetEndAction() + */ + EndAction GetEndAction() const; + + /** + * @copydoc Dali::Animation::SetDisconnectAction() + */ + void SetDisconnectAction(EndAction action); + + /** + * @copydoc Dali::Animation::GetDisconnectAction() + */ + EndAction GetDisconnectAction() const; + + /** + * @copydoc Dali::Animation::SetDefaultAlphaFunction() + */ + void SetDefaultAlphaFunction(AlphaFunction alpha) + { + mDefaultAlpha = alpha; + } + + /** + * @copydoc Dali::Animation::GetDefaultAlphaFunction() + */ + AlphaFunction GetDefaultAlphaFunction() const + { + return mDefaultAlpha; + } + + /** + * @copydoc Dali::Animation::Play() + */ + void Play(); + + /** + * @copydoc Dali::Animation::PlayFrom() + */ + void PlayFrom( float progress ); + + /** + * @copydoc Dali::Animation::Pause() + */ + void Pause(); + + /** + * @copydoc Dali::Animation::Stop() + */ + void Stop(); + + /** + * @copydoc Dali::Animation::Clear() + */ + void Clear(); + + /** + * Query whether a Finished signal should be emitted for this animation. + * This should only be called by NotificationManager, before signals are emitted. + * @post HasFinished() will return false on subsequent calls, until the animation is replayed to completion. + */ + bool HasFinished(); + + /** + * @copydoc Dali::Animation::FinishedSignal() + */ + Dali::Animation::AnimationSignalType& FinishedSignal(); + + /** + * Emit the Finished signal + */ + void EmitSignalFinish(); + + /** + * Connects a callback function with the object's signals. + * @param[in] object The object providing the signal. + * @param[in] tracker Used to disconnect the signal. + * @param[in] signalName The signal to connect to. + * @param[in] functor A newly allocated FunctorDelegate. + * @return True if the signal was connected. + * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor. + */ + static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor ); + + /** + * Performs actions as requested using the action name. + * @param[in] object The object on which to perform the action. + * @param[in] actionName The action to perform. + * @param[in] attributes The attributes with which to perfrom this action. + * @return true if action was done + */ + static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes); + + /** + * This callback is intended for internal use only, to avoid the overhead of using a signal. + * @param[in] callback The callback function to connect. + * @param[in] object The internal object requesting the callback, or NULL. + */ + void SetFinishedCallback( FinishedCallback callback, Object* object ); + + /** + * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue) + */ + void AnimateBy(Property& target, Property::Value& relativeValue); + + /** + * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha) + */ + void AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha); + + /** + * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, TimePeriod period) + */ + void AnimateBy(Property& target, Property::Value& relativeValue, TimePeriod period); + + /** + * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period) + */ + void AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha, TimePeriod period); + + /** + * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue) + */ + void AnimateTo(Property& target, Property::Value& destinationValue); + + /** + * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha) + */ + void AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha); + + /** + * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, TimePeriod period) + */ + void AnimateTo(Property& target, Property::Value& destinationValue, TimePeriod period); + + /** + * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period) + */ + void AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period); + + /** + * Animate a property to a destination value. + * @param [in] targetObject The target object to animate. + * @param [in] targetPropertyIndex The index of the target property. + * @param [in] componentIndex Index to a sub component of a property, for use with Vector2, Vector3 and Vector4 + * @param [in] destinationValue The destination value. + * @param [in] alpha The alpha function to apply. + * @param [in] period The effect will occur during this time period. + */ + void AnimateTo(Object& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period); + + /** + * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames) + */ + void AnimateBetween(Property target, const KeyFrames& keyFrames); + + /** + * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, Interpolation interpolation) + */ + void AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation ); + + /** + * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period) + */ + void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period); + + /** + * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation) + */ + void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation); + + /** + * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha) + */ + void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha); + + /** + * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation) + */ + void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation); + + /** + * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period) + */ + void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period); + + /** + * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation ) + */ + void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation ); + + // Actor-specific convenience functions + + /** + * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward ) + */ + void Animate( Actor& actor, const Path& path, const Vector3& forward ); + + /** + * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha ) + */ + void Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha ); + + /** + * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, TimePeriod period ) + */ + void Animate( Actor& actor, const Path& path, const Vector3& forward, TimePeriod period ); + + /** + * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha, TimePeriod period) + */ + void Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period); + + /** + * @copydoc Dali::Animation::Show() + */ + void Show(Actor& actor, float delaySeconds); + + /** + * @copydoc Dali::Animation::Hide() + */ + void Hide(Actor& actor, float delaySeconds); + + /* + * @copydoc Dali::Animation::SetCurrentProgress() + */ + void SetCurrentProgress(float progress); + + /* + * @copydoc Dali::Animation::GetCurrentProgress() + */ + float GetCurrentProgress(); + + /* + * @copydoc Dali::Animation::SetSpeedFactor() + */ + void SetSpeedFactor( float factor ); + + /* + * @copydoc Dali::Animation::GetSpeedFactor() + */ + float GetSpeedFactor() const; + + /* + * @copydoc Dali::Animation::SetPlayRange() + */ + void SetPlayRange( const Vector2& range ); + + /* + * @copydoc Dali::Animation::GetPlayRange + */ + Vector2 GetPlayRange() const; + +public: // For connecting animators to animations + + /** + * Add an animator connector. + * @param[in] connector The animator connector. + */ + void AddAnimatorConnector( AnimatorConnectorBase* connector ); + + /** + * Retrieve the SceneGraph::Animation object. + * @return The animation. + */ + const SceneGraph::Animation* GetSceneObject() + { + return mAnimation; + } + + /** + * Retrieve the event thread services object + * @return The interface for sending messages to the scene graph + */ + EventThreadServices& GetEventThreadServices() + { + return mEventThreadServices; + } + +protected: + + /** + * Construct a new Animation. + * @param[in] eventThreadServices The interface for sending messages to the scene graph + * @param[in] playlist The list of currently playing animations. + * @param[in] durationSeconds The duration of the animation in seconds. + * @param[in] endAction The action to perform when the animation ends. + * @param[in] disconnectAction The action to perform when the property owner of an animator is disconnected. + * @param[in] defaultAlpha The default alpha function to apply to animators. + */ + Animation( EventThreadServices& eventThreadServices, + AnimationPlaylist& playlist, + float durationSeconds, + EndAction endAction, + EndAction disconnectAction, + AlphaFunction defaultAlpha); + + /** + * Second-phase constructor. + */ + void Initialize(); + + /** + * Helper to create a scene-graph animation + */ + void CreateSceneObject(); + + /** + * Helper to create a scene-graph animation + */ + void DestroySceneObject(); + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~Animation(); + +private: + + /** + * Extends the duration when an animator is added with TimePeriod that exceeds current duration. + * @param[in] timePeriod The time period for an animator. + */ + void ExtendDuration( const TimePeriod& timePeriod ); + + // Undefined + Animation(const Animation&); + + // Undefined + Animation& operator=(const Animation& rhs); + +private: + EventThreadServices& mEventThreadServices; + AnimationPlaylist& mPlaylist; + + const SceneGraph::Animation* mAnimation; + + int mNotificationCount; ///< Keep track of how many Finished signals have been emitted. + + Dali::Animation::AnimationSignalType mFinishedSignal; + + FinishedCallback mFinishedCallback; + Object* mFinishedCallbackObject; + + AnimatorConnectorContainer mConnectors; ///< Owned by the Animation + + // Cached for public getters + float mDurationSeconds; + float mSpeedFactor; + bool mIsLooping; + Vector2 mPlayRange; + EndAction mEndAction; + EndAction mDisconnectAction; + AlphaFunction mDefaultAlpha; + +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Internal::Animation& GetImplementation(Dali::Animation& animation) +{ + DALI_ASSERT_ALWAYS( animation && "Animation handle is empty" ); + + BaseObject& handle = animation.GetBaseObject(); + + return static_cast(handle); +} + +inline const Internal::Animation& GetImplementation(const Dali::Animation& animation) +{ + DALI_ASSERT_ALWAYS( animation && "Animation handle is empty" ); + + const BaseObject& handle = animation.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Dali + +#endif // __DALI_INTERNAL_ANIMATION_H__ diff --git a/dali/internal/event/animation/animation-playlist-declarations.h b/dali/internal/event/animation/animation-playlist-declarations.h new file mode 100644 index 0000000..a180d94 --- /dev/null +++ b/dali/internal/event/animation/animation-playlist-declarations.h @@ -0,0 +1,39 @@ +#ifndef __DALI_INTERNAL_ANIMATION_PLAYLIST_DECLARATIONS_H__ +#define __DALI_INTERNAL_ANIMATION_PLAYLIST_DECLARATIONS_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +class AnimationPlaylist; + +typedef OwnerPointer AnimationPlaylistOwner; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_ANIMATION_PLAYLIST_DECLARATIONS_H__ + diff --git a/dali/internal/event/animation/animation-playlist.cpp b/dali/internal/event/animation/animation-playlist.cpp new file mode 100644 index 0000000..ef3644b --- /dev/null +++ b/dali/internal/event/animation/animation-playlist.cpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + + +// INTERNAL INCLUDES +#include +#include +#include + + +namespace Dali +{ + +namespace Internal +{ + +AnimationPlaylist* AnimationPlaylist::New() +{ + return new AnimationPlaylist(); +} + +AnimationPlaylist::AnimationPlaylist() +{ +} + +AnimationPlaylist::~AnimationPlaylist() +{ +} + +void AnimationPlaylist::AnimationCreated( Animation& animation ) +{ + mAnimations.PushBack( &animation ); +} + +void AnimationPlaylist::AnimationDestroyed( Animation& animation ) +{ + Dali::Vector< Animation* >::Iterator iter = std::find( mAnimations.Begin(), mAnimations.End(), &animation ); + DALI_ASSERT_ALWAYS( iter != mAnimations.End() && "Animation not found" ); + + mAnimations.Remove( iter ); +} + +void AnimationPlaylist::OnPlay( Animation& animation ) +{ + mPlaylist.push_back( Dali::Animation(&animation) ); +} + +void AnimationPlaylist::OnClear( Animation& animation ) +{ + std::vector< Dali::Animation >::iterator iter = std::find( mPlaylist.begin(), mPlaylist.end(), Dali::Animation(&animation) ); + std::vector< Dali::Animation >::iterator last = mPlaylist.end(); + if( iter != last ) + { + --last; // move to real last + std::swap( *iter, *last ); // swap + mPlaylist.resize( mPlaylist.size() - 1u ); + } +} + +void AnimationPlaylist::NotifyCompleted() +{ + std::vector< Dali::Animation > finishedAnimations; + + // Since animations can be unreferenced during the signal emissions, iterators into animationPointers may be invalidated. + // First copy and reference the finished animations, then emit signals + for ( Dali::Vector< Animation* >::Iterator iter = mAnimations.Begin(); iter != mAnimations.End(); ++iter ) + { + Animation* animation = *iter; + + if ( animation->HasFinished() ) + { + finishedAnimations.push_back( Dali::Animation(animation) ); + + // The animation may be present in mPlaylist - remove if necessary + // Note that the animation "Finish" signal is emitted after Stop() has been called + std::vector< Dali::Animation >::iterator iter = std::find( mPlaylist.begin(), mPlaylist.end(), Dali::Animation(animation) ); + mPlaylist.erase( iter ); + } + } + + // Now it's safe to emit the signals + for ( std::vector< Dali::Animation >::iterator iter = finishedAnimations.begin(); iter != finishedAnimations.end(); ++iter ) + { + Dali::Animation& handle = *iter; + + GetImplementation(handle).EmitSignalFinish(); + } +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/animation/animation-playlist.h b/dali/internal/event/animation/animation-playlist.h new file mode 100644 index 0000000..504bc5f --- /dev/null +++ b/dali/internal/event/animation/animation-playlist.h @@ -0,0 +1,108 @@ +#ifndef __DALI_INTERNAL_ANIMATION_PLAYLIST_H__ +#define __DALI_INTERNAL_ANIMATION_PLAYLIST_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +class Animation; + +/** + * AnimationPlaylist provides notifications to applications when animations are finished. + * It reference-counts playing animations, to allow "fire and forget" behaviour. + */ +class AnimationPlaylist : public CompleteNotificationInterface +{ +public: + + /** + * Create an AnimationPlaylist. + * @return A newly allocated animation playlist. + */ + static AnimationPlaylist* New(); + + /** + * Virtual destructor. + */ + virtual ~AnimationPlaylist(); + + /** + * Called when an animation is constructed. + */ + void AnimationCreated( Animation& animation ); + + /** + * Called when an animation is destroyed. + */ + void AnimationDestroyed( Animation& animation ); + + /** + * Called when an animation is playing. + * @post The animation will be referenced by AnimationPlaylist, until the "Finished" signal is emitted. + */ + void OnPlay( Animation& animation ); + + /** + * Called when an animation is cleared. + * @post The animation will no longer be referenced by AnimationPlaylist. + */ + void OnClear( Animation& animation ); + +private: + + /** + * Create an AnimationPlaylist. + */ + AnimationPlaylist(); + + // Undefined + AnimationPlaylist(const AnimationPlaylist&); + + // Undefined + AnimationPlaylist& operator=(const AnimationPlaylist& rhs); + +private: // from CompleteNotificationInterface + + /** + * @copydoc CompleteNotificationInterface::NotifyCompleted() + */ + virtual void NotifyCompleted(); + +private: + + Dali::Vector< Animation* > mAnimations; ///< All existing animations (not owned) + std::vector< Dali::Animation > mPlaylist; ///< The currently playing animations (owned through handle) + +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_NOTIFICATION_MANAGER_H__ + diff --git a/dali/internal/event/animation/animator-connector-base.h b/dali/internal/event/animation/animator-connector-base.h new file mode 100644 index 0000000..90ff6f5 --- /dev/null +++ b/dali/internal/event/animation/animator-connector-base.h @@ -0,0 +1,96 @@ +#ifndef __DALI_INTERNAL_ANIMATOR_CONNECTOR_BASE_H__ +#define __DALI_INTERNAL_ANIMATOR_CONNECTOR_BASE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +class Animation; +class AnimatorConnectorBase; + +typedef OwnerPointer AnimatorConnectorPtr; + +typedef OwnerContainer< AnimatorConnectorBase* > AnimatorConnectorContainer; + +typedef AnimatorConnectorContainer::Iterator AnimatorConnectorIter; +typedef AnimatorConnectorContainer::ConstIterator AnimatorConnectorConstIter; + +/** + * An abstract base class for animator connectors. + */ +class AnimatorConnectorBase +{ +public: + + /** + * Constructor. + */ + AnimatorConnectorBase(AlphaFunction alpha, const TimePeriod& period) + : mParent(NULL), + mAlphaFunction(alpha), + mTimePeriod(period) + { + } + + /** + * Virtual destructor. + */ + virtual ~AnimatorConnectorBase() + { + } + + /** + * Set the parent of the AnimatorConnector. + * @pre The connector does not already have a parent. + * @param [in] parent The parent object. + */ + virtual void SetParent(Animation& parent) = 0; + + /** + * Retrieve the parent of the AnimatorConnector. + * @return The parent object, or NULL. + */ + Animation* GetParent() + { + return mParent; + } + +protected: + + Animation* mParent; ///< The parent owns the connector. + + AlphaFunction mAlphaFunction; + TimePeriod mTimePeriod; +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_ANIMATOR_CONNECTOR_BASE_H__ diff --git a/dali/internal/event/animation/animator-connector.h b/dali/internal/event/animation/animator-connector.h new file mode 100644 index 0000000..9440f91 --- /dev/null +++ b/dali/internal/event/animation/animator-connector.h @@ -0,0 +1,370 @@ +#ifndef __DALI_INTERNAL_ANIMATOR_CONNECTOR_H__ +#define __DALI_INTERNAL_ANIMATOR_CONNECTOR_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * AnimatorConnector is used to connect SceneGraph::Animators for newly created scene-graph objects. + * + * The scene-graph objects are created by a Object e.g. Actor is a proxy for SceneGraph::Node. + * AnimatorConnector observes the proxy object, in order to detect when a scene-graph object is created. + * + * SceneGraph::Animators weakly reference scene objects, and are automatically deleted when orphaned. + * Therefore the AnimatorConnector is NOT responsible for disconnecting animators. + */ +template < typename PropertyType > +class AnimatorConnector : public AnimatorConnectorBase, public Object::Observer +{ +public: + + typedef SceneGraph::Animator< PropertyType, PropertyAccessor > AnimatorType; + typedef SceneGraph::AnimatableProperty< PropertyType > PropertyInterfaceType; + + /** + * Construct a new animator connector. + * @param[in] object The object for a scene-graph object to animate. + * @param[in] propertyIndex The index of a property provided by the object. + * @param[in] componentIndex Index to a sub component of a property, for use with Vector2, Vector3 and Vector4 (INVALID_PROPERTY_COMPONENTINDEX to use the whole property) + * @param[in] animatorFunction A function used to animate the property. + * @param[in] alpha The alpha function to apply. + * @param[in] period The time period of the animator. + * @return A pointer to a newly allocated animator connector. + */ + static AnimatorConnectorBase* New( Object& object, + Property::Index propertyIndex, + int componentIndex, + AnimatorFunctionBase* animatorFunction, + AlphaFunction alpha, + const TimePeriod& period ) + { + return new AnimatorConnector< PropertyType >( object, + propertyIndex, + componentIndex, + animatorFunction, + alpha, + period ); + } + + /** + * Virtual destructor. + */ + virtual ~AnimatorConnector() + { + if( mObject ) + { + mObject->RemoveObserver( *this ); + } + + //If there is not a SceneGraph::Animator, the AnimatorConnector is responsible for deleting the mAnimatorFunction + //otherwise, the animator function ownership is transferred to the SceneGraph::Animator + if( !mAnimator ) + { + delete mAnimatorFunction; + mAnimatorFunction = 0; + } + } + + /** + * From AnimatorConnectorBase. + * This is only expected to be called once, when added to an Animation. + */ + void SetParent( Animation& parent ) + { + DALI_ASSERT_ALWAYS( mParent == NULL && "AnimationConnector already has a parent" ); + mParent = &parent; + + if( mObject && mObject->GetSceneObject() ) + { + CreateAnimator(); + } + } + +private: + + /** + * Private constructor; see also AnimatorConnector::New(). + */ + AnimatorConnector( Object& object, + Property::Index propertyIndex, + int componentIndex, + Internal::AnimatorFunctionBase* animatorFunction, + AlphaFunction alpha, + const TimePeriod& period ) + : AnimatorConnectorBase( alpha, period ), + mObject( &object ), + mAnimator(0), + mPropertyIndex( propertyIndex ), + mComponentIndex( componentIndex ), + mAnimatorFunction( animatorFunction ) + { + object.AddObserver( *this ); + } + + // Undefined + AnimatorConnector( const AnimatorConnector& ); + + // Undefined + AnimatorConnector& operator=( const AnimatorConnector& rhs ); + + /** + * From Object::Observer + */ + virtual void SceneObjectAdded( Object& object ) + { + //If the animator has not been created yet, create it now. + if( !mAnimator ) + { + CreateAnimator(); + } + } + + /** + * From Object::Observer + */ + virtual void SceneObjectRemoved( Object& object ) + { + } + + /** + * From Object::Observer + */ + virtual void ObjectDestroyed( Object& object ) + { + mObject = NULL; + } + + /** + * Helper function to create a Scenegraph::Animator and add it to its correspondent SceneGraph::Animation. + * @note This function will only be called the first time the object is added to the scene or at creation time if + * the object was already in the scene + */ + void CreateAnimator() + { + DALI_ASSERT_DEBUG( mAnimator == NULL ); + DALI_ASSERT_DEBUG( mAnimatorFunction != NULL ); + DALI_ASSERT_DEBUG( mParent != NULL ); + + //Get the PropertyOwner the animator is going to animate + const SceneGraph::PropertyOwner* propertyOwner = mObject->GetSceneObject(); + + //Get SceneGraph::BaseProperty + const SceneGraph::PropertyBase* baseProperty = mObject->GetSceneObjectAnimatableProperty( mPropertyIndex ); + + //Check if property is a component of another property + const int componentIndex = mObject->GetPropertyComponentIndex( mPropertyIndex ); + if( componentIndex != Property::INVALID_COMPONENT_INDEX ) + { + mComponentIndex = componentIndex; + } + + if( mComponentIndex == Property::INVALID_COMPONENT_INDEX ) + { + ///Animating the whole property + + //Cast to AnimatableProperty + const PropertyInterfaceType* animatableProperty = dynamic_cast< const PropertyInterfaceType* >( baseProperty ); + + //Dynamic cast will fail if BaseProperty is not an AnimatableProperty + DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" ); + + //Create the animator + mAnimator = AnimatorType::New( *propertyOwner, *animatableProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod ); + + } + else + { + ///Animating a component of the property + if ( PropertyTypes::Get< Vector2 >() == baseProperty->GetType() ) + { + // Animate float component of Vector2 property + + // Cast to AnimatableProperty of type Vector2 + const SceneGraph::AnimatableProperty* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty* >( baseProperty ); + + //Dynamic cast will fail if BaseProperty is not a Vector2 AnimatableProperty + DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" ); + + switch( mComponentIndex ) + { + case 0: + { + mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX >::New( *propertyOwner, + *animatableProperty, + mAnimatorFunction, + mAlphaFunction, + mTimePeriod ); + break; + } + case 1: + { + mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY >::New( *propertyOwner, + *animatableProperty, + mAnimatorFunction, + mAlphaFunction, + mTimePeriod ); + break; + } + default: + { + break; + } + } + } + else if ( PropertyTypes::Get< Vector3 >() == baseProperty->GetType() ) + { + // Animate float component of Vector3 property + + // Cast to AnimatableProperty of type Vector3 + const SceneGraph::AnimatableProperty* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty* >( baseProperty ); + + //Dynamic cast will fail if BaseProperty is not a Vector3 AnimatableProperty + DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" ); + + switch( mComponentIndex ) + { + case 0: + { + mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX >::New( *propertyOwner, + *animatableProperty, + mAnimatorFunction, + mAlphaFunction, + mTimePeriod ); + break; + } + case 1: + { + mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY >::New( *propertyOwner, + *animatableProperty, + mAnimatorFunction, + mAlphaFunction, + mTimePeriod ); + break; + } + case 2: + { + mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorZ >::New( *propertyOwner, + *animatableProperty, + mAnimatorFunction, + mAlphaFunction, + mTimePeriod ); + break; + } + default: + { + break; + } + } + } + else if ( PropertyTypes::Get< Vector4 >() == baseProperty->GetType() ) + { + // Animate float component of Vector4 property + + // Cast to AnimatableProperty of type Vector4 + const SceneGraph::AnimatableProperty* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty* >( baseProperty ); + + //Dynamic cast will fail if BaseProperty is not a Vector4 AnimatableProperty + DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" ); + + switch( mComponentIndex ) + { + case 0: + { + mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX >::New( *propertyOwner, + *animatableProperty, + mAnimatorFunction, + mAlphaFunction, + mTimePeriod ); + break; + } + case 1: + { + mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY >::New( *propertyOwner, + *animatableProperty, + mAnimatorFunction, + mAlphaFunction, + mTimePeriod ); + break; + } + case 2: + { + mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorZ >::New( *propertyOwner, + *animatableProperty, + mAnimatorFunction, + mAlphaFunction, + mTimePeriod ); + break; + } + case 3: + { + mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorW >::New( *propertyOwner, + *animatableProperty, + mAnimatorFunction, + mAlphaFunction, + mTimePeriod ); + break; + } + + default: + { + break; + } + } + } + } + + DALI_ASSERT_DEBUG( mAnimator != NULL ); + + // Add the new SceneGraph::Animator to its correspondent SceneGraph::Animation via message + const SceneGraph::Animation* animation = mParent->GetSceneObject(); + DALI_ASSERT_DEBUG( NULL != animation ); + AddAnimatorMessage( mParent->GetEventThreadServices(), *animation, *mAnimator ); + } + +protected: + + Object* mObject; ///< Not owned by the animator connector. Valid until ObjectDestroyed() is called. + SceneGraph::AnimatorBase* mAnimator; + + Property::Index mPropertyIndex; + int mComponentIndex; + + Internal::AnimatorFunctionBase* mAnimatorFunction; ///< Owned by the animator connector until an Scenegraph::Animator is created +}; + + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_ANIMATOR_CONNECTOR_H__ diff --git a/dali/internal/event/animation/constrainer.cpp b/dali/internal/event/animation/constrainer.cpp new file mode 100644 index 0000000..7e4f6a2 --- /dev/null +++ b/dali/internal/event/animation/constrainer.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +Constrainer::Constrainer() +:Object() +{ +} + +Constrainer::~Constrainer() +{ + //Remove all the constraints created by the object + size_t tag = reinterpret_cast( this ); + const ObjectIter end = mObservedObjects.End(); + for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter ) + { + //Remove Constrainer from the observers list of the object + (*iter)->RemoveObserver( *this ); + + //Remove constraints + (*iter)->RemoveConstraints( tag ); + } +} + +void Constrainer::ObjectDestroyed( Object& object ) +{ + //Remove object from the list of observed + const ObjectIter end = mObservedObjects.End(); + for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter ) + { + if( *iter == &object ) + { + mObservedObjects.Erase(iter); + return; + } + } +} + +void Constrainer::Remove( Dali::Handle& target ) +{ + size_t tag = reinterpret_cast( this ); + Object& object = GetImplementation(target); + const ObjectIter end = mObservedObjects.End(); + for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter ) + { + if( *iter == &object ) + { + //Stop observing the object + (*iter)->RemoveObserver( *this ); + + //Remove constraints created in the object + target.RemoveConstraints( tag ); + + //Remove object from the vector of observed objects + mObservedObjects.Erase(iter); + } + } +} + +void Constrainer::Observe( Dali::Handle& handle ) +{ + Object& object = GetImplementation(handle); + + //Add the object to the list of observed objects if it is not in it already + const ObjectIter end = mObservedObjects.End(); + ObjectIter iter = mObservedObjects.Begin(); + for(; iter != end; ++iter ) + { + if( *iter == &object ) + { + break; + } + } + + if( iter == end ) + { + //Start observing the object + object.AddObserver( *this ); + + //Add object in the observed objects vector + mObservedObjects.PushBack( &object ); + } +} + +} // namespace Internal + +} // namespace Dali + diff --git a/dali/internal/event/animation/constrainer.h b/dali/internal/event/animation/constrainer.h new file mode 100644 index 0000000..3b56212 --- /dev/null +++ b/dali/internal/event/animation/constrainer.h @@ -0,0 +1,174 @@ +#ifndef __DALI_INTERNAL_CONSTRAINER_H__ +#define __DALI_INTERNAL_CONSTRAINER_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +typedef Dali::Vector ObjectContainer; +typedef ObjectContainer::Iterator ObjectIter; + +/** + * An abstract base class for constrainers. + * Constrainer base class is responsible or observing constrained objects and remove all the constraints created + * when it is destroyed + */ +class Constrainer : public Object, public Object::Observer +{ +public: + + /** + * Constructor. + */ + Constrainer(); + + /** + * Virtual destructor. + */ + virtual ~Constrainer(); + +public: // Object methods + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyCount() + */ + virtual unsigned int GetDefaultPropertyCount() const{return 0;} + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices() + */ + virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const{} + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyName() + */ + virtual const char* GetDefaultPropertyName( Property::Index index ) const{return 0;} + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex() + */ + virtual Property::Index GetDefaultPropertyIndex( const std::string& name ) const{return Property::INVALID_INDEX;} + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable() + */ + virtual bool IsDefaultPropertyWritable( Property::Index index ) const{return false;} + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable() + */ + virtual bool IsDefaultPropertyAnimatable( Property::Index index ) const{return false;} + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput() + */ + virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const{return false;} + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyType() + */ + virtual Property::Type GetDefaultPropertyType( Property::Index index ) const{return Property::NONE;} + + /** + * @copydoc Dali::Internal::Object::SetDefaultProperty() + */ + virtual void SetDefaultProperty( Property::Index index, const Property::Value& propertyValue ){} + + /** + * @copydoc Dali::Internal::Object::GetDefaultProperty() + */ + virtual Property::Value GetDefaultProperty( Property::Index index ) const{return Property::Value();} + + /** + * @copydoc Dali::Internal::Object::GetSceneObject() + */ + virtual const SceneGraph::PropertyOwner* GetSceneObject() const{return 0;} + + /** + * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty() + */ + virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const{return 0;} + + /** + * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty() + */ + virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const{return 0;} + +public: // Object::Observer methods + + /** + * @copydoc Object::Observer::SceneObjectAdded() + */ + virtual void SceneObjectAdded( Object& object ){} + + /** + * @copydoc Object::Observer::SceneObjectRemoved() + */ + virtual void SceneObjectRemoved( Object& object ){} + + /** + * @copydoc Object::Observer::ObjectDestroyed() + */ + virtual void ObjectDestroyed( Object& object ); + +public: + + /** + * @brief Applies the constraint to the target property + + * @param[in] target Property to be constrained + * @param[in] source Property used as parameter for the path + * @param[in] range The range of values in the source property which will be mapped to [0,1] + * @param[in] wrap Wrapping domain. Source property will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1] + */ + virtual void Apply( Property target, Property source, const Vector2& range, const Vector2& wrap) = 0; + + /** + * @brief Removes the constraint in the target object + * + * @param[in] target A handle to an object constrained by the Constrainer + */ + void Remove( Dali::Handle& target ); + +protected: + + /** + * @brief Adds an object to the list of observed objects + * + * @param[in] handle A handle to the object to be observed + */ + void Observe( Dali::Handle& handle ); + +private: + + ObjectContainer mObservedObjects; ///< The list of object which have been constrained by the Constrainer +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_CONSTRAINER_H__ diff --git a/dali/internal/event/animation/constraint-base.cpp b/dali/internal/event/animation/constraint-base.cpp new file mode 100644 index 0000000..f781543 --- /dev/null +++ b/dali/internal/event/animation/constraint-base.cpp @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include + +using Dali::Internal::SceneGraph::AnimatableProperty; + +namespace Dali +{ + +namespace Internal +{ + +ConstraintBase::ConstraintBase( Object& object, Property::Index targetPropertyIndex, SourceContainer& sources ) +: mEventThreadServices( *Stage::GetCurrent() ), + mTargetObject( &object ), + mSceneGraphConstraint( NULL ), + mSources( sources ), + mObservedObjects(), + mTargetPropertyIndex( targetPropertyIndex ), + mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ), + mTag( 0 ), + mApplied( false ), + mSourceDestroyed( false ) +{ + ObserveObject( object ); +} + +ConstraintBase::~ConstraintBase() +{ + StopObservation(); + + RemoveInternal(); +} + +void ConstraintBase::AddSource( Source source ) +{ + mSources.push_back( source ); + + // Observe the object providing this property + if ( OBJECT_PROPERTY == source.sourceType ) + { + if ( source.object != NULL ) + { + ObserveObject( *source.object ); + } + else + { + DALI_LOG_ERROR( "Constraint source object not found" ); + } + } +} + +void ConstraintBase::Apply() +{ + if ( mTargetObject && !mApplied && !mSourceDestroyed ) + { + mApplied = true; + ConnectConstraint(); + + mTargetObject->ApplyConstraint( *this ); + } +} + +void ConstraintBase::Remove() +{ + RemoveInternal(); + + if( mTargetObject ) + { + mTargetObject->RemoveConstraint( *this ); + } +} + +void ConstraintBase::RemoveInternal() +{ + if ( mApplied ) + { + mApplied = false; + + // Guard against constraint sending messages during core destruction + if( Stage::IsInstalled() ) + { + const SceneGraph::PropertyOwner* propertyOwner = mTargetObject ? mTargetObject->GetSceneObject() : NULL; + + if ( propertyOwner && + mSceneGraphConstraint ) + { + // Remove from scene-graph + RemoveConstraintMessage( GetEventThreadServices(), *propertyOwner, *(mSceneGraphConstraint) ); + + // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer + mSceneGraphConstraint = NULL; + } + } + } +} + +Object* ConstraintBase::GetParent() +{ + return mTargetObject; +} + +Dali::Handle ConstraintBase::GetTargetObject() +{ + return Dali::Handle( mTargetObject ); +} + +Property::Index ConstraintBase::GetTargetProperty() +{ + return mTargetPropertyIndex; +} + +void ConstraintBase::SetRemoveAction( ConstraintBase::RemoveAction action ) +{ + mRemoveAction = action; +} + +ConstraintBase::RemoveAction ConstraintBase::GetRemoveAction() const +{ + return mRemoveAction; +} + +void ConstraintBase::SetTag(const unsigned int tag) +{ + mTag = tag; +} + +unsigned int ConstraintBase::GetTag() const +{ + return mTag; +} + +void ConstraintBase::SceneObjectAdded( Object& object ) +{ + if ( mApplied && + ( NULL == mSceneGraphConstraint ) && + mTargetObject ) + { + ConnectConstraint(); + } +} + +void ConstraintBase::SceneObjectRemoved( Object& object ) +{ + if ( mSceneGraphConstraint ) + { + // An input property owning source has been deleted, need to tell the scene-graph-constraint owner to remove it + if ( &object != mTargetObject ) + { + const SceneGraph::PropertyOwner* propertyOwner = mTargetObject ? mTargetObject->GetSceneObject() : NULL; + + if( propertyOwner ) + { + // Remove from scene-graph + RemoveConstraintMessage( GetEventThreadServices(), *propertyOwner, *(mSceneGraphConstraint) ); + } + } + + // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer + mSceneGraphConstraint = NULL; + } +} + +void ConstraintBase::ObjectDestroyed( Object& object ) +{ + // Remove object pointer from observation set + ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object ); + DALI_ASSERT_DEBUG( mObservedObjects.End() != iter ); + mObservedObjects.Erase( iter ); + + // Constraint is not useful anymore as an input-source has been destroyed + mSourceDestroyed = true; + + // Stop observing the remaining objects + StopObservation(); + + // Clear our sources as well + mSources.clear(); + + // Discard all object & scene-graph pointers + mSceneGraphConstraint = NULL; + mTargetObject = NULL; +} + +void ConstraintBase::ObserveObject( Object& object ) +{ + ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object ); + if ( mObservedObjects.End() == iter ) + { + object.AddObserver( *this ); + mObservedObjects.PushBack( &object ); + } +} + +void ConstraintBase::StopObservation() +{ + const ObjectIter end = mObservedObjects.End(); + for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter ) + { + (*iter)->RemoveObserver( *this ); + } + + mObservedObjects.Clear(); +} + +} // namespace Internal + +} // namespace Dali diff --git a/dali/internal/event/animation/constraint-base.h b/dali/internal/event/animation/constraint-base.h new file mode 100644 index 0000000..5b006ed --- /dev/null +++ b/dali/internal/event/animation/constraint-base.h @@ -0,0 +1,238 @@ +#ifndef __DALI_INTERNAL_ACTIVE_CONSTRAINT_BASE_H__ +#define __DALI_INTERNAL_ACTIVE_CONSTRAINT_BASE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +class EventThreadServices; +class Object; +typedef Dali::Vector ObjectContainer; +typedef ObjectContainer::Iterator ObjectIter; + +namespace SceneGraph +{ +class ConstraintBase; + +template +class AnimatableProperty; +} + +/** + * An abstract base class for active constraints. + */ +class ConstraintBase : public BaseObject, public Object::Observer +{ +public: + + typedef Dali::Constraint::RemoveAction RemoveAction; + + /** + * Constructor. + * @param[in] object The property owning object. + * @param[in] messageController Used to send messages to the update-thread. + * @param[in] targetPropertyIndex The index of the property being constrained. + * @param[in] sources The sources of the input properties. + */ + ConstraintBase( Object& object, Property::Index targetPropertyIndex, SourceContainer& sources ); + + /** + * Clone this constraint for another object. + * @param[in] object The object to clone this constraint for + * @return A new constraint. + */ + virtual ConstraintBase* Clone( Object& object ) = 0; + + /** + * Virtual destructor. + */ + virtual ~ConstraintBase(); + + /** + * Adds a constraint source to the constraint + * + * @param[in] source The constraint source input to add + */ + void AddSource( Source source ); + + /** + * @copydoc Dali::Constraint::Apply() + */ + void Apply(); + + /** + * @copydoc Dali::Constraint::Remove() + */ + void Remove(); + + /** + * Called when the Constraint is removed. + * + * @note This removes the scene-object as well but then does not call back into the target-object. + */ + void RemoveInternal(); + + /** + * Retrieve the parent of the constraint. + * @return The parent object, or NULL. + */ + Object* GetParent(); + + /** + * @copydoc Dali::Constraint::GetTargetObject() + */ + Dali::Handle GetTargetObject(); + + /** + * @copydoc Dali::Constraint::GetTargetProperty() + */ + Property::Index GetTargetProperty(); + + /** + * @copydoc Dali::Constraint::SetRemoveAction() + */ + void SetRemoveAction(RemoveAction action); + + /** + * @copydoc Dali::Constraint::GetRemoveAction() + */ + RemoveAction GetRemoveAction() const; + + /** + * @copydoc Dali::Constraint::SetTag() + */ + void SetTag(const unsigned int tag); + + /** + * @copydoc Dali::Constraint::GetTag() + */ + unsigned int GetTag() const; + +private: // Object::Observer methods + + /** + * @copydoc Object::Observer::SceneObjectAdded() + */ + virtual void SceneObjectAdded( Object& object ); + + /** + * @copydoc Object::Observer::SceneObjectRemoved() + */ + virtual void SceneObjectRemoved( Object& object ); + + /** + * @copydoc Object::Observer::ObjectDestroyed() + */ + virtual void ObjectDestroyed( Object& object ); + +private: + + /** + * Helper to observe an object, if not already observing it + */ + void ObserveObject( Object& object ); + + /** + * Helper to stop observing objects + */ + void StopObservation(); + + // To be implemented in derived classes + + /** + * Create and connect a constraint for a scene-object. + */ + virtual void ConnectConstraint() = 0; + +protected: + + /** + * Get the event thread services object - used for sending messages to the scene graph + * Assert if called from the wrong thread. + * This is intentionally inline for performance reasons. + * + * @return The event thread services object + */ + inline EventThreadServices& GetEventThreadServices() + { + DALI_ASSERT_DEBUG( EventThreadServices::IsCoreRunning() ); + return mEventThreadServices; + } + + /** + * Get the event thread services object - used for sending messages to the scene graph + * Assert if called from the wrong thread + * This is intentionally inline for performance reasons. + * + * @return The event thread services object + */ + inline const EventThreadServices& GetEventThreadServices() const + { + DALI_ASSERT_DEBUG( EventThreadServices::IsCoreRunning() ); + return mEventThreadServices; + } + +protected: + EventThreadServices& mEventThreadServices; + Object* mTargetObject; ///< The object owns the constraint. + const SceneGraph::ConstraintBase* mSceneGraphConstraint; + SourceContainer mSources; + ObjectContainer mObservedObjects; // We don't observe the same object twice + Property::Index mTargetPropertyIndex; + RemoveAction mRemoveAction; + unsigned int mTag; + bool mApplied:1; ///< Whether the constraint has been applied + bool mSourceDestroyed:1; ///< Is set to true if any of our input source objects are destroyed +}; + +} // namespace Internal + +// Helpers for public-api forwarding methods + +inline Internal::ConstraintBase& GetImplementation(Dali::Constraint& constraint) +{ + DALI_ASSERT_ALWAYS( constraint && "Constraint handle is empty" ); + + BaseObject& handle = constraint.GetBaseObject(); + + return static_cast(handle); +} + +inline const Internal::ConstraintBase& GetImplementation(const Dali::Constraint& constraint) +{ + DALI_ASSERT_ALWAYS( constraint && "Constraint handle is empty" ); + + const BaseObject& handle = constraint.GetBaseObject(); + + return static_cast(handle); +} + +} // namespace Dali + +#endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_BASE_H__ diff --git a/dali/internal/event/animation/constraint-impl.h b/dali/internal/event/animation/constraint-impl.h new file mode 100644 index 0000000..45d17ab --- /dev/null +++ b/dali/internal/event/animation/constraint-impl.h @@ -0,0 +1,578 @@ +#ifndef __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__ +#define __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * Helper to add only unique entries to the propertyOwner container + * @param propertyOwners to add the entries to + * @param object to add + */ +inline void AddUnique( SceneGraph::PropertyOwnerContainer& propertyOwners, SceneGraph::PropertyOwner* object ) +{ + const SceneGraph::PropertyOwnerIter iter = std::find( propertyOwners.Begin(), propertyOwners.End(), object ); + if( iter == propertyOwners.End() ) + { + // each owner should only be added once + propertyOwners.PushBack( object ); + } +} + +/** + * Connects a constraint which takes another property as an input. + */ +template < typename PropertyType > +class Constraint : public ConstraintBase +{ +public: + + typedef SceneGraph::Constraint< PropertyType, PropertyAccessor > SceneGraphConstraint; + typedef const SceneGraph::AnimatableProperty* ScenePropertyPtr; + typedef typename PropertyConstraintPtr::Type ConstraintFunctionPtr; + + /** + * Construct a new constraint. + * @param[in] object The property-owning object. + * @param[in] targetIndex The index of the property to constrain. + * @param[in] sources The sources of the input properties passed to func. + * @param[in] func The constraint function. + * @return A newly allocated active-constraint. + */ + static ConstraintBase* New( Object& object, + Property::Index targetIndex, + SourceContainer& sources, + ConstraintFunctionPtr func ) + { + return new Constraint< PropertyType >( object, targetIndex, sources, func ); + } + + /** + * @copydoc ConstraintBase::Clone() + */ + virtual ConstraintBase* Clone( Object& object ) + { + DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" ); + + ConstraintBase* clone( NULL ); + + ConstraintFunctionPtr funcPtr( mUserFunction->Clone() ); + + clone = new Constraint< PropertyType >( object, + mTargetIndex, + mSources, + funcPtr ); + + clone->SetRemoveAction(mRemoveAction); + clone->SetTag( mTag ); + + return clone; + } + + + /** + * Virtual destructor. + */ + virtual ~Constraint() + { + // This is not responsible for removing constraints. + } + +private: + + /** + * Private constructor; see also Constraint::New(). + */ + Constraint( Object& object, + Property::Index targetIndex, + SourceContainer& sources, + ConstraintFunctionPtr& func ) + : ConstraintBase( object, targetIndex, sources ), + mTargetIndex( targetIndex ), + mUserFunction( func ) + { + } + + // Undefined + Constraint( const Constraint& ); + + // Undefined + Constraint& operator=( const Constraint& rhs ); + + /** + * Create and connect a constraint for a scene-object. + */ + void ConnectConstraint() + { + // Should not come here if target-object has been destroyed + DALI_ASSERT_DEBUG( NULL != mTargetObject ); + + // Guard against double connections + DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint ); + + // Short-circuit until the target scene-object exists + SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() ); + if ( NULL == targetObject ) + { + return; + } + + // Build a container of property-owners, providing the scene-graph properties + SceneGraph::PropertyOwnerContainer propertyOwners; + propertyOwners.PushBack( targetObject ); + + // Build the constraint function; this requires a scene-graph property from each source + ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) ); + + if ( func ) + { + // Create the SceneGraphConstraint, and connect to the scene-graph + + const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex ); + + // The targetProperty should exist, when targetObject exists + DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" ); + + // Connect the constraint + SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, + propertyOwners, + func ); + DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint ); + sceneGraphConstraint->SetRemoveAction( mRemoveAction ); + + // object is being used in a separate thread; queue a message to apply the constraint + ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint ); + + // Keep a raw-pointer to the scene-graph constraint + mSceneGraphConstraint = sceneGraphConstraint; + } + } + + /** + * Helper for ConnectConstraint. Creates a connected constraint-function. + * Also populates the property-owner container, for each input connected to the constraint-function. + * @param[out] propertyOwners The container of property-owners providing the scene-graph properties. + * @return A connected constraint-function, or NULL if the scene-graph properties are not available. + */ + PropertyConstraint* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners ) + { + PropertyConstraint* func = mUserFunction->Clone(); + + for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter ) + { + Source& source = *iter; + + PropertyInputImpl* inputProperty( NULL ); + int componentIndex( Property::INVALID_COMPONENT_INDEX ); + + if ( OBJECT_PROPERTY == source.sourceType ) + { + DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) ); + + SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() ); + + // The property owner will not exist, if the target object is off-stage + if( NULL != owner ) + { + AddUnique( propertyOwners, owner ); + inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) ); + componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex ); + + // The scene-object property should exist, when the property owner exists + DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" ); + } + } + else if ( LOCAL_PROPERTY == source.sourceType ) + { + DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) ); + + inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) ); + componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex ); + + // The target scene-object should provide this property + DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" ); + } + else + { + DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" ); + + Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent(); + + // This will not exist, if the target object is off-stage + if ( NULL != objectParent ) + { + DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) ); + + SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() ); + + // The property owner will not exist, if the parent object is off-stage + if ( NULL != owner ) + { + AddUnique( propertyOwners, owner ); + inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) ); + componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex ); + + // The scene-object property should exist, when the property owner exists + DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" ); + } + } + } + + if ( NULL == inputProperty ) + { + delete func; + func = NULL; + + // Exit if a scene-graph object is not available from one of the sources + break; + } + + func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty ); + } + + return func; + } + +protected: + + Property::Index mTargetIndex; + + ConstraintFunctionPtr mUserFunction; +}; + +/** + * Variant which allows float components to be animated individually. + */ +template <> +class Constraint : public ConstraintBase +{ +public: + + typedef typename PropertyConstraintPtr::Type ConstraintFunctionPtr; + + /** + * Construct a new constraint. + * @param[in] object The property-owning object. + * @param[in] targetIndex The index of the property to constrain. + * @param[in] sources The sources of the input properties passed to func. + * @param[in] func The constraint function. + * @return A newly allocated constraint. + */ + static ConstraintBase* New( Object& object, + Property::Index targetIndex, + SourceContainer& sources, + ConstraintFunctionPtr func ) + { + return new Constraint< float >( object, targetIndex, sources, func ); + } + + /** + * @copydoc ConstraintBase::Clone() + */ + virtual ConstraintBase* Clone( Object& object ) + { + DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" ); + + ConstraintBase* clone( NULL ); + + ConstraintFunctionPtr funcPtr( mUserFunction->Clone() ); + + clone = new Constraint< float >( object, + mTargetIndex, + mSources, + funcPtr ); + + clone->SetRemoveAction(mRemoveAction); + clone->SetTag( mTag ); + + return clone; + } + + /** + * Virtual destructor. + */ + virtual ~Constraint() + { + // This is not responsible for removing constraints. + } + +private: + + /** + * Private constructor; see also Constraint::New(). + */ + Constraint( Object& object, + Property::Index targetIndex, + SourceContainer& sources, + ConstraintFunctionPtr& func ) + : ConstraintBase( object, targetIndex, sources ), + mTargetIndex( targetIndex ), + mUserFunction( func ) + { + } + + // Undefined + Constraint( const Constraint& ); + + // Undefined + Constraint& operator=( const Constraint& rhs ); + + /** + * Create and connect a constraint for a scene-object. + */ + void ConnectConstraint() + { + // Should not come here if target-object has been destroyed + DALI_ASSERT_DEBUG( NULL != mTargetObject ); + + // Guard against double connections + DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint ); + + // Short-circuit until the target scene-object exists + SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() ); + if ( NULL == targetObject ) + { + return; + } + + // Build a container of property-owners, providing the scene-graph properties + SceneGraph::PropertyOwnerContainer propertyOwners; + propertyOwners.PushBack( targetObject ); + + // Build the constraint function; this requires a scene-graph property from each source + ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) ); + + if ( func ) + { + // Create the SceneGraphConstraint, and connect to the scene-graph + + const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex ); + + // The targetProperty should exist, when targetObject exists + DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" ); + + const int componentIndex = mTargetObject->GetPropertyComponentIndex( mTargetIndex ); + + SceneGraph::ConstraintBase* sceneGraphConstraint( NULL ); + + if ( Property::INVALID_COMPONENT_INDEX == componentIndex ) + { + // Not a Vector2, Vector3 or Vector4 component, expecting float type + DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == targetProperty->GetType() ); + + typedef SceneGraph::Constraint< float, PropertyAccessor > SceneGraphConstraint; + + sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, + propertyOwners, + func ); + } + else + { + // Expecting Vector2, Vector3 or Vector4 type + + if ( PropertyTypes::Get< Vector2 >() == targetProperty->GetType() ) + { + // Constrain float component of Vector2 property + + if ( 0 == componentIndex ) + { + typedef SceneGraph::Constraint< float, PropertyComponentAccessorX > SceneGraphConstraint; + sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func ); + } + else if ( 1 == componentIndex ) + { + typedef SceneGraph::Constraint< float, PropertyComponentAccessorY > SceneGraphConstraint; + sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func ); + } + } + else if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() ) + { + // Constrain float component of Vector3 property + + if ( 0 == componentIndex ) + { + typedef SceneGraph::Constraint< float, PropertyComponentAccessorX > SceneGraphConstraint; + sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func ); + } + else if ( 1 == componentIndex ) + { + typedef SceneGraph::Constraint< float, PropertyComponentAccessorY > SceneGraphConstraint; + sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func ); + } + else if ( 2 == componentIndex ) + { + typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ > SceneGraphConstraint; + sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func ); + } + } + else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() ) + { + // Constrain float component of Vector4 property + + if ( 0 == componentIndex ) + { + typedef SceneGraph::Constraint< float, PropertyComponentAccessorX > SceneGraphConstraint; + sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func ); + } + else if ( 1 == componentIndex ) + { + typedef SceneGraph::Constraint< float, PropertyComponentAccessorY > SceneGraphConstraint; + sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func ); + } + else if ( 2 == componentIndex ) + { + typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ > SceneGraphConstraint; + sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func ); + } + else if ( 3 == componentIndex ) + { + typedef SceneGraph::Constraint< float, PropertyComponentAccessorW > SceneGraphConstraint; + sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func ); + } + } + } + + DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint ); + sceneGraphConstraint->SetRemoveAction( mRemoveAction ); + + // object is being used in a separate thread; queue a message to apply the constraint + ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint ); + + // Keep a raw-pointer to the scene-graph constraint + mSceneGraphConstraint = sceneGraphConstraint; + } + } + + /** + * Helper for ConnectConstraint. Creates a connected constraint-function. + * Also populates the property-owner container, for each input connected to the constraint-function. + * @param[out] propertyOwners The container of property-owners providing the scene-graph properties. + * @return A connected constraint-function, or NULL if the scene-graph properties are not available. + */ + PropertyConstraint* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners ) + { + PropertyConstraint* func = mUserFunction->Clone(); + + for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter ) + { + Source& source = *iter; + + PropertyInputImpl* inputProperty( NULL ); + int componentIndex( Property::INVALID_COMPONENT_INDEX ); + + if ( OBJECT_PROPERTY == source.sourceType ) + { + DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) ); + + SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() ); + + // The property owner will not exist, if the target object is off-stage + if( NULL != owner ) + { + AddUnique( propertyOwners, owner ); + inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) ); + componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex ); + + // The scene-object property should exist, when the property owner exists + DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" ); + } + } + else if ( LOCAL_PROPERTY == source.sourceType ) + { + DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) ); + + inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) ); + componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex ); + + // The target scene-object should provide this property + DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" ); + } + else + { + DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" ); + + Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent(); + + // This will not exist, if the target object is off-stage + if ( NULL != objectParent ) + { + DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) ); + + SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() ); + + // The property owner will not exist, if the parent object is off-stage + if ( NULL != owner ) + { + AddUnique( propertyOwners, owner ); + inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) ); + componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex ); + + // The scene-object property should exist, when the property owner exists + DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" ); + } + } + } + + if ( NULL == inputProperty ) + { + delete func; + func = NULL; + + // Exit if a scene-graph object is not available from one of the sources + break; + } + + func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty ); + } + + return func; + } + +protected: + + Property::Index mTargetIndex; + + ConstraintFunctionPtr mUserFunction; +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__ diff --git a/dali/internal/event/animation/constraint-source-impl.h b/dali/internal/event/animation/constraint-source-impl.h new file mode 100644 index 0000000..8e1d2c1 --- /dev/null +++ b/dali/internal/event/animation/constraint-source-impl.h @@ -0,0 +1,78 @@ +#ifndef __DALI_INTERNAL_CONSTRAINT_SOURCE_H__ +#define __DALI_INTERNAL_CONSTRAINT_SOURCE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +struct Source; +typedef std::vector SourceContainer; +typedef SourceContainer::iterator SourceIter; + +/** + * The source of an input property for a constraint. + */ +struct Source +{ + /** + * Default constructor + */ + Source() + : sourceType( OBJECT_PROPERTY ), + propertyIndex( Property::INVALID_INDEX ), + object( NULL ) + { + } + + /** + * Create a constraint source from a public handle. + * The internal object is not referenced by the Internal::Source; therefore + * the owner of this object is responsible for observing the Object's lifetime. + */ + Source( Dali::ConstraintSource& source ) + : sourceType( source.sourceType ), + propertyIndex( source.propertyIndex ), + object( NULL ) + { + if ( source.object ) + { + object = &dynamic_cast< Object& > ( GetImplementation(source.object) ); + } + } + + SourceType sourceType; ///< The source type + + Property::Index propertyIndex; ///< The index of the source property + + Object* object; ///< The target object; only valid if sourceType == OBJECT_PROPERTY +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_CONSTRAINT_SOURCE_H__ diff --git a/dali/internal/event/animation/key-frame-channel.h b/dali/internal/event/animation/key-frame-channel.h new file mode 100644 index 0000000..bba814f --- /dev/null +++ b/dali/internal/event/animation/key-frame-channel.h @@ -0,0 +1,206 @@ +#ifndef __DALI_INTERNAL_KEY_FRAME_CHANNEL_H__ +#define __DALI_INTERNAL_KEY_FRAME_CHANNEL_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ +namespace Internal +{ + +class KeyFrameChannelBase +{ +public: + enum KeyFrameChannelId + { + Translate, Rotate, Scale, + }; + + KeyFrameChannelBase(KeyFrameChannelId channel_id) + : mChannelId(channel_id) + { + } + + virtual ~KeyFrameChannelBase() + { + } + + KeyFrameChannelId GetId() const + { + return mChannelId; + } + + virtual bool IsActive(float progress) = 0; + +protected: + KeyFrameChannelId mChannelId; +}; + + +template +class KeyFrameChannel : public KeyFrameChannelBase +{ +public: + typedef std::vector > ProgressValues; + + KeyFrameChannel(KeyFrameChannelId channel_id, ProgressValues& values ) + : KeyFrameChannelBase(channel_id), + mValues(values) + { + } + + + virtual ~KeyFrameChannel() + { + } + + bool IsActive (float progress); + + V GetValue(float progress, Dali::Animation::Interpolation interpolation) const; + + bool FindInterval(typename ProgressValues::iterator& start, + typename ProgressValues::iterator& end, + float progress) const; + + ProgressValues& mValues; +}; + +template +bool KeyFrameChannel::IsActive (float progress) +{ + bool active = false; + if(!mValues.empty()) + { + ProgressValue& first = mValues.front(); + + if( progress >= first.GetProgress() ) + { + active = true; + } + } + return active; +} + +/** + * Use a linear search to find the interval containing progress + * TODO: Use binary search instead + */ +template +bool KeyFrameChannel::FindInterval( + typename ProgressValues::iterator& start, + typename ProgressValues::iterator& end, + float progress) const +{ + bool found = false; + typename std::vector >::iterator iter = mValues.begin(); + typename std::vector >::iterator prevIter = iter; + + while(iter != mValues.end() && iter->GetProgress() <= progress) + { + prevIter = iter; + ++iter; + } + + if(iter == mValues.end()) + { + --prevIter; + --iter; + } + + if(prevIter->GetProgress() <= progress + && + iter->GetProgress() > progress) + { + found = true; + start = prevIter; + end = iter; + } + + return found; +} + +template +V KeyFrameChannel::GetValue (float progress, Dali::Animation::Interpolation interpolation) const +{ + ProgressValue& firstPV = mValues.front(); + + typename std::vector >::iterator start; + typename std::vector >::iterator end; + + V interpolatedV = firstPV.GetValue(); + if(progress >= mValues.back().GetProgress() ) + { + interpolatedV = mValues.back().GetValue(); // This should probably be last value... + } + else if(FindInterval(start, end, progress)) + { + float frameProgress = (progress - start->GetProgress()) / (end->GetProgress() - start->GetProgress()); + + if( interpolation == Dali::Animation::Linear ) + { + Interpolate(interpolatedV, start->GetValue(), end->GetValue(), frameProgress); + } + else + { + //Calculate prev and next values + V prev; + if( start != mValues.begin() ) + { + prev = (start-1)->GetValue(); + } + else + { + //Project next value through start point + prev = start->GetValue() + (start->GetValue()-(start+1)->GetValue()); + } + + V next; + if( end != mValues.end()-1) + { + next = (end+1)->GetValue(); + } + else + { + //Project prev value through end point + next = end->GetValue() + (end->GetValue()-(end-1)->GetValue()); + } + + CubicInterpolate(interpolatedV, prev, start->GetValue(), end->GetValue(), next, frameProgress); + } + } + + return interpolatedV; +} + +typedef KeyFrameChannel KeyFrameChannelNumber; +typedef KeyFrameChannel KeyFrameChannelVector2; +typedef KeyFrameChannel KeyFrameChannelVector3; +typedef KeyFrameChannel KeyFrameChannelVector4; +typedef KeyFrameChannel KeyFrameChannelQuaternion; +typedef KeyFrameChannel KeyFrameChannelAngleAxis; + + +} // Internal +} // namespace Dali + +#endif // __DALI_INTERNAL_KEY_FRAME_CHANNEL_H__ diff --git a/dali/internal/event/animation/key-frames-impl.cpp b/dali/internal/event/animation/key-frames-impl.cpp new file mode 100644 index 0000000..4e0c3ed --- /dev/null +++ b/dali/internal/event/animation/key-frames-impl.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +namespace Dali +{ +namespace Internal +{ + +KeyFrames* KeyFrames::New() +{ + return new KeyFrames(); +} + +KeyFrames::KeyFrames() + : mType(Property::NONE), + mKeyFrames(NULL) +{ +} + +KeyFrames::~KeyFrames() +{ +} + + +void KeyFrames::CreateKeyFramesSpec(Property::Type type) +{ + mType = type; + // Now we have a type, can create specific implementation + switch(type) + { + case Property::BOOLEAN: + { + mKeyFrames = Internal::KeyFrameBoolean::New(); + break; + } + case Property::INTEGER: + { + mKeyFrames = Internal::KeyFrameInteger::New(); + break; + } + case Property::FLOAT: + { + mKeyFrames = Internal::KeyFrameNumber::New(); + break; + } + case Property::VECTOR2: + { + mKeyFrames = Internal::KeyFrameVector2::New(); + break; + } + case Property::VECTOR3: + { + mKeyFrames = Internal::KeyFrameVector3::New(); + break; + } + case Property::VECTOR4: + { + mKeyFrames = Internal::KeyFrameVector4::New(); + break; + } + case Property::ROTATION: + { + mKeyFrames = Internal::KeyFrameQuaternion::New(); + break; + } + default: + { + DALI_ASSERT_DEBUG(!"Type not supported"); + break; + } + } +} + +Property::Type KeyFrames::GetType() const +{ + return mType; +} + +void KeyFrames::Add(float time, Property::Value value, AlphaFunction alpha) +{ + if(mType == Property::NONE) + { + CreateKeyFramesSpec(value.GetType()); + } + + // Once we have created a type, can only add values of the same type + DALI_ASSERT_ALWAYS( mType == value.GetType() && "Can only add values of the same type to a KeyFrame" ); + + DALI_ASSERT_DEBUG(mKeyFrames); + + switch(mType) + { + case Property::BOOLEAN: + { + Internal::KeyFrameBoolean* kf = static_cast(mKeyFrames.Get()); + kf->AddKeyFrame(time, value.Get(), alpha); + break; + } + case Property::INTEGER: + { + Internal::KeyFrameInteger* kf = static_cast(mKeyFrames.Get()); + kf->AddKeyFrame(time, value.Get(), alpha); + break; + } + case Property::FLOAT: + { + Internal::KeyFrameNumber* kf = static_cast(mKeyFrames.Get()); + kf->AddKeyFrame(time, value.Get(), alpha); + break; + } + case Property::VECTOR2: + { + Internal::KeyFrameVector2* kf = static_cast(mKeyFrames.Get()); + kf->AddKeyFrame(time, value.Get(), alpha); + break; + } + case Property::VECTOR3: + { + Internal::KeyFrameVector3* kf = static_cast(mKeyFrames.Get()); + kf->AddKeyFrame(time, value.Get(), alpha); + break; + } + case Property::VECTOR4: + { + Internal::KeyFrameVector4* kf = static_cast(mKeyFrames.Get()); + kf->AddKeyFrame(time, value.Get(), alpha); + break; + } + case Property::ROTATION: + { + Internal::KeyFrameQuaternion* kf = static_cast(mKeyFrames.Get()); + kf->AddKeyFrame(time, value.Get(), alpha); + break; + } + default: + DALI_ASSERT_DEBUG(!"Type not supported"); + break; + } +} + +KeyFrameSpec* KeyFrames::GetKeyFramesBase() const +{ + return mKeyFrames.Get(); +} + +} // Internal +} // Dali diff --git a/dali/internal/event/animation/key-frames-impl.h b/dali/internal/event/animation/key-frames-impl.h new file mode 100644 index 0000000..90a865e --- /dev/null +++ b/dali/internal/event/animation/key-frames-impl.h @@ -0,0 +1,358 @@ +#ifndef __DALI_INTERNAL_KEY_FRAMES_H__ +#define __DALI_INTERNAL_KEY_FRAMES_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +namespace Dali +{ +namespace Internal +{ +class KeyFrameSpec; +class KeyFrames; +typedef IntrusivePtr KeyFramesPtr; + + +/** + * KeyFrames class is responsible for creating and building a specialized KeyFrame class + * from the Property::Value type used in Add. + */ +class KeyFrames : public BaseObject +{ +public: + static KeyFrames* New(); + + /** + * Instantiate an empty KeyFrames object + */ + KeyFrames(); + +protected: + virtual ~KeyFrames(); + +private: + /** + * Don't allow copy constructor + */ + KeyFrames(const KeyFrames& rhs); + + /** + * Don't allow copy operator + */ + KeyFrames& operator=(const KeyFrames& rhs); + + /** + * Create a specialization from the given type, and store it to the mSpec + * member variable + */ + void CreateKeyFramesSpec(Property::Type type); + +public: + /** + * Get the type of this key frame. + * An empty key frame will return Property::NONE, wheras an initialised + * key frame object will return the type of it's first element. + * @return the Property::Type of the key frame values + */ + Property::Type GetType() const; + + /** + * Add a key frame. The first key frame to be added denotes the type + * of all subsequent key frames. If a value with a different type is + * added, it will throw a run time assert. + * @param[in] time The time (between 0 and 1) + * @param[in] value The value of the keyframe at the given time + * @param[in] alpha An alpha function to blend between this key frame and the + * next key frame. + */ + void Add(float time, Property::Value value, AlphaFunction alpha); + + /** + * Return the key frames without specialization. The GetSpecialization methods + * below will convert to the specialized objects. + */ + KeyFrameSpec* GetKeyFramesBase() const; + +private: + Dali::Property::Type mType; // Type of the specialization + IntrusivePtr mKeyFrames; // Pointer to the specialized key frame object +}; + + +/** + * This is the base class for the individual template specializations, allowing a ptr to be + * stored in the handle object above. It inherits from RefObject to allow smart pointers + * to be used for the specializations. Note that the derived template class below + * allows for a copy constructor so that the specialization object can be cloned before + * being passed to the scene-graph for animation. + */ +class KeyFrameSpec : public RefObject +{ +public: + + KeyFrameSpec() {} + + virtual unsigned int GetNumberOfKeyFrames() const = 0; + +protected: + + /** + * A reference counted object may only be deleted by calling Unreference() + */ + virtual ~KeyFrameSpec() {} +}; + + +/** + * The base template class for each key frame specialization. It stores a vector of + * ProgressValue pairs in mPVs, and uses the existing interface for KeyFrameChannel + * to point at this vector. + * TODO: Incorporate KeyFrameChannel into this base template + */ +template +class KeyFrameBaseSpec : public KeyFrameSpec +{ +private: + typedef ProgressValue PV; + typedef std::vector PVContainer; + + PVContainer mPVs; // The ProgressValue pairs + KeyFrameChannel* mKeyFrames; // The key frame interpolator + +public: + static KeyFrameBaseSpec* New() + { + return new KeyFrameBaseSpec(); + } + + static KeyFrameBaseSpec* Clone(const KeyFrameBaseSpec& keyFrames) + { + return new KeyFrameBaseSpec(keyFrames); + } + + /** + * Constructor + */ + KeyFrameBaseSpec() + { + mKeyFrames = new KeyFrameChannel(KeyFrameChannelBase::Translate, mPVs); + } + +protected: + /** + * Copy Constructor + * Allow cloning of this object + */ + KeyFrameBaseSpec(const KeyFrameBaseSpec& keyFrames) + : mPVs(keyFrames.mPVs) + { + mKeyFrames = new KeyFrameChannel(KeyFrameChannelBase::Translate, mPVs); + } + + KeyFrameBaseSpec& operator=( const KeyFrameBaseSpec& keyFrames ) + { + mPVs.clear(); + mPVs = keyFrames.mPVs; + delete mKeyFrames; + mKeyFrames = new KeyFrameChannel(KeyFrameChannelBase::Translate, mPVs); + return *this; + } + + /** + * Destructor. Ensure progress value pairs are cleared down + */ + virtual ~KeyFrameBaseSpec() + { + delete mKeyFrames; + mPVs.clear(); + } + +public: + /** + * Add a key frame to the progress value vector. Key frames should be added + * in time order (this method does not sort the vector by time) + * @param[in] t - progress + * @param[in] v - value + * @param[in] alpha - Alpha function for blending to the next keyframe + */ + void AddKeyFrame(float t, V v, AlphaFunction alpha) + { + // TODO:: Support alpha + mPVs.push_back(PV(t, v)); + } + + /** + * Get the number of key frames + * @return The size of the progress value vector + */ + virtual unsigned int GetNumberOfKeyFrames() const + { + return mPVs.size(); + } + + /** + * Get a key frame. + * @param[in] index The index of the key frame to fetch + * @param[out] time The progress of the given key frame + * @param[out] value The value of the given key frame + */ + virtual void GetKeyFrame(unsigned int index, float& time, V& value) const + { + DALI_ASSERT_ALWAYS( index < mPVs.size() && "KeyFrame index is out of bounds" ); + time = mPVs[index].mProgress; + value = mPVs[index].mValue; + } + + /** + * Return whether the progress is valid for the range of keyframes. (The first + * keyframe doesn't have to start at 0, and the last doesn't have to end at 1.0) + * @param[in] progress The progress to test + * @return True if the progress is valid for this object + */ + bool IsActive(float progress) const + { + return mKeyFrames->IsActive(progress); + } + + /** + * Return an interpolated value for the given progress. + * @param[in] progress The progress to test + * @return The interpolated value + */ + V GetValue(float progress, Dali::Animation::Interpolation interpolation) const + { + return mKeyFrames->GetValue(progress, interpolation); + } +}; + +typedef KeyFrameBaseSpec KeyFrameNumber; +typedef KeyFrameBaseSpec KeyFrameBoolean; +typedef KeyFrameBaseSpec KeyFrameInteger; +typedef KeyFrameBaseSpec KeyFrameVector2; +typedef KeyFrameBaseSpec KeyFrameVector3; +typedef KeyFrameBaseSpec KeyFrameVector4; +typedef KeyFrameBaseSpec KeyFrameQuaternion; + +typedef IntrusivePtr KeyFrameBooleanPtr; +typedef IntrusivePtr KeyFrameNumberPtr; +typedef IntrusivePtr KeyFrameIntegerPtr; +typedef IntrusivePtr KeyFrameVector2Ptr; +typedef IntrusivePtr KeyFrameVector3Ptr; +typedef IntrusivePtr KeyFrameVector4Ptr; +typedef IntrusivePtr KeyFrameQuaternionPtr; + + +inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameBoolean*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameBoolean*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameNumber*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameNumber*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameInteger*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameInteger*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameVector2*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameVector2*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameVector3*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameVector3*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameVector4*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameVector4*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameQuaternion*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameQuaternion*& keyFrameSpec) +{ + keyFrameSpec = static_cast(keyFrames.GetKeyFramesBase()); +} + +} // Internal + + +// Get impl of handle +inline Internal::KeyFrames& GetImplementation(Dali::KeyFrames& keyFrames) +{ + DALI_ASSERT_ALWAYS( keyFrames && "KeyFrames handle is empty" ); + Dali::RefObject& object = keyFrames.GetBaseObject(); + return static_cast(object); +} + +inline const Internal::KeyFrames& GetImplementation(const Dali::KeyFrames& keyFrames) +{ + DALI_ASSERT_ALWAYS( keyFrames && "KeyFrames handle is empty" ); + const Dali::RefObject& object = keyFrames.GetBaseObject(); + return static_cast(object); +} + + +} // Dali + +#endif //__DALI_INTERNAL_KEY_FRAMES_H__ diff --git a/dali/internal/event/animation/linear-constrainer-impl.cpp b/dali/internal/event/animation/linear-constrainer-impl.cpp new file mode 100644 index 0000000..11ef59e --- /dev/null +++ b/dali/internal/event/animation/linear-constrainer-impl.cpp @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +//EXTRENAL INCLUDES +#include // for strcmp + +// INTERNAL INCLUDES +#include +#include +#include + + +namespace Dali +{ + +namespace Internal +{ + +namespace +{ + +// Properties +// Name Type writable animatable constraint-input enum for index-checking +DALI_PROPERTY_TABLE_BEGIN +DALI_PROPERTY( "value", ARRAY, true, false, false, Dali::LinearConstrainer::Property::VALUE ) +DALI_PROPERTY( "progress", ARRAY, true, false, false, Dali::LinearConstrainer::Property::PROGRESS ) +DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX ) + +} //Unnamed namespace + +LinearConstrainer* LinearConstrainer::New() +{ + return new LinearConstrainer(); +} + +LinearConstrainer::LinearConstrainer() +: Constrainer() +{ +} + +LinearConstrainer::~LinearConstrainer() +{ +} + +unsigned int LinearConstrainer::GetDefaultPropertyCount() const +{ + return DEFAULT_PROPERTY_COUNT; +} + +void LinearConstrainer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const +{ + indices.Reserve( DEFAULT_PROPERTY_COUNT ); + + for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) + { + indices.PushBack( i ); + } +} + +const char* LinearConstrainer::GetDefaultPropertyName(Property::Index index) const +{ + if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) + { + return DEFAULT_PROPERTY_DETAILS[index].name; + } + + // index out of range + return NULL; +} + +Property::Index LinearConstrainer::GetDefaultPropertyIndex(const std::string& name) const +{ + Property::Index index = Property::INVALID_INDEX; + + // Look for name in default properties + for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) + { + const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ]; + if( 0 == strcmp( name.c_str(), property->name ) ) + { + index = i; + break; + } + } + return index; +} + +Property::Type LinearConstrainer::GetDefaultPropertyType(Property::Index index) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[index].type; + } + + // index out of range + return Property::NONE; +} + +Property::Value LinearConstrainer::GetDefaultProperty( Property::Index index ) const +{ + if( index == Dali::LinearConstrainer::Property::VALUE ) + { + Property::Value value( Property::ARRAY ); + Property::Array* array = value.GetArray(); + size_t count( mValue.Size() ); + + if( array ) + { + array->Reserve( count ); + for( size_t i( 0 ); i != count; ++i ) + { + array->PushBack( mValue[i] ); + } + } + return value; + } + else if( index == Dali::LinearConstrainer::Property::PROGRESS ) + { + Property::Value value( Property::ARRAY ); + Property::Array* array = value.GetArray(); + size_t count( mValue.Size() ); + + if( array ) + { + array->Reserve( count ); + for( size_t i( 0 ); i != count; ++i ) + { + array->PushBack( mProgress[i] ); + } + } + return value; + } + + return Property::Value(); +} + +void LinearConstrainer::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue ) +{ + const Property::Array* array = propertyValue.GetArray(); + if( array ) + { + size_t propertyArrayCount = array->Count(); + if( index == Dali::LinearConstrainer::Property::VALUE ) + { + mValue.Clear(); // remove old values + mValue.Resize( propertyArrayCount ); + for( size_t i(0); i != propertyArrayCount; ++i ) + { + array->GetElementAt( i ).Get( mValue[ i ] ); + } + } + else if( index == Dali::LinearConstrainer::Property::PROGRESS ) + { + mProgress.Clear(); // remove old values + mProgress.Resize( propertyArrayCount ); + for( size_t i(0); i != propertyArrayCount; ++i ) + { + array->GetElementAt( i ).Get( mProgress[ i ] ); + } + } + } +} + +bool LinearConstrainer::IsDefaultPropertyWritable(Property::Index index) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[index].writable; + } + + return false; +} + +bool LinearConstrainer::IsDefaultPropertyAnimatable(Property::Index index) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[index].animatable; + } + + return false; +} + +bool LinearConstrainer::IsDefaultPropertyAConstraintInput( Property::Index index ) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[index].constraintInput; + } + + return false; +} + +void LinearConstrainer::Apply( Property target, Property source, const Vector2& range, const Vector2& wrap) +{ + Dali::Constraint constraint = Dali::Constraint::New( target.object, target.propertyIndex, LinearConstraintFunctor( mValue, mProgress, range, wrap ) ); + constraint.AddSource( Dali::Source(source.object, source.propertyIndex ) ); + + constraint.SetTag( reinterpret_cast( this ) ); + constraint.SetRemoveAction( Dali::Constraint::Discard ); + constraint.Apply(); + + + //Start observing the object + Observe( target.object ); +} + +} // Internal + +} // Dali diff --git a/dali/internal/event/animation/linear-constrainer-impl.h b/dali/internal/event/animation/linear-constrainer-impl.h new file mode 100644 index 0000000..d9d607d --- /dev/null +++ b/dali/internal/event/animation/linear-constrainer-impl.h @@ -0,0 +1,257 @@ +#ifndef __DALI_INTERNAL_LINEAR_CONSTRAINER_H__ +#define __DALI_INTERNAL_LINEAR_CONSTRAINER_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +typedef IntrusivePtr LinearConstrainerPtr; + +/** + * @brief Constraint functor to constraint properties given a linear map. + */ +struct LinearConstraintFunctor +{ + /** + * @brief Constructor. + * + * @param[in] value The list of values for the linear map (f(x) of the linear map) + * @param[in] progress Progress for each of the values normalized to [0,1] ( x of the linear map) + * @param[in] range The range of values in the input property which will be mapped to [0,1] + * @param[in] wrap Wrapping domain. Input property value will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1] + * + * @note If progress is an empty vector, the values will be assumed to be equally spaced in the x-axis + */ + LinearConstraintFunctor( Dali::Vector& value, Dali::Vector& progress, const Vector2& range, const Vector2& wrap ) + :mValue(value), + mProgress(progress), + mRange(range), + mWrap(wrap) + {} + + /** + * @brief Functor operator for float properties + * + * @param[in,out] position Current value of the property + * @param[in] inputs Contains the input property used as the parameter for the path + * + * @return The value of the linear map at the given parameter. + */ + void operator()( float& value, + const PropertyInputContainer& inputs) + { + size_t valueCount( mValue.Size() ); + if( valueCount == 0 ) + { + //No values. + } + else if(valueCount == 1 ) + { + value = mValue[0]; + } + else + { + float inputWrapped = inputs[0]->GetFloat(); + if( inputWrapped < mWrap.x || inputWrapped > mWrap.y ) + { + inputWrapped = WrapInDomain(inputWrapped, mWrap.x, mWrap.y); + } + + float t = (( inputWrapped - mRange.x ) / ( mRange.y-mRange.x )); + + //Find min and max values and local t between them + size_t min(0); + size_t max(0); + float tLocal(0.0f); + if( mProgress.Size() < valueCount ) + { + float step = 1.0f / (valueCount-1.0f); + float tLocation = t/step; + if( tLocation < 0) + { + min = 0; + max = 1; + } + else if( tLocation >= valueCount-1 ) + { + min = max = valueCount-1; + } + else + { + min = static_cast(tLocation); + max = min+1; + } + + tLocal =(t - min*step) / step; + } + else + { + while( t >= mProgress[min] && min < valueCount-1 ) + { + min++; + } + + min--; + max = min+1; + + if( min >= valueCount-1) + { + min = max = valueCount-1; + tLocal = 0.0f; + } + else + { + tLocal =(t - mProgress[min]) / ( mProgress[max]-mProgress[min]); + } + } + + //Linear interpolation + value = (mValue[max]-mValue[min])*tLocal + mValue[min]; + } + } + + + Dali::Vector mValue; ///< values for the linear map + Dali::Vector mProgress; ///< Progress for each of the values normalized to [0,1] + Vector2 mRange; ///< The range of values in the input property which will be mapped to 0..1 + Vector2 mWrap; ///< Wrapping domain. Input property will be wrapped in this domain before being mapped to [0,1] +}; + +/** + * @brief A LinearConstrainer used to constraint properties given a linear map + */ +class LinearConstrainer : public Constrainer +{ +public: + + /** + * Create a new LinearConstrainer + * @return A smart-pointer to the newly allocated LinearConstrainer. + */ + static LinearConstrainer* New(); + +protected: + + /** + * virtual destructor + */ + virtual ~LinearConstrainer(); + +private: + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyCount() + */ + virtual unsigned int GetDefaultPropertyCount() const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices() + */ + virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyName() + */ + virtual const char* GetDefaultPropertyName(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex() + */ + virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable() + */ + virtual bool IsDefaultPropertyWritable(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable() + */ + virtual bool IsDefaultPropertyAnimatable(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput() + */ + virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyType() + */ + virtual Property::Type GetDefaultPropertyType(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::SetDefaultProperty() + */ + virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue); + + /** + * @copydoc Dali::Internal::Object::GetDefaultProperty() + */ + virtual Property::Value GetDefaultProperty( Property::Index index ) const; + +public: + + /** + * @copydoc Dali::PathConstrainer::Apply + */ + void Apply( Property target, Property source, const Vector2& range, const Vector2& wrap ); + +private: + + //Constructor + LinearConstrainer(); + + // Undefined + LinearConstrainer(const LinearConstrainer&); + + // Undefined + LinearConstrainer& operator=(const LinearConstrainer& rhs); + + Dali::Vector mValue; ///< values for the linear map + Dali::Vector mProgress; ///< Progress for each of the values normalized to [0,1] +}; + +} // Internal + +// Get impl of handle +inline Internal::LinearConstrainer& GetImplementation(Dali::LinearConstrainer& linearConstrainer) +{ + DALI_ASSERT_ALWAYS( linearConstrainer && "LinearConstrainer handle is empty" ); + Dali::RefObject& object = linearConstrainer.GetBaseObject(); + return static_cast(object); +} + +inline const Internal::LinearConstrainer& GetImplementation(const Dali::LinearConstrainer& linearConstrainer) +{ + DALI_ASSERT_ALWAYS( linearConstrainer && "LinearConstrainer handle is empty" ); + const Dali::RefObject& object = linearConstrainer.GetBaseObject(); + return static_cast(object); +} + +} // Dali + +#endif //__DALI_INTERNAL_PATH_CONSTRAINER_H__ diff --git a/dali/internal/event/animation/path-constrainer-impl.cpp b/dali/internal/event/animation/path-constrainer-impl.cpp new file mode 100644 index 0000000..8097cc9 --- /dev/null +++ b/dali/internal/event/animation/path-constrainer-impl.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +//EXTRENAL INCLUDES +#include // for strcmp + +// INTERNAL INCLUDES +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace +{ + +// Properties +// Name Type writable animatable constraint-input enum for index-checking +DALI_PROPERTY_TABLE_BEGIN +DALI_PROPERTY( "forward", VECTOR3, true, false, false, Dali::PathConstrainer::Property::FORWARD ) +DALI_PROPERTY( "points", ARRAY, true, false, false, Dali::PathConstrainer::Property::POINTS ) +DALI_PROPERTY( "control-points", ARRAY, true, false, false, Dali::PathConstrainer::Property::CONTROL_POINTS ) +DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX ) + +} //Unnamed namespace + +PathConstrainer* PathConstrainer::New() +{ + return new PathConstrainer(); +} + +PathConstrainer::PathConstrainer() +: Constrainer(), + mPath( Path::New() ) +{ +} + +PathConstrainer::~PathConstrainer() +{ +} + +unsigned int PathConstrainer::GetDefaultPropertyCount() const +{ + return DEFAULT_PROPERTY_COUNT; +} + +void PathConstrainer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const +{ + indices.Reserve( DEFAULT_PROPERTY_COUNT ); + + for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) + { + indices.PushBack( i ); + } +} + +const char* PathConstrainer::GetDefaultPropertyName(Property::Index index) const +{ + if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) + { + return DEFAULT_PROPERTY_DETAILS[index].name; + } + + // index out of range + return NULL; +} + +Property::Index PathConstrainer::GetDefaultPropertyIndex(const std::string& name) const +{ + Property::Index index = Property::INVALID_INDEX; + + // Look for name in default properties + for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) + { + const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ]; + if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string + { + index = i; + break; + } + } + return index; +} + +Property::Type PathConstrainer::GetDefaultPropertyType(Property::Index index) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[index].type; + } + + // index out of range + return Property::NONE; +} + +Property::Value PathConstrainer::GetDefaultProperty( Property::Index index ) const +{ + if( index == Dali::PathConstrainer::Property::FORWARD ) + { + return Property::Value( mForward ); + } + else + { + if( index == Dali::PathConstrainer::Property::POINTS ) + { + Property::Value value( Property::ARRAY ); + Property::Array* array = value.GetArray(); + const Dali::Vector& point = mPath->GetPoints(); + Property::Array::SizeType pointCount = point.Size(); + + if( array ) + { + array->Reserve( pointCount ); + for( Property::Array::SizeType i = 0; i < pointCount; ++i ) + { + array->PushBack( point[i] ); + } + } + return value; + } + else if( index == Dali::PathConstrainer::Property::CONTROL_POINTS ) + { + Property::Value value( Property::ARRAY ); + Property::Array* array = value.GetArray(); + const Dali::Vector& point = mPath->GetControlPoints(); + Property::Array::SizeType pointCount = point.Size(); + + if( array ) + { + array->Reserve( pointCount ); + for( Property::Array::SizeType i = 0; i < pointCount; ++i ) + { + array->PushBack( point[i] ); + } + } + return value; + } + } + + return Property::Value(); +} + +void PathConstrainer::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue ) +{ + if( index == Dali::PathConstrainer::Property::FORWARD ) + { + propertyValue.Get(mForward); + } + else if( index == Dali::PathConstrainer::Property::POINTS ) + { + const Property::Array* array = propertyValue.GetArray(); + mPath->ClearPoints(); + if( array ) + { + for( Property::Array::SizeType i = 0, count = array->Count(); i < count; ++i ) + { + Vector3 point; + array->GetElementAt( i ).Get( point ); + mPath->AddPoint( point ); + } + } + } + else if( index == Dali::PathConstrainer::Property::CONTROL_POINTS ) + { + const Property::Array* array = propertyValue.GetArray(); + mPath->ClearControlPoints(); + if( array ) + { + for( Property::Array::SizeType i = 0, count = array->Count(); i < count; ++i ) + { + Vector3 point; + array->GetElementAt( i ).Get( point ); + mPath->AddControlPoint( point ); + } + } + } +} + +bool PathConstrainer::IsDefaultPropertyWritable(Property::Index index) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[index].writable; + } + + return false; +} + +bool PathConstrainer::IsDefaultPropertyAnimatable(Property::Index index) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[index].animatable; + } + + return false; +} + +bool PathConstrainer::IsDefaultPropertyAConstraintInput( Property::Index index ) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[index].constraintInput; + } + + return false; +} + +void PathConstrainer::Apply( Property target, Property source, const Vector2& range, const Vector2& wrap) +{ + Dali::Property::Type propertyType = target.object.GetPropertyType( target.propertyIndex); + if( propertyType == Dali::Property::VECTOR3) + { + // If property type is Vector3, constrain its value to the position of the path + Dali::Constraint constraint = Dali::Constraint::New( target.object, target.propertyIndex, PathConstraintFunctor( mPath, range, wrap ) ); + constraint.AddSource( Dali::Source(source.object, source.propertyIndex ) ); + + constraint.SetTag( reinterpret_cast( this ) ); + constraint.SetRemoveAction( Dali::Constraint::Discard ); + constraint.Apply(); + } + else if( propertyType == Dali::Property::ROTATION ) + { + // If property type is Rotation, constrain its value to align the forward vector to the tangent of the path + Dali::Constraint constraint = Dali::Constraint::New( target.object, target.propertyIndex, PathConstraintFunctor( mPath, range, mForward, wrap) ); + constraint.AddSource( Dali::Source(source.object, source.propertyIndex ) ); + + constraint.SetTag( reinterpret_cast( this ) ); + constraint.SetRemoveAction( Dali::Constraint::Discard ); + constraint.Apply(); + } + + //Start observing the object + Observe( target.object ); +} + +} // Internal + +} // Dali diff --git a/dali/internal/event/animation/path-constrainer-impl.h b/dali/internal/event/animation/path-constrainer-impl.h new file mode 100644 index 0000000..e988321 --- /dev/null +++ b/dali/internal/event/animation/path-constrainer-impl.h @@ -0,0 +1,229 @@ +#ifndef __DALI_INTERNAL_PATH_CONSTRAINER_H__ +#define __DALI_INTERNAL_PATH_CONSTRAINER_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +typedef IntrusivePtr PathConstrainerPtr; + +/** + * @brief Constraint functor to constraint properties to paths. + * + * Vector3 properties will be constrained to the position of the path and + * Rotation properties will be constrained to follow the tangent of the path + * given a forward vector in object's local space. + */ +struct PathConstraintFunctor +{ + /** + * @brief Constructor. + * + * @param[in] path The path used in the constraint + * @param[in] range The range of values in the input property which will be mapped to [0,1] + * @param[in] wrap Wrapping domain. Input property value will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1] + */ + PathConstraintFunctor(PathPtr path, const Vector2& range, const Vector2& wrap ):mPath(path),mRange(range),mWrap(wrap){} + + /** + * @brief Constructor. + * + * @param[in] path The path used in the constraint + * @param[in] range The range of values in the input property which will be mapped to 0..1 + * @param[in] forward Vector in object space which will be aligned with the tangent of the path + * @param[in] wrap Wrapping domain. Input property value will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1] + */ + PathConstraintFunctor(PathPtr path, const Vector2& range,const Vector3& forward, const Vector2& wrap ):mPath(path),mForward(forward),mRange(range),mWrap(wrap){} + + /** + * @brief Functor operator for Vector3 properties + * + * @param[in,out] position Current value of the property + * @param[in] inputs Contains the input property used as the parameter for the path + * + * @return The position of the path at the given parameter. + */ + void operator()( Vector3& position, + const PropertyInputContainer& inputs) + { + float inputWrapped = inputs[0]->GetFloat(); + if( inputWrapped < mWrap.x || inputWrapped > mWrap.y ) + { + inputWrapped = WrapInDomain(inputWrapped, mWrap.x, mWrap.y); + } + + float t = ( inputWrapped - mRange.x ) / ( mRange.y-mRange.x ); + + Vector3 tangent; + mPath->Sample( t, position, tangent ); + } + + /** + * @brief Functor operator for Quaternion properties + * + * @param[in,out] current Current value of the property + * @param[in] inputs Contains the input property used as the parameter for the path + * + * @return The rotation which will align the forward vector and the tangent of the path at the given parameter. + */ + void operator()( Quaternion& current, + const PropertyInputContainer& inputs) + { + float inputWrapped = inputs[0]->GetFloat(); + if( inputWrapped < mWrap.x || inputWrapped > mWrap.y ) + { + inputWrapped = WrapInDomain(inputWrapped, mWrap.x, mWrap.y); + } + + float t = ( inputWrapped - mRange.x ) / ( mRange.y-mRange.x ); + + Vector3 position, tangent; + mPath->Sample( t, position, tangent ); + current = Quaternion( mForward, tangent ); + } + + PathPtr mPath; ///< The path used + Vector3 mForward; ///< Vector in object space which will be aligned with the tangent of the path + Vector2 mRange; ///< The range of values in the input property which will be mapped to 0..1 + Vector2 mWrap; ///< Wrapping domain. Input property will be wrapped in this domain before being mapped to [0,1] +}; + +/** + * @brief A PathConstrainer used to constraint properties to a path + */ +class PathConstrainer : public Constrainer +{ +public: + + /** + * Create a new PathConstrainer + * @return A smart-pointer to the newly allocated PathConstrainer. + */ + static PathConstrainer* New(); + +protected: + + /** + * virtual destructor + */ + virtual ~PathConstrainer(); + +private: + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyCount() + */ + virtual unsigned int GetDefaultPropertyCount() const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices() + */ + virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyName() + */ + virtual const char* GetDefaultPropertyName(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex() + */ + virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable() + */ + virtual bool IsDefaultPropertyWritable(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable() + */ + virtual bool IsDefaultPropertyAnimatable(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput() + */ + virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyType() + */ + virtual Property::Type GetDefaultPropertyType(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::SetDefaultProperty() + */ + virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue); + + /** + * @copydoc Dali::Internal::Object::GetDefaultProperty() + */ + virtual Property::Value GetDefaultProperty( Property::Index index ) const; + +public: + + /** + * @copydoc Dali::PathConstrainer::Apply + */ + void Apply( Property target, Property source, const Vector2& range, const Vector2& wrap ); + +private: + + //Constructor + PathConstrainer(); + + // Undefined + PathConstrainer(const PathConstrainer&); + + // Undefined + PathConstrainer& operator=(const PathConstrainer& rhs); + + PathPtr mPath; ///< The path used in the constraints + Vector3 mForward; ///< Vector in object space which will be aligned with the tangent of the path +}; + +} // Internal + +// Get impl of handle +inline Internal::PathConstrainer& GetImplementation(Dali::PathConstrainer& pathConstrainer) +{ + DALI_ASSERT_ALWAYS( pathConstrainer && "PathConstrainer handle is empty" ); + Dali::RefObject& object = pathConstrainer.GetBaseObject(); + return static_cast(object); +} + +inline const Internal::PathConstrainer& GetImplementation(const Dali::PathConstrainer& pathConstrainer) +{ + DALI_ASSERT_ALWAYS( pathConstrainer && "PathConstrainer handle is empty" ); + const Dali::RefObject& object = pathConstrainer.GetBaseObject(); + return static_cast(object); +} + +} // Dali + +#endif //__DALI_INTERNAL_PATH_CONSTRAINER_H__ diff --git a/dali/internal/event/animation/path-impl.cpp b/dali/internal/event/animation/path-impl.cpp new file mode 100644 index 0000000..ad34ce7 --- /dev/null +++ b/dali/internal/event/animation/path-impl.cpp @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// CLASS HEADER +#include + +// EXTERNAL INCLUDES +#include // for strcmp + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +namespace +{ + +// Properties + +// Name Type writable animatable constraint-input enum for index-checking +DALI_PROPERTY_TABLE_BEGIN +DALI_PROPERTY( "points", ARRAY, true, false, false, Dali::Path::Property::POINTS ) +DALI_PROPERTY( "control-points", ARRAY, true, false, false, Dali::Path::Property::CONTROL_POINTS ) +DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX ) + +/** + * These coefficient arise from the cubic polynomial equations for + * a bezier curve. + * + * A bezier curve is defined by a cubic polynomial. Given two end points p0 and p1 + * and two control points cp0 and cp1, the bezier curve will be defined by a polynomial in the form + * f(x) = a3*x^3 + a2*x^2 + a1*x + a0 with this restrictions: + * f(0) = p0 + * f(1) = p1 + * f'(0) = 3*(cp0 - p0) + * f'(1) = 3*(p1-cp1) + */ +const float BezierBasisCoeff[] = { -1.0f, 3.0f, -3.0f, 1.0f, + 3.0f, -6.0f, 3.0f, 0.0f, + -3.0f, 3.0f, 0.0f, 0.0f, + 1.0f, 0.0f, 0.0f, 0.0f }; + +const Dali::Matrix BezierBasis = Dali::Matrix( BezierBasisCoeff ); + +} //Unnamed namespace + +Path* Path::New() +{ + return new Path(); +} + +Path::Path() +: Object() +{ +} + +Path::~Path() +{ +} + +Path* Path::Clone(const Path& path) +{ + Path* clone = new Path(); + clone->SetPoints( path.GetPoints() ); + clone->SetControlPoints( path.GetControlPoints() ); + + return clone; +} + +unsigned int Path::GetDefaultPropertyCount() const +{ + return DEFAULT_PROPERTY_COUNT; +} + +void Path::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const +{ + indices.Reserve( DEFAULT_PROPERTY_COUNT ); + + for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) + { + indices.PushBack( i ); + } +} + +const char* Path::GetDefaultPropertyName(Property::Index index) const +{ + if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) ) + { + return DEFAULT_PROPERTY_DETAILS[index].name; + } + + // index out of range + return NULL; +} + +Property::Index Path::GetDefaultPropertyIndex(const std::string& name) const +{ + Property::Index index = Property::INVALID_INDEX; + + // Look for name in default properties + for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i ) + { + const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ]; + if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string + { + index = i; + break; + } + } + return index; +} + +Property::Type Path::GetDefaultPropertyType(Property::Index index) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[index].type; + } + + // index out of range + return Property::NONE; +} + +Property::Value Path::GetDefaultProperty( Property::Index index ) const +{ + if( index == Dali::Path::Property::POINTS ) + { + Property::Value value( Property::ARRAY ); + Property::Array* array = value.GetArray(); + Property::Array::SizeType pointCount = mPoint.Count(); + + if( array ) + { + array->Reserve( pointCount ); + for( Property::Array::SizeType i = 0; i < pointCount; ++i ) + { + array->PushBack( mPoint[i] ); + } + } + return value; + } + else if( index == Dali::Path::Property::CONTROL_POINTS ) + { + Property::Value value( Property::ARRAY ); + Property::Array* array = value.GetArray(); + Property::Array::SizeType controlpointCount = mControlPoint.Count(); + + if( array ) + { + array->Reserve( controlpointCount ); + for( Property::Array::SizeType i = 0; i < controlpointCount; ++i ) + { + array->PushBack( mControlPoint[i] ); + } + } + return value; + } + + return Property::Value(); +} + +void Path::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue) +{ + const Property::Array* array = propertyValue.GetArray(); + if( array ) + { + Property::Array::SizeType propertyArrayCount = array->Count(); + if( index == Dali::Path::Property::POINTS ) + { + mPoint.Reserve( propertyArrayCount ); + for( Property::Array::SizeType i = 0; i < propertyArrayCount; ++i ) + { + Vector3 point; + array->GetElementAt( i ).Get( point ); + mPoint.PushBack( point ); + } + } + else if( index == Dali::Path::Property::CONTROL_POINTS ) + { + mControlPoint.Reserve( propertyArrayCount ); + for( Property::Array::SizeType i = 0; i < propertyArrayCount; ++i ) + { + Vector3 point; + array->GetElementAt( i ).Get( point ); + mControlPoint.PushBack( point ); + } + } + } +} + +bool Path::IsDefaultPropertyWritable(Property::Index index) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[index].writable; + } + + return false; +} + +bool Path::IsDefaultPropertyAnimatable(Property::Index index) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[index].animatable; + } + + return false; +} + +bool Path::IsDefaultPropertyAConstraintInput( Property::Index index ) const +{ + if( index < DEFAULT_PROPERTY_COUNT ) + { + return DEFAULT_PROPERTY_DETAILS[index].constraintInput; + } + + return false; +} + +void Path::AddPoint(const Vector3& point ) +{ + mPoint.PushBack( point ); +} + +void Path::AddControlPoint(const Vector3& point ) +{ + mControlPoint.PushBack( point ); +} + +unsigned int Path::GetNumberOfSegments() const +{ + return (mPoint.Size()>1)?mPoint.Size()-1:0; +} + +void Path::GenerateControlPoints( float curvature ) +{ + unsigned int numSegments = GetNumberOfSegments(); + DALI_ASSERT_ALWAYS( numSegments > 0 && "Need at least 1 segment to generate control points" ); // need at least 1 segment + + mControlPoint.Resize( numSegments * 2); + + //Generate two control points for each segment + for( unsigned int i(0); i= 1.0f ) + { + segment = numSegs-1; + tLocal = 1.0f; + } + else + { + segment = t * numSegs; + float segLength = 1.0f / numSegs; + float segStart = (float)segment * segLength; + tLocal = (t - segStart) * numSegs; + } +} + +void Path::Sample( float t, Vector3& position, Vector3& tangent ) const +{ + DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" ); + + unsigned int segment; + float tLocal; + FindSegmentAndProgress( t, segment, tLocal ); + + //Get points and control points in the segment + const Vector3& controlPoint0 = mControlPoint[2*segment]; + const Vector3& controlPoint1 = mControlPoint[2*segment+1]; + const Vector3& point0 = mPoint[segment]; + const Vector3& point1 = mPoint[segment+1]; + + if(tLocal < Math::MACHINE_EPSILON_1) + { + position = point0; + tangent = ( controlPoint0 - point0 ) * 3.0f; + tangent.Normalize(); + } + else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1) + { + position = point1; + tangent = ( point1 - controlPoint1 ) * 3.0f; + tangent.Normalize(); + } + else + { + const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f ); + const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f ); + + //X + Vector4 cVect( point0.x, controlPoint0.x, controlPoint1.x, point1.x); + + Vector4 A = BezierBasis * cVect; + position.x = sVect.Dot4(A); + tangent.x = sVectDerivative.Dot(Vector3(A)); + + //Y + cVect.x = point0.y; + cVect.y = controlPoint0.y; + cVect.z = controlPoint1.y; + cVect.w = point1.y; + + A = BezierBasis * cVect; + position.y = sVect.Dot4(A); + tangent.y = sVectDerivative.Dot(Vector3(A)); + + //Z + cVect.x = point0.z; + cVect.y = controlPoint0.z; + cVect.z = controlPoint1.z; + cVect.w = point1.z; + + A = BezierBasis * cVect; + position.z = sVect.Dot4(A); + tangent.z = sVectDerivative.Dot(Vector3(A)); + + tangent.Normalize(); + } +} + +Vector3 Path::SamplePosition( float t ) const +{ + DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" ); + + unsigned int segment; + float tLocal; + FindSegmentAndProgress( t, segment, tLocal ); + + const Vector3& controlPoint0 = mControlPoint[2*segment]; + const Vector3& controlPoint1 = mControlPoint[2*segment+1]; + const Vector3& point0 = mPoint[segment]; + const Vector3& point1 = mPoint[segment+1]; + + Vector3 position; + if(tLocal < Math::MACHINE_EPSILON_1) + { + position = point0; + } + else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1) + { + position = point1; + } + else + { + const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f ); + + //X + Vector4 cVect( point0.x, controlPoint0.x, controlPoint1.x, point1.x); + position.x = sVect.Dot4(BezierBasis * cVect); + + //Y + cVect.x = point0.y; + cVect.y = controlPoint0.y; + cVect.z = controlPoint1.y; + cVect.w = point1.y; + position.y = sVect.Dot4(BezierBasis * cVect); + + //Z + cVect.x = point0.z; + cVect.y = controlPoint0.z; + cVect.z = controlPoint1.z; + cVect.w = point1.z; + position.z = sVect.Dot4(BezierBasis * cVect); + } + + return position; +} + +Vector3 Path::SampleTangent( float t ) const +{ + DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" ); + + unsigned int segment; + float tLocal; + FindSegmentAndProgress( t, segment, tLocal ); + + const Vector3& controlPoint0 = mControlPoint[2*segment]; + const Vector3& controlPoint1 = mControlPoint[2*segment+1]; + const Vector3& point0 = mPoint[segment]; + const Vector3& point1 = mPoint[segment+1]; + + Vector3 tangent; + if(tLocal < Math::MACHINE_EPSILON_1) + { + tangent = ( controlPoint0 - point0 ) * 3.0f; + } + else if( (1.0f - tLocal) < Math::MACHINE_EPSILON_1) + { + tangent = ( point1 - controlPoint1 ) * 3.0f; + } + else + { + const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f ); + + //X + Vector4 cVect( point0.x, controlPoint0.x, controlPoint1.x, point1.x); + tangent.x = sVectDerivative.Dot(Vector3(BezierBasis * cVect)); + + //Y + cVect.x = point0.y; + cVect.y = controlPoint0.y; + cVect.z = controlPoint1.y; + cVect.w = point1.y; + tangent.y = sVectDerivative.Dot(Vector3(BezierBasis * cVect)); + + //Z + cVect.x = point0.z; + cVect.y = controlPoint0.z; + cVect.z = controlPoint1.z; + cVect.w = point1.z; + tangent.z = sVectDerivative.Dot(Vector3(BezierBasis * cVect)); + } + + tangent.Normalize(); + return tangent; +} + +Vector3& Path::GetPoint( size_t index ) +{ + DALI_ASSERT_ALWAYS( index < mPoint.Size() && "Path: Point index out of bounds" ); + + return mPoint[index]; +} + +Vector3& Path::GetControlPoint( size_t index ) +{ + DALI_ASSERT_ALWAYS( index < mControlPoint.Size() && "Path: Control Point index out of bounds" ); + + return mControlPoint[index]; +} + +size_t Path::GetPointCount() const +{ + return mPoint.Size(); +} + +void Path::ClearPoints() +{ + mPoint.Clear(); +} + +void Path::ClearControlPoints() +{ + mControlPoint.Clear(); +} + +} // Internal +} // Dali diff --git a/dali/internal/event/animation/path-impl.h b/dali/internal/event/animation/path-impl.h new file mode 100644 index 0000000..26a1a01 --- /dev/null +++ b/dali/internal/event/animation/path-impl.h @@ -0,0 +1,288 @@ +#ifndef __DALI_INTERNAL_PATH_H__ +#define __DALI_INTERNAL_PATH_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ +typedef IntrusivePtr PathPtr; + +/** + * A 3D path + */ +class Path : public Object +{ +public: + + /** + * Construct a new path + */ + static Path* New(); + + /** + * Constructor + */ + Path(); + + +protected: + /** + * virtual destructor + */ + virtual ~Path(); + +private: + /** + * @copydoc Dali::Internal::Object::Observer::SceneObjectAdded() + */ + virtual void SceneObjectAdded(Object& object){} + + /** + * @copydoc Dali::Internal::Object::Observer::SceneObjectAdded() + */ + virtual void SceneObjectRemoved(Object& object){} + + /** + * @copydoc Dali::Internal::Object::Observer::ObjectDestroyed() + */ + virtual void ObjectDestroyed(Object& object){} + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyCount() + */ + virtual unsigned int GetDefaultPropertyCount() const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices() + */ + virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyName() + */ + virtual const char* GetDefaultPropertyName(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex() + */ + virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable() + */ + virtual bool IsDefaultPropertyWritable(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable() + */ + virtual bool IsDefaultPropertyAnimatable(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput() + */ + virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetDefaultPropertyType() + */ + virtual Property::Type GetDefaultPropertyType(Property::Index index) const; + + /** + * @copydoc Dali::Internal::Object::SetDefaultProperty() + */ + virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue); + + /** + * @copydoc Dali::Internal::Object::GetDefaultProperty() + */ + virtual Property::Value GetDefaultProperty( Property::Index index ) const; + + /** + * @copydoc Dali::Internal::Object::GetSceneObject() + */ + virtual const SceneGraph::PropertyOwner* GetSceneObject() const{ return NULL; } + + /** + * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty() + */ + virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const{ return NULL; } + + /** + * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty() + */ + virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const{ return NULL; } + +public: + + /** + * Returns a clone to the given path + */ + static Path* Clone(const Path& path); + + /** + * @copydoc Dali::Path::AddPoint + */ + void AddPoint(const Vector3& point ); + + /** + * @copydoc Dali::Path::AddControlPoint + */ + void AddControlPoint(const Vector3& point ); + + /** + * @copydoc Dali::Path::GenerateControlPoints + */ + void GenerateControlPoints( float curvature ); + + /** + * @copydoc Dali::Path::Sample + */ + void Sample( float t, Vector3& position, Vector3& tangent ) const; + + /** + * Sample position at point t. + * + * @param[in] progress A floating point value between 0.0 and 1.0. + * @param[out] position The interpolated position at that progress. + */ + Vector3 SamplePosition( float t ) const; + + /** + * @brief Sample tangent at point t. + * + * @param[in] progress A floating point value between 0.0 and 1.0. + * @param[out] tangent The interpolated tangent at that progress. + */ + Vector3 SampleTangent( float t ) const; + + /** + * @copydoc Dali::Path::GetPoint + */ + Vector3& GetPoint( size_t index ); + + /** + * @copydoc Dali::Path::GetControlPoint + */ + Vector3& GetControlPoint( size_t index ); + + /** + * @copydoc Dali::Path::GetPointCount + */ + size_t GetPointCount() const; + + /** + * Clears the points of the path + */ + void ClearPoints(); + + /** + * Clears the control points of the path + */ + void ClearControlPoints(); + + /** + * @brief Get mPoint property + * + * @return A const reference to mPoint vector + */ + const Dali::Vector& GetPoints() const{ return mPoint; } + + /* + * @brief Set mPoint + * + * @param[in] p New value for mPoint property + */ + void SetPoints( const Dali::Vector& p ){ mPoint = p; } + + /** + * @brief Get mCotrolPoint property + * + * @return A const reference to mControlPoint vector + */ + const Dali::Vector& GetControlPoints() const{ return mControlPoint; } + + /* + * @brief Set mControlPoint property + * + * @param[in] p New value for mControlPoint property + */ + void SetControlPoints( const Dali::Vector& p ){ mControlPoint = p; } + +private: + + /** + * Undefined + */ + Path(const Path& p); + + /** + * Undefined + */ + Path& operator=(const Path& rhs); + + /** + * Helper function to calculate the segment and local progress in that segment + * given a progress + * + * @param[in] t Progress + * @param[out] segment Segment for t + * @param[out] tLocal Local progress in the segment + * + */ + void FindSegmentAndProgress( float t, unsigned int& segment, float& tLocal ) const; + + /** + * Helper function to calculate to number of segments in the path + */ + unsigned int GetNumberOfSegments() const; + + Dali::Vector mPoint; ///< Interpolation points + Dali::Vector mControlPoint; ///< Control points +}; + +} // Internal + +// Get impl of handle +inline Internal::Path& GetImplementation(Dali::Path& path) +{ + DALI_ASSERT_ALWAYS( path && "Path handle is empty" ); + Dali::RefObject& object = path.GetBaseObject(); + return static_cast(object); +} + +inline const Internal::Path& GetImplementation(const Dali::Path& path) +{ + DALI_ASSERT_ALWAYS( path && "Path handle is empty" ); + const Dali::RefObject& object = path.GetBaseObject(); + return static_cast(object); +} + + +} // Dali + +#endif //__DALI_INTERNAL_KEY_FRAMES_H__ diff --git a/dali/internal/event/animation/progress-value.h b/dali/internal/event/animation/progress-value.h new file mode 100644 index 0000000..7de8d3c --- /dev/null +++ b/dali/internal/event/animation/progress-value.h @@ -0,0 +1,219 @@ +#ifndef __DALI_INTERNAL_PROGRESS_VALUE_H__ +#define __DALI_INTERNAL_PROGRESS_VALUE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * Progress / value pair for animating channels (properties) with keyframes + */ +template +class ProgressValue +{ +public: + ProgressValue (float progress, T value) + : mProgress(progress), + mValue (value) + { + } + + ~ProgressValue () + { + } + + float GetProgress () const + { + return mProgress; + } + + const T& GetValue () const + { + return mValue; + } + +public: + float mProgress; ///< Progress this value applies to animation channel + T mValue; ///< value this animation channel should take +}; + +typedef ProgressValue ProgressQuaternion; +typedef std::vector ProgressQuaternionContainer; + +typedef ProgressValue ProgressAngleAxis; +typedef std::vector ProgressAngleAxisContainer; + +typedef ProgressValue ProgressBoolean; +typedef std::vector ProgressBooleanContainer; + +typedef ProgressValue ProgressInteger; +typedef std::vector ProgressIntegerContainer; + +typedef ProgressValue ProgressNumber; +typedef std::vector ProgressNumberContainer; + +typedef ProgressValue ProgressVector2; +typedef std::vector ProgressVector2Container; + +typedef ProgressValue ProgressVector3; +typedef std::vector ProgressVector3Container; + +typedef ProgressValue ProgressVector4; +typedef std::vector ProgressVector4Container; + +inline void Interpolate (Quaternion& result, const Quaternion& a, const Quaternion& b, float progress) +{ + result = Quaternion::Slerp(a, b, progress); +} + +inline void Interpolate (AngleAxis& result, const AngleAxis& a, const AngleAxis& b, float progress) +{ + Quaternion q1(a.angle, a.axis); + Quaternion q2(b.angle, b.axis); + + Quaternion iq = Quaternion::Slerp(q1, q2, progress); + iq.ToAxisAngle(result.axis, result.angle); +} + + +inline void Interpolate (bool& result, bool a, bool b, float progress) +{ + result = progress < 0.5f ? a : b; +} + +inline void Interpolate (int& result, int a, int b, float progress) +{ + result = static_cast(a + (b - a) * progress + 0.5f); +} + +inline void Interpolate (unsigned int& result, unsigned int a, unsigned int b, float progress) +{ + result = static_cast(a + (b - a) * progress + 0.5f); +} + +inline void Interpolate (float& result, float a, float b, float progress) +{ + result = a + (b-a) * progress; +} + +inline void Interpolate (Vector2& result, const Vector2& a, const Vector2& b, float progress) +{ + result = a + (b-a) * progress; +} + +inline void Interpolate (Vector3& result, const Vector3& a, const Vector3& b, float progress) +{ + result = a + (b-a) * progress; +} + +inline void Interpolate (Vector4& result, const Vector4& a, const Vector4& b, float progress) +{ + result = a + (b-a) * progress; +} + +/* Cubic Interpolation (Catmull-Rom spline) between values p1 and p2. p0 and p3 are prev and next values + * and are used as control points to calculate tangent of the curve at interpolation points. + * + * f(t) = a3*t^3 + a2*t^2 + a1*t + a0 + * Restrictions: f(0)=p1 f(1)=p2 f'(0)=(p2-p0)*0.5 f'(1)=(p3-p1)*0.5 + */ + +inline void CubicInterpolate( int& result, int p0, int p1, int p2, int p3, float progress ) +{ + float a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f; + float a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f; + float a1 = (p2-p0)*0.5f; + + result = static_cast( a3*progress*progress*progress + a2*progress*progress + a1*progress + p1 + 0.5f ); +} + +inline void CubicInterpolate( unsigned int& result, unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, float progress ) +{ + float a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f; + float a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f; + float a1 = (p2-p0)*0.5f; + + result = static_cast( a3*progress*progress*progress + a2*progress*progress + a1*progress + p1 + 0.5f ); +} + +inline void CubicInterpolate( float& result, float p0, float p1, float p2, float p3, float progress ) +{ + float a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f; + float a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f; + float a1 = (p2-p0)*0.5f; + + result = a3*progress*progress*progress + a2*progress*progress + a1*progress + p1; +} + +inline void CubicInterpolate( Vector2& result, const Vector2& p0, const Vector2& p1, const Vector2& p2, const Vector2& p3, float progress ) +{ + Vector2 a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f; + Vector2 a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f; + Vector2 a1 = (p2-p0)*0.5f; + + result = a3*progress*progress*progress + a2*progress*progress + a1*progress + p1; +} + +inline void CubicInterpolate( Vector3& result, const Vector3& p0, const Vector3& p1, const Vector3& p2, const Vector3& p3, float progress ) +{ + Vector3 a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f; + Vector3 a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f; + Vector3 a1 = (p2-p0)*0.5f; + + result = a3*progress*progress*progress + a2*progress*progress + a1*progress + p1; +} + +inline void CubicInterpolate( Vector4& result, const Vector4& p0, const Vector4& p1, const Vector4& p2, const Vector4& p3, float progress ) +{ + Vector4 a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f; + Vector4 a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f; + Vector4 a1 = (p2-p0)*0.5f; + + result = a3*progress*progress*progress + a2*progress*progress + a1*progress + p1; +} + +inline void CubicInterpolate( bool& result, bool p0, bool p1, bool p2, bool p3, float progress ) +{ + Interpolate( result, p1, p2, progress); +} + +inline void CubicInterpolate( Quaternion& result, const Quaternion& p0, const Quaternion& p1, const Quaternion& p2, const Quaternion& p3, float progress ) +{ + Interpolate( result, p1, p2, progress); +} + +inline void CubicInterpolate( AngleAxis& result, const AngleAxis& p0, const AngleAxis& p1, const AngleAxis& p2, const AngleAxis& p3, float progress ) +{ + Interpolate( result, p1, p2, progress); +} + +} // namespace Internal + +} // namespace Dali + +#endif //__DALI_PROGRESS_VALUE_H__ diff --git a/dali/internal/event/animation/property-constraint-ptr.h b/dali/internal/event/animation/property-constraint-ptr.h new file mode 100644 index 0000000..495607a --- /dev/null +++ b/dali/internal/event/animation/property-constraint-ptr.h @@ -0,0 +1,41 @@ +#ifndef __DALI_INTERNAL_PROPERTY_CONSTRAINT_PTR_H__ +#define __DALI_INTERNAL_PROPERTY_CONSTRAINT_PTR_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +template +struct PropertyConstraintPtr +{ + typedef OwnerPointer< PropertyConstraint

> Type; +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_PROPERTY_CONSTRAINT_PTR_H__ diff --git a/dali/internal/event/animation/property-constraint.h b/dali/internal/event/animation/property-constraint.h new file mode 100644 index 0000000..196c229 --- /dev/null +++ b/dali/internal/event/animation/property-constraint.h @@ -0,0 +1,221 @@ +#ifndef __DALI_PROPERTY_CONSTRAINT_H__ +#define __DALI_PROPERTY_CONSTRAINT_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include +#include +#include +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * A class for connecting properties to a constraint function. + */ +template < typename PropertyType > +class PropertyConstraint +{ +public: + + typedef std::vector < PropertyInputAccessor > InputContainer; + typedef typename InputContainer::iterator InputContainerIter; + typedef typename InputContainer::const_iterator InputContainerConstIter; + + typedef std::vector< PropertyInputIndexer< PropertyInputAccessor > > InputIndexerContainer; + + typedef Dali::Constraint::Function< PropertyType > ConstraintFunction; + + /** + * Create a property constraint. + * + * @param[in] func A constraint function. Ownership of this callback-function is passed to this object. + */ + PropertyConstraint( Dali::Constraint::Function< PropertyType >* func ) + : mInputsInitialized( false ), + mFunction( func ), + mInputs() + { + } + + /** + * Constructor. + * @param [in] func A constraint function. Ownership of this callback-function is passed to this object. + * @param [in] inputs Property inputs. + */ + PropertyConstraint( Dali::Constraint::Function< PropertyType >* func, + const InputContainer& inputs ) + : mInputsInitialized( false ), + mFunction( func ), + mInputs( inputs ) + { + } + + /** + * Non virtual destructor. + */ + ~PropertyConstraint() + { + delete mFunction; + } + + /** + * Clone a property constraint. + * + * @return The clone of the property-constraint. + * + * @note This function will create a copy of the stored constraint function for the clone. + */ + PropertyConstraint< PropertyType >* Clone() + { + return new PropertyConstraint< PropertyType >( reinterpret_cast< ConstraintFunction* >( mFunction->Clone() ), mInputs ); + } + + /** + * Set the input for one of the property constraint parameters. + * @param [in] index The parameter index. + * @param [in] input The interface for receiving a property value. + */ + void SetInput( unsigned int index, int componentIndex, const PropertyInputImpl& input ) + { + if ( index >= mInputs.size() ) + { + mInputs.push_back( PropertyInputAccessor() ); + } + + mInputs[ index ].SetInput( input, componentIndex ); + } + + /** + * Retrieve the input for one of the property constraint parameters. + * @param [in] index The parameter index. + * @return The property input, or NULL if no input exists with this index. + */ + const PropertyInputImpl* GetInput( unsigned int index ) const + { + if ( index < mInputs.size() ) + { + return mInputs[ index ].GetInput(); + } + + return NULL; + } + + /** + * Query whether all of the inputs have been initialized. + * @return True if all of the inputs have been initialized. + */ + bool InputsInitialized() + { + if ( !mInputsInitialized ) + { + // Check whether the inputs are initialized yet + unsigned int index( 0u ); + for ( const PropertyInputImpl* input = GetInput( index ); + NULL != input; + input = GetInput( ++index ) ) + { + if ( !input->InputInitialized() ) + { + return false; + } + } + + // All inputs are now initialized + mInputsInitialized = true; + } + + return true; + } + + /** + * Query whether any of the inputs have changed + * @return True if any of the inputs have changed. + */ + bool InputsChanged() + { + unsigned int index( 0u ); + for ( const PropertyInputImpl* input = GetInput( index ); + NULL != input; + input = GetInput( ++index ) ) + { + if ( input->InputChanged() ) + { + // At least one of the inputs has changed + return true; + } + } + + return false; + } + + /** + * Apply the constraint. + * @param [in] bufferIndex The current update buffer index. + * @param [in,out] current The current property value, will be set to the constrained value upon return. + */ + void Apply( BufferIndex bufferIndex, PropertyType& current ) + { + InputIndexerContainer mInputIndices; + PropertyInputContainer mIndices; + const unsigned int noOfInputs = mInputs.size(); + + mInputIndices.reserve( noOfInputs ); + mIndices.Reserve( noOfInputs ); + + const InputContainerConstIter endIter = mInputs.end(); + unsigned int index = 0; + for ( InputContainerConstIter iter = mInputs.begin(); iter != endIter; ++iter, ++index ) + { + DALI_ASSERT_DEBUG( NULL != iter->GetInput() ); + mInputIndices.push_back( PropertyInputIndexer< PropertyInputAccessor >( bufferIndex, &*iter ) ); + mIndices.PushBack( &mInputIndices[ index ] ); + } + + CallbackBase::Execute< PropertyType&, const PropertyInputContainer& >( *mFunction, current, mIndices ); + } + +private: + + // Undefined + PropertyConstraint( const PropertyConstraint& ); + + // Undefined + PropertyConstraint& operator=( const PropertyConstraint& rhs ); + +private: + + bool mInputsInitialized; + + ConstraintFunction* mFunction; + + InputContainer mInputs; +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_PROPERTY_CONSTRAINT_H__ diff --git a/dali/internal/event/animation/property-input-accessor.h b/dali/internal/event/animation/property-input-accessor.h new file mode 100644 index 0000000..9c203a1 --- /dev/null +++ b/dali/internal/event/animation/property-input-accessor.h @@ -0,0 +1,227 @@ +#ifndef __DALI_PROPERTY_INPUT_ACCESSOR_H__ +#define __DALI_PROPERTY_INPUT_ACCESSOR_H__ + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include +#include + +namespace Dali +{ + +namespace Internal +{ + +class PropertyInputAccessor +{ +public: + + /** + * Create the PropertyInputAccessor. + */ + PropertyInputAccessor() + : mInput( NULL ), + mComponentIndex( -1 ) + { + } + + /** + * Create the PropertyInputAccessor. + */ + PropertyInputAccessor( const PropertyInputImpl* input, int componentIndex ) + : mInput( input ), + mComponentIndex( componentIndex ) + { + } + + /** + * Copy from a PropertyInputAccessor + */ + PropertyInputAccessor( const PropertyInputAccessor& accessor ) + : mInput( accessor.mInput ), + mComponentIndex( accessor.mComponentIndex ) + { + } + + /** + * Copy from a PropertyInputAccessor + */ + PropertyInputAccessor& operator=(const PropertyInputAccessor& accessor) + { + mInput = accessor.mInput; + mComponentIndex = accessor.mComponentIndex; + return *this; + } + + /** + * Set the property input. + */ + void SetInput( const PropertyInputImpl& input, int componentIndex ) + { + mInput = &input; + mComponentIndex = componentIndex; + } + + /** + * Retrieve the property input. + */ + const PropertyInputImpl* GetInput() const + { + return mInput; + } + + /** + * @copydoc Dali::Internal::PropertyInputImpl::GetType() + */ + Property::Type GetType() const + { + return mInput->GetType(); + } + + /** + * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputBoolean() + */ + const bool& GetConstraintInputBoolean( BufferIndex updateBufferIndex ) const + { + return mInput->GetConstraintInputBoolean( updateBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputInteger() const + */ + const int& GetConstraintInputInteger( BufferIndex updateBufferIndex ) const + { + DALI_ASSERT_DEBUG( mComponentIndex < 0 && "Did not expect valid component index" ); + + return mInput->GetConstraintInputInteger( updateBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputFloat() + */ + const float& GetConstraintInputFloat( BufferIndex updateBufferIndex ) const + { + // Invalid index is ok + if ( mComponentIndex < 0 ) + { + // Not a Vector2, Vector3 or Vector4 component, expecting float type + return mInput->GetConstraintInputFloat( updateBufferIndex ); + } + else if ( PropertyTypes::Get< Vector2 >() == mInput->GetType() ) + { + if ( 0 == mComponentIndex ) + { + return mInput->GetConstraintInputVector2( updateBufferIndex ).x; + } + + DALI_ASSERT_DEBUG( 1 == mComponentIndex && "Invalid Vector2 component index" ); + return mInput->GetConstraintInputVector2( updateBufferIndex ).y; + } + else if ( PropertyTypes::Get< Vector3 >() == mInput->GetType() ) + { + if ( 0 == mComponentIndex ) + { + return mInput->GetConstraintInputVector3( updateBufferIndex ).x; + } + else if ( 1 == mComponentIndex ) + { + return mInput->GetConstraintInputVector3( updateBufferIndex ).y; + } + + DALI_ASSERT_DEBUG( 2 == mComponentIndex && "Invalid Vector3 component index" ); + return mInput->GetConstraintInputVector3( updateBufferIndex ).z; + } + + // Expecting Vector4 + if ( 0 == mComponentIndex ) + { + return mInput->GetConstraintInputVector4( updateBufferIndex ).x; + } + else if ( 1 == mComponentIndex ) + { + return mInput->GetConstraintInputVector4( updateBufferIndex ).y; + } + else if ( 2 == mComponentIndex ) + { + return mInput->GetConstraintInputVector4( updateBufferIndex ).z; + } + + DALI_ASSERT_DEBUG( 3 == mComponentIndex && "Invalid Vector4 component index" ); + return mInput->GetConstraintInputVector4( updateBufferIndex ).w; + } + + /** + * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputVector2() + */ + const Vector2& GetConstraintInputVector2( BufferIndex updateBufferIndex ) const + { + return mInput->GetConstraintInputVector2( updateBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputVector3() + */ + const Vector3& GetConstraintInputVector3( BufferIndex updateBufferIndex ) const + { + return mInput->GetConstraintInputVector3( updateBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputVector4() + */ + const Vector4& GetConstraintInputVector4( BufferIndex updateBufferIndex ) const + { + return mInput->GetConstraintInputVector4( updateBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputQuaternion() + */ + const Quaternion& GetConstraintInputQuaternion( BufferIndex updateBufferIndex ) const + { + return mInput->GetConstraintInputQuaternion( updateBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputMatrix3() + */ + const Matrix3& GetConstraintInputMatrix3( BufferIndex updateBufferIndex ) const + { + return mInput->GetConstraintInputMatrix3( updateBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputMatrix() + */ + const Matrix& GetConstraintInputMatrix( BufferIndex updateBufferIndex ) const + { + return mInput->GetConstraintInputMatrix( updateBufferIndex ); + } + +public: + + const PropertyInputImpl* mInput; + int mComponentIndex; +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_PROPERTY_INPUT_ACCESSOR_H__ diff --git a/dali/internal/event/animation/property-input-indexer.h b/dali/internal/event/animation/property-input-indexer.h new file mode 100644 index 0000000..c19bf14 --- /dev/null +++ b/dali/internal/event/animation/property-input-indexer.h @@ -0,0 +1,167 @@ +#ifndef __DALI_PROPERTY_INPUT_INDEXER_H__ +#define __DALI_PROPERTY_INPUT_INDEXER_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES +#include + +namespace Dali +{ + +namespace Internal +{ + +/** + * Helper object to map public-api PropertyInput methods to internal + * PropertyInputImpl methods (which require the current buffer index). + */ +template < typename AccessorType > +class PropertyInputIndexer : public PropertyInput +{ +public: + + /** + * Create an indexer object. + * @param[in] bufferIndex The current buffer index. + * @param[in] input The internal property input. + */ + PropertyInputIndexer( BufferIndex bufferIndex, const AccessorType* input ) + : mBufferIndex( bufferIndex ), + mInput( input ) + { + } + + /** + * Copy constructor + */ + PropertyInputIndexer( const PropertyInputIndexer& other ) + : mBufferIndex( other.mBufferIndex ), + mInput( other.mInput ) + { + } + + /** + * Assignment operator + */ + PropertyInputIndexer& operator=( const PropertyInputIndexer& other ) + { + mBufferIndex = other.mBufferIndex; + mInput = other.mInput; + + return *this; + } + + /** + * Virtual Destructor + */ + virtual ~PropertyInputIndexer() + { + } + + /** + * @copydoc Dali::Internal::PropertyInput::GetType() + */ + virtual Property::Type GetType() const + { + return mInput->GetType(); + } + + /** + * @copydoc Dali::Internal::PropertyInput::GetBoolean() + */ + virtual const bool& GetBoolean() const + { + return mInput->GetConstraintInputBoolean( mBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInput::GetInteger() + */ + virtual const int& GetInteger() const + { + return mInput->GetConstraintInputInteger( mBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInput::GetFloat() + */ + virtual const float& GetFloat() const + { + return mInput->GetConstraintInputFloat( mBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInput::GetVector2() + */ + virtual const Vector2& GetVector2() const + { + return mInput->GetConstraintInputVector2( mBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInput::GetVector3() + */ + virtual const Vector3& GetVector3() const + { + return mInput->GetConstraintInputVector3( mBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInput::GetVector4() + */ + virtual const Vector4& GetVector4() const + { + return mInput->GetConstraintInputVector4( mBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInput::GetMatrix3() + */ + virtual const Matrix3& GetMatrix3() const + { + return mInput->GetConstraintInputMatrix3( mBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInput::GetMatrix() + */ + virtual const Matrix& GetMatrix() const + { + return mInput->GetConstraintInputMatrix( mBufferIndex ); + } + + /** + * @copydoc Dali::Internal::PropertyInput::Quaternion() + */ + virtual const Quaternion& GetQuaternion() const + { + return mInput->GetConstraintInputQuaternion( mBufferIndex ); + } + +public: + + unsigned int mBufferIndex; + const AccessorType* mInput; +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_PROPERTY_INPUT_INDEXER_H__ diff --git a/dali/internal/event/common/complete-notification-interface.h b/dali/internal/event/common/complete-notification-interface.h new file mode 100644 index 0000000..af43f25 --- /dev/null +++ b/dali/internal/event/common/complete-notification-interface.h @@ -0,0 +1,63 @@ +#ifndef __DALI_INTERNAL_COMPLETE_NOTIFICATION_INTERFACE_H__ +#define __DALI_INTERNAL_COMPLETE_NOTIFICATION_INTERFACE_H__ + +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES + +namespace Dali +{ + +namespace Internal +{ + +/** + * Provides notifications to the event-thread regarding the changes in previous update(s). + * For example after an animation finished, or after resources were loaded. + */ +class CompleteNotificationInterface +{ +protected: + + /** + * Constructor, not to be directly instantiated. + */ + CompleteNotificationInterface() + {} + + /** + * Virtual destructor as this is an interface, no deletion through this interface though. + */ + virtual ~CompleteNotificationInterface() + {} + +public: + + /** + * This method is called by Notification Manager + */ + virtual void NotifyCompleted() = 0; + +}; + +} // namespace Internal + +} // namespace Dali + +#endif // __DALI_INTERNAL_COMPLETE_NOTIFICATION_INTERFACE_H__ + diff --git a/dali/internal/event/common/connectable.h b/dali/internal/event/common/connectable.h new file mode 100644 index 0000000..643e9b6 --- /dev/null +++ b/dali/internal/event/common/connectable.h @@ -0,0 +1,60 @@ +#ifndef DALI_INTERNAL_CONNECTABLE_H +#define DALI_INTERNAL_CONNECTABLE_H + +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// INTERNAL INCLUDES + +namespace Dali +{ +namespace Internal +{ + +/** + * @brief Interface for objects that can be connected to the stage. + */ +class Connectable +{ +public: + + /** + * @brief Destructor + */ + virtual ~Connectable() {} + + /** + * @brief Check if the object is on stage + */ + virtual bool OnStage() const = 0; + + /** + * @brief Notify this objects that it has been connected to the stage. + */ + virtual void Connect() = 0; + + /** + * @brief Notify this objects that it has been disconnected to the stage. + */ + virtual void Disconnect() = 0; + +}; + +} // namespace Internal +} // namespace Dali + +#endif // DALI_INTERNAL_CONNECTABLE_H diff --git a/dali/internal/event/common/demangler.cpp b/dali/internal/event/common/demangler.cpp new file mode 100644 index 0000000..5a2caed --- /dev/null +++ b/dali/internal/event/common/demangler.cpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +// +// gcc and clang minimal demangling +// Both follow Itanium C++ ABI +// +// We only decode namespaces and class typeid names for simplicity as its all we need. +// +// From http://mentorembedded.github.io/cxx-abi/abi.html#mangling-structure +// +// ::= N [] E +// ::= N [] E +// +// ::= +// ::= +// ::= +// ::= +// ::= # empty +// ::= +// ::= +// +// ::=