diff options
Diffstat (limited to 'tests/auto/animation')
20 files changed, 2927 insertions, 351 deletions
diff --git a/tests/auto/animation/animation.pro b/tests/auto/animation/animation.pro index 421ecfdd5..1226f9498 100644 --- a/tests/auto/animation/animation.pro +++ b/tests/auto/animation/animation.pro @@ -13,7 +13,10 @@ SUBDIRS += \ qkeyframeanimation \ qmorphinganimation \ qmorphtarget \ - qvertexblendanimation + qvertexblendanimation \ + qclock \ + qskeletonmapping \ + qcallbackmapping qtConfig(private_tests) { SUBDIRS += \ @@ -35,5 +38,7 @@ qtConfig(private_tests) { clipblendvalue \ animationutils \ qabstractanimation \ + clock \ + skeleton \ findrunningclipanimatorsjob } diff --git a/tests/auto/animation/animationutils/animationutils.qrc b/tests/auto/animation/animationutils/animationutils.qrc index ddaeab7f1..0b499ed76 100644 --- a/tests/auto/animation/animationutils/animationutils.qrc +++ b/tests/auto/animation/animationutils/animationutils.qrc @@ -4,5 +4,6 @@ <file>clip2.json</file> <file>clip3.json</file> <file>clip4.json</file> + <file>clip5.json</file> </qresource> </RCC> diff --git a/tests/auto/animation/animationutils/clip5.json b/tests/auto/animation/animationutils/clip5.json new file mode 100644 index 000000000..50a848f03 --- /dev/null +++ b/tests/auto/animation/animationutils/clip5.json @@ -0,0 +1,1401 @@ +{ + "animations": [ + { + "animationName": "SkeletonAction", + "channels": [ + { + "channelComponents": [ + { + "channelComponentName": "Rotation W", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.9597616195678711, + 1.0 + ], + "rightHandle": [ + 0.9597616195678711, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -4.371138828673793e-08 + ], + "leftHandle": [ + 1.4985717137654622, + -4.371138828673793e-08 + ], + "rightHandle": [ + 3.4180949529012046, + -4.371138828673793e-08 + ] + } + ] + }, + { + "channelComponentName": "Rotation X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Z", + "keyFrames": [ + { + "coords": [ + 0.0, + -0.0 + ], + "leftHandle": [ + -0.9597616195678711, + -0.0 + ], + "rightHandle": [ + 0.9597616195678711, + -0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -1.0 + ], + "leftHandle": [ + 1.4985717137654622, + -1.0 + ], + "rightHandle": [ + 3.4180949529012046, + -1.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Rotation", + "jointIndex": 0 + }, + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location", + "jointIndex": 0 + }, + { + "channelComponents": [ + { + "channelComponentName": "Scale X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Scale", + "jointIndex": 0 + }, + { + "channelComponents": [ + { + "channelComponentName": "Rotation W", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.9597616195678711, + 1.0 + ], + "rightHandle": [ + 0.9597616195678711, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -4.371138828673793e-08 + ], + "leftHandle": [ + 1.4985717137654622, + -4.371138828673793e-08 + ], + "rightHandle": [ + 3.4180949529012046, + -4.371138828673793e-08 + ] + } + ] + }, + { + "channelComponentName": "Rotation X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Z", + "keyFrames": [ + { + "coords": [ + 0.0, + -0.0 + ], + "leftHandle": [ + -0.9597616195678711, + -0.0 + ], + "rightHandle": [ + 0.9597616195678711, + -0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -1.0 + ], + "leftHandle": [ + 1.4985717137654622, + -1.0 + ], + "rightHandle": [ + 3.4180949529012046, + -1.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Rotation", + "jointIndex": 1 + }, + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location", + "jointIndex": 1 + }, + { + "channelComponents": [ + { + "channelComponentName": "Scale X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Scale", + "jointIndex": 1 + }, + { + "channelComponents": [ + { + "channelComponentName": "Rotation W", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.9597616195678711, + 1.0 + ], + "rightHandle": [ + 0.9597616195678711, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -4.371138828673793e-08 + ], + "leftHandle": [ + 1.4985717137654622, + -4.371138828673793e-08 + ], + "rightHandle": [ + 3.4180949529012046, + -4.371138828673793e-08 + ] + } + ] + }, + { + "channelComponentName": "Rotation X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Z", + "keyFrames": [ + { + "coords": [ + 0.0, + -0.0 + ], + "leftHandle": [ + -0.9597616195678711, + -0.0 + ], + "rightHandle": [ + 0.9597616195678711, + -0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -1.0 + ], + "leftHandle": [ + 1.4985717137654622, + -1.0 + ], + "rightHandle": [ + 3.4180949529012046, + -1.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Rotation", + "jointIndex": 2 + }, + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location", + "jointIndex": 2 + }, + { + "channelComponents": [ + { + "channelComponentName": "Scale X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Scale", + "jointIndex": 2 + }, + { + "channelComponents": [ + { + "channelComponentName": "Rotation W", + "keyFrames": [ + { + "coords": [ + 0.0, + 1.0 + ], + "leftHandle": [ + -0.9597616195678711, + 1.0 + ], + "rightHandle": [ + 0.9597616195678711, + 1.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -4.371138828673793e-08 + ], + "leftHandle": [ + 1.4985717137654622, + -4.371138828673793e-08 + ], + "rightHandle": [ + 3.4180949529012046, + -4.371138828673793e-08 + ] + } + ] + }, + { + "channelComponentName": "Rotation X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Z", + "keyFrames": [ + { + "coords": [ + 0.0, + -0.0 + ], + "leftHandle": [ + -0.9597616195678711, + -0.0 + ], + "rightHandle": [ + 0.9597616195678711, + -0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + -1.0 + ], + "leftHandle": [ + 1.4985717137654622, + -1.0 + ], + "rightHandle": [ + 3.4180949529012046, + -1.0 + ] + } + ] + }, + { + "channelComponentName": "Rotation Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Rotation", + "jointIndex": 3 + }, + { + "channelComponents": [ + { + "channelComponentName": "Location X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Location Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Location Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Location", + "jointIndex": 3 + }, + { + "channelComponents": [ + { + "channelComponentName": "Scale X", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 5.0 + ], + "leftHandle": [ + 1.4985717137654622, + 5.0 + ], + "rightHandle": [ + 3.4180949529012046, + 5.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Y", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + }, + { + "channelComponentName": "Scale Z", + "keyFrames": [ + { + "coords": [ + 0.0, + 0.0 + ], + "leftHandle": [ + -0.9597616195678711, + 0.0 + ], + "rightHandle": [ + 0.9597616195678711, + 0.0 + ] + }, + { + "coords": [ + 2.4583333333333335, + 0.0 + ], + "leftHandle": [ + 1.4985717137654622, + 0.0 + ], + "rightHandle": [ + 3.4180949529012046, + 0.0 + ] + } + ] + } + ], + "channelName": "Scale", + "jointIndex": 3 + } + ] + } + ] +} diff --git a/tests/auto/animation/animationutils/tst_animationutils.cpp b/tests/auto/animation/animationutils/tst_animationutils.cpp index 36e954a85..5ec8c7d60 100644 --- a/tests/auto/animation/animationutils/tst_animationutils.cpp +++ b/tests/auto/animation/animationutils/tst_animationutils.cpp @@ -30,6 +30,7 @@ #include <Qt3DAnimation/private/animationclip_p.h> #include <Qt3DAnimation/private/animationutils_p.h> #include <Qt3DAnimation/private/blendedclipanimator_p.h> +#include <Qt3DAnimation/private/clock_p.h> #include <Qt3DAnimation/private/channelmapper_p.h> #include <Qt3DAnimation/private/channelmapping_p.h> #include <Qt3DAnimation/private/clipblendvalue_p.h> @@ -51,6 +52,7 @@ using namespace Qt3DAnimation::Animation; Q_DECLARE_METATYPE(Qt3DAnimation::Animation::Handler*) Q_DECLARE_METATYPE(QVector<ChannelMapping *>) +Q_DECLARE_METATYPE(Clock *) Q_DECLARE_METATYPE(ChannelMapper *) Q_DECLARE_METATYPE(AnimationClip *) Q_DECLARE_METATYPE(QVector<MappingData>) @@ -61,6 +63,7 @@ Q_DECLARE_METATYPE(ClipEvaluationData) Q_DECLARE_METATYPE(ClipAnimator *) Q_DECLARE_METATYPE(BlendedClipAnimator *) Q_DECLARE_METATYPE(QVector<ChannelNameAndType>) +Q_DECLARE_METATYPE(QVector<AnimationCallbackAndValue>) namespace { @@ -122,6 +125,12 @@ bool fuzzyCompare(float x1, float x2) } } +class DummyCallback : public Qt3DAnimation::QAnimationCallback +{ +public: + void valueChanged(const QVariant &) override { } +}; + } // anonymous @@ -140,11 +149,25 @@ public: auto channelMappingId = Qt3DCore::QNodeId::createId(); ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); setPeerId(channelMapping, channelMappingId); + channelMapping->setHandler(handler); channelMapping->setTargetId(targetId); channelMapping->setProperty(property); channelMapping->setPropertyName(propertyName); channelMapping->setChannelName(channelName); channelMapping->setType(type); + channelMapping->setMappingType(ChannelMapping::ChannelMappingType); + return channelMapping; + } + + ChannelMapping *createChannelMapping(Handler *handler, + const Qt3DCore::QNodeId skeletonId) + { + auto channelMappingId = Qt3DCore::QNodeId::createId(); + ChannelMapping *channelMapping = handler->channelMappingManager()->getOrCreateResource(channelMappingId); + setPeerId(channelMapping, channelMappingId); + channelMapping->setHandler(handler); + channelMapping->setSkeletonId(skeletonId); + channelMapping->setMappingType(ChannelMapping::SkeletonMappingType); return channelMapping; } @@ -238,9 +261,19 @@ public: return node; } + Skeleton *createSkeleton(Handler *handler, int jointCount) + { + auto skeletonId = Qt3DCore::QNodeId::createId(); + Skeleton *skeleton = handler->skeletonManager()->getOrCreateResource(skeletonId); + setPeerId(skeleton, skeletonId); + skeleton->setJointCount(jointCount); + return skeleton; + } + private Q_SLOTS: void checkBuildPropertyMappings_data() { + QTest::addColumn<Handler *>("handler"); QTest::addColumn<QVector<ChannelMapping *>>("channelMappings"); QTest::addColumn<QVector<ChannelNameAndType>>("channelNamesAndTypes"); QTest::addColumn<QVector<ComponentIndices>>("channelComponentIndices"); @@ -248,12 +281,14 @@ private Q_SLOTS: // Single ChannelMapping { - auto channelMapping = new ChannelMapping(); - channelMapping->setChannelName("Location"); - channelMapping->setTargetId(Qt3DCore::QNodeId::createId()); - channelMapping->setProperty(QLatin1String("translation")); - channelMapping->setPropertyName("translation"); - channelMapping->setType(static_cast<int>(QVariant::Vector3D)); + Handler *handler = new Handler(); + + auto channelMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); QVector<ChannelMapping *> channelMappings = { channelMapping }; @@ -289,6 +324,7 @@ private Q_SLOTS: QVector<MappingData> expectedResults = { expectedMapping }; QTest::newRow("single mapping") + << handler << channelMappings << channelNamesAndTypes << channelComponentIndices @@ -297,40 +333,42 @@ private Q_SLOTS: // Multiple ChannelMappings { - auto locationMapping = new ChannelMapping(); - locationMapping->setChannelName("Location"); - locationMapping->setTargetId(Qt3DCore::QNodeId::createId()); - locationMapping->setProperty(QLatin1String("translation")); - locationMapping->setPropertyName("translation"); - locationMapping->setType(static_cast<int>(QVariant::Vector3D)); - - auto metalnessMapping = new ChannelMapping(); - metalnessMapping->setChannelName("Metalness"); - metalnessMapping->setTargetId(Qt3DCore::QNodeId::createId()); - metalnessMapping->setProperty(QLatin1String("metalness")); - metalnessMapping->setPropertyName("metalness"); - metalnessMapping->setType(static_cast<int>(QVariant::Double)); - - auto baseColorMapping = new ChannelMapping(); - baseColorMapping->setChannelName("BaseColor"); - baseColorMapping->setTargetId(Qt3DCore::QNodeId::createId()); - baseColorMapping->setProperty(QLatin1String("baseColor")); - baseColorMapping->setPropertyName("baseColor"); - baseColorMapping->setType(static_cast<int>(QVariant::Vector3D)); - - auto roughnessMapping = new ChannelMapping(); - roughnessMapping->setChannelName("Roughness"); - roughnessMapping->setTargetId(Qt3DCore::QNodeId::createId()); - roughnessMapping->setProperty(QLatin1String("roughness")); - roughnessMapping->setPropertyName("roughness"); - roughnessMapping->setType(static_cast<int>(QVariant::Double)); - - auto rotationMapping = new ChannelMapping(); - rotationMapping->setChannelName("Rotation"); - rotationMapping->setTargetId(Qt3DCore::QNodeId::createId()); - rotationMapping->setProperty(QLatin1String("rotation")); - rotationMapping->setPropertyName("rotation"); - rotationMapping->setType(static_cast<int>(QVariant::Quaternion)); + Handler *handler = new Handler(); + + auto locationMapping = createChannelMapping(handler, + QLatin1String("Location"), + Qt3DCore::QNodeId::createId(), + QLatin1String("translation"), + "translation", + static_cast<int>(QVariant::Vector3D)); + + auto metalnessMapping = createChannelMapping(handler, + QLatin1String("Metalness"), + Qt3DCore::QNodeId::createId(), + QLatin1String("metalness"), + "metalness", + static_cast<int>(QVariant::Double)); + + auto baseColorMapping = createChannelMapping(handler, + QLatin1String("BaseColor"), + Qt3DCore::QNodeId::createId(), + QLatin1String("baseColor"), + "baseColor", + static_cast<int>(QVariant::Vector3D)); + + auto roughnessMapping = createChannelMapping(handler, + QLatin1String("Roughness"), + Qt3DCore::QNodeId::createId(), + QLatin1String("roughness"), + "roughness", + static_cast<int>(QVariant::Double)); + + auto rotationMapping = createChannelMapping(handler, + QLatin1String("Rotation"), + Qt3DCore::QNodeId::createId(), + QLatin1String("rotation"), + "rotation", + static_cast<int>(QVariant::Quaternion)); QVector<ChannelMapping *> channelMappings = { locationMapping, metalnessMapping, @@ -399,6 +437,77 @@ private Q_SLOTS: expectedRotationMapping }; QTest::newRow("multiple mappings") + << handler + << channelMappings + << channelNamesAndTypes + << channelComponentIndices + << expectedResults; + } + + // Single skeleton mapping + { + Handler *handler = new Handler(); + const int jointCount = 4; + auto skeleton = createSkeleton(handler, jointCount); + auto channelMapping = createChannelMapping(handler, skeleton->peerId()); + + QVector<ChannelMapping *> channelMappings = { channelMapping }; + + // Create a few channels in the format description + QVector<ChannelNameAndType> channelNamesAndTypes; + for (int i = 0; i < jointCount; ++i) { + channelNamesAndTypes.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), i }); + channelNamesAndTypes.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), i }); + channelNamesAndTypes.push_back({ QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), i }); + } + + // And the matching indices + QVector<ComponentIndices> channelComponentIndices; + channelComponentIndices.push_back({ 0, 1, 2 }); + channelComponentIndices.push_back({ 3, 4, 5, 6 }); + channelComponentIndices.push_back({ 7, 8, 9 }); + + channelComponentIndices.push_back({ 10, 11, 12 }); + channelComponentIndices.push_back({ 13, 14, 15, 16 }); + channelComponentIndices.push_back({ 17, 18, 19 }); + + channelComponentIndices.push_back({ 20, 21, 22 }); + channelComponentIndices.push_back({ 23, 24, 25, 26 }); + channelComponentIndices.push_back({ 27, 28, 29 }); + + channelComponentIndices.push_back({ 30, 31, 32 }); + channelComponentIndices.push_back({ 33, 34, 35, 36 }); + channelComponentIndices.push_back({ 37, 38, 39 }); + + QVector<MappingData> expectedResults; + int componentIndicesIndex = 0; + for (int i = 0; i < jointCount; ++i) { + MappingData locationMapping; + locationMapping.targetId = channelMapping->skeletonId(); + locationMapping.propertyName = "translation"; + locationMapping.type = static_cast<int>(QVariant::Vector3D); + locationMapping.channelIndices = channelComponentIndices[componentIndicesIndex++]; + locationMapping.jointIndex = i; + + MappingData rotationMapping; + rotationMapping.targetId = channelMapping->skeletonId(); + rotationMapping.propertyName = "rotation"; + rotationMapping.type = static_cast<int>(QVariant::Quaternion); + rotationMapping.channelIndices = channelComponentIndices[componentIndicesIndex++]; + rotationMapping.jointIndex = i; + + MappingData scaleMapping; + scaleMapping.targetId = channelMapping->skeletonId(); + scaleMapping.propertyName = "scale"; + scaleMapping.type = static_cast<int>(QVariant::Vector3D); + scaleMapping.channelIndices = channelComponentIndices[componentIndicesIndex++]; + scaleMapping.jointIndex = i; + + expectedResults << locationMapping << rotationMapping << scaleMapping; + } + + QTest::newRow("single skeleton mapping") + << handler << channelMappings << channelNamesAndTypes << channelComponentIndices @@ -409,6 +518,7 @@ private Q_SLOTS: void checkBuildPropertyMappings() { // GIVEN + QFETCH(Handler *, handler); QFETCH(QVector<ChannelMapping *>, channelMappings); QFETCH(QVector<ChannelNameAndType>, channelNamesAndTypes); QFETCH(QVector<ComponentIndices>, channelComponentIndices); @@ -426,6 +536,7 @@ private Q_SLOTS: const auto expectedMapping = expectedResults[i]; QCOMPARE(actualMapping.targetId, expectedMapping.targetId); + QCOMPARE(actualMapping.jointIndex, expectedMapping.jointIndex); QCOMPARE(actualMapping.propertyName, expectedMapping.propertyName); QCOMPARE(actualMapping.type, expectedMapping.type); QCOMPARE(actualMapping.channelIndices.size(), expectedMapping.channelIndices.size()); @@ -433,338 +544,142 @@ private Q_SLOTS: QCOMPARE(actualMapping.channelIndices[j], expectedMapping.channelIndices[j]); } } + + // Cleanup + delete handler; } - void checkLocalTimeFromGlobalTime_data() + void checkLocalTimeFromElapsedTime_data() { - QTest::addColumn<double>("globalTime"); - QTest::addColumn<double>("globalStartTime"); + QTest::addColumn<double>("elapsedTime"); + QTest::addColumn<double>("currentTime"); QTest::addColumn<double>("playbackRate"); QTest::addColumn<double>("duration"); QTest::addColumn<int>("loopCount"); + QTest::addColumn<int>("currentLoop"); QTest::addColumn<double>("expectedLocalTime"); QTest::addColumn<int>("expectedCurrentLoop"); - double globalTime; - double globalStartTime; + double elapsedTime; + double currentTime; double playbackRate; double duration; int loopCount; + int currentLoop; double expectedLocalTime; int expectedCurrentLoop; - globalTime = 0.0; - globalStartTime = 0.0; + elapsedTime = 0.0; + currentTime = 0.0; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 0.0; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0, t_elapsed = 0, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 0.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.0; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 0.5; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0, t_elapsed = 0.5, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 1.0; - globalStartTime = 0.0; + elapsedTime = 1.5; + currentTime = 0.0; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 1.0; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.0") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = -0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedLocalTime = 0.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = -0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0, t_elapsed = 1.5, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 1.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.6; playbackRate = 1.0; duration = 1.0; loopCount = 1; + currentLoop = 0; expectedLocalTime = 1.0; expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 0") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 0.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.6; playbackRate = 1.0; duration = 1.0; loopCount = 2; - expectedLocalTime = 0.5; - expectedCurrentLoop = 0; - QTest::newRow("simple, loopCount = 2, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 2; - expectedLocalTime = 0.5; + currentLoop = 0; + expectedLocalTime = 0.1; expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = 2, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 0, loop_count = 2") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 3.5; - globalStartTime = 0.0; + elapsedTime = 0.5; + currentTime = 0.6; playbackRate = 1.0; - duration = 2.0; - loopCount = 2; - expectedLocalTime = 1.5; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 3.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 4.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 2.0; + duration = 1.0; loopCount = 2; - expectedLocalTime = 2.0; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 4.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount + currentLoop = 1; + expectedLocalTime = 1.0; + expectedCurrentLoop = 1; // We clamp at end of final loop + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 1, loop_count = 2") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; + elapsedTime = 0.5; + currentTime = 0.6; + playbackRate = 0.1; duration = 1.0; - loopCount = -1; - expectedLocalTime = 0.5; + loopCount = 2; + currentLoop = 1; + expectedLocalTime = 0.65; expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = inf, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedLocalTime << expectedCurrentLoop; - - globalTime = 10.2; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = -1; - expectedLocalTime = 0.2; - expectedCurrentLoop = 10; - QTest::newRow("simple, loopCount = inf, t_global = 10.2") - << globalTime << globalStartTime << playbackRate << duration << loopCount + QTest::newRow("simple, t_current = 0.5, t_elapsed = 0.6, loop_current = 1, loop_count = 2") + << elapsedTime << currentTime << playbackRate << duration << loopCount << currentLoop << expectedLocalTime << expectedCurrentLoop; } - void checkLocalTimeFromGlobalTime() + void checkLocalTimeFromElapsedTime() { // GIVEN - QFETCH(double, globalTime); - QFETCH(double, globalStartTime); + QFETCH(double, elapsedTime); + QFETCH(double, currentTime); QFETCH(double, playbackRate); QFETCH(double, duration); QFETCH(int, loopCount); + QFETCH(int, currentLoop); QFETCH(double, expectedLocalTime); QFETCH(int, expectedCurrentLoop); // WHEN - int actualCurrentLoop = 0; - double actualLocalTime = localTimeFromGlobalTime(globalTime, - globalStartTime, - playbackRate, - duration, - loopCount, - actualCurrentLoop); + int actualCurrentLoop = currentLoop; + double actualLocalTime = localTimeFromElapsedTime(currentTime, + elapsedTime, + playbackRate, + duration, + loopCount, + actualCurrentLoop); // THEN QCOMPARE(actualCurrentLoop, expectedCurrentLoop); QCOMPARE(actualLocalTime, expectedLocalTime); } - void checkPhaseFromGlobalTime_data() - { - QTest::addColumn<double>("globalTime"); - QTest::addColumn<double>("globalStartTime"); - QTest::addColumn<double>("playbackRate"); - QTest::addColumn<double>("duration"); - QTest::addColumn<int>("loopCount"); - QTest::addColumn<double>("expectedPhase"); - QTest::addColumn<int>("expectedCurrentLoop"); - - double globalTime; - double globalStartTime; - double playbackRate; - double duration; - int loopCount; - double expectedPhase; - int expectedCurrentLoop; - - globalTime = 0.0; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 0.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 0.5; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.0; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 1.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.0") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = -0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 0.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = -0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 1; - expectedPhase = 1.0; - expectedCurrentLoop = 0; - QTest::newRow("simple, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 0.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 2; - expectedPhase = 0.5; - expectedCurrentLoop = 0; - QTest::newRow("simple, loopCount = 2, t_global = 0.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = 2; - expectedPhase = 0.5; - expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = 2, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 3.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 2.0; - loopCount = 2; - expectedPhase = 0.75; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 3.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 4.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 2.0; - loopCount = 2; - expectedPhase = 1.0; - expectedCurrentLoop = 1; - QTest::newRow("duration = 2, loopCount = 2, t_global = 4.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 1.5; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = -1; - expectedPhase = 0.5; - expectedCurrentLoop = 1; - QTest::newRow("simple, loopCount = inf, t_global = 1.5") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - - globalTime = 10.2; - globalStartTime = 0.0; - playbackRate = 1.0; - duration = 1.0; - loopCount = -1; - expectedPhase = 0.2; - expectedCurrentLoop = 10; - QTest::newRow("simple, loopCount = inf, t_global = 10.2") - << globalTime << globalStartTime << playbackRate << duration << loopCount - << expectedPhase << expectedCurrentLoop; - } - - void checkPhaseFromGlobalTime() - { - // GIVEN - QFETCH(double, globalTime); - QFETCH(double, globalStartTime); - QFETCH(double, playbackRate); - QFETCH(double, duration); - QFETCH(int, loopCount); - QFETCH(double, expectedPhase); - QFETCH(int, expectedCurrentLoop); - - // WHEN - int actualCurrentLoop = 0; - double actualPhase = phaseFromGlobalTime(globalTime, - globalStartTime, - playbackRate, - duration, - loopCount, - actualCurrentLoop); - - // THEN - QCOMPARE(actualCurrentLoop, expectedCurrentLoop); - QCOMPARE(actualPhase, expectedPhase); - } - void checkPreparePropertyChanges_data() { QTest::addColumn<Qt3DCore::QNodeId>("animatorId"); @@ -1034,6 +949,117 @@ private Q_SLOTS: } } + void checkPrepareCallbacks_data() + { + QTest::addColumn<QVector<MappingData>>("mappingData"); + QTest::addColumn<QVector<float>>("channelResults"); + QTest::addColumn<QVector<AnimationCallbackAndValue> >("expectedValues"); + + QVector<MappingData> mappingData; + QVector<float> channelResults; + QVector<AnimationCallbackAndValue> expectedValues; + + // vec3 + { + DummyCallback callback; // safe since the object is never used, just the address + MappingData mapping; + mapping.targetId = Qt3DCore::QNodeId::createId(); + mapping.propertyName = "translation"; + mapping.type = static_cast<int>(QVariant::Vector3D); + mapping.channelIndices = QVector<int>() << 0 << 1 << 2; + mapping.callback = &callback; + mapping.callbackFlags = 0; + mappingData.push_back(mapping); + channelResults = QVector<float>() << 1.0f << 2.0f << 3.0f; + + AnimationCallbackAndValue cbv; + cbv.callback = mapping.callback; + cbv.flags = mapping.callbackFlags; + cbv.value = QVariant::fromValue<QVector3D>(QVector3D(1.0f, 2.0f, 3.0f)); + expectedValues.push_back(cbv); + + QTest::newRow("vec3 translation, no flags") << mappingData << channelResults << expectedValues; + + mappingData.clear(); + channelResults.clear(); + expectedValues.clear(); + } + + // double + { + DummyCallback callback; + MappingData mapping; + mapping.targetId = Qt3DCore::QNodeId::createId(); + mapping.propertyName = "something"; + mapping.type = static_cast<int>(QVariant::Double); + mapping.channelIndices = QVector<int>() << 0; + mapping.callback = &callback; + mapping.callbackFlags = 0; + mappingData.push_back(mapping); + channelResults = QVector<float>() << 1.0f; + + AnimationCallbackAndValue cbv; + cbv.callback = mapping.callback; + cbv.flags = mapping.callbackFlags; + cbv.value = QVariant(double(1.0)); + expectedValues.push_back(cbv); + + QTest::newRow("double, no flags") << mappingData << channelResults << expectedValues; + + mappingData.clear(); + channelResults.clear(); + expectedValues.clear(); + } + + // float, set a flag + { + DummyCallback callback; + MappingData mapping; + mapping.targetId = Qt3DCore::QNodeId::createId(); + mapping.propertyName = "opacity"; + mapping.type = static_cast<int>(QMetaType::Float); + mapping.channelIndices = QVector<int>() << 0; + mapping.callback = &callback; + mapping.callbackFlags = Qt3DAnimation::QAnimationCallback::OnThreadPool; + mappingData.push_back(mapping); + channelResults = QVector<float>() << 0.5f; + + AnimationCallbackAndValue cbv; + cbv.callback = mapping.callback; + cbv.flags = mapping.callbackFlags; + cbv.value = QVariant(float(0.5f)); + expectedValues.push_back(cbv); + + QTest::newRow("float, OnThreadPool") << mappingData << channelResults << expectedValues; + + mappingData.clear(); + channelResults.clear(); + expectedValues.clear(); + } + } + + void checkPrepareCallbacks() + { + // GIVEN + QFETCH(QVector<MappingData>, mappingData); + QFETCH(QVector<float>, channelResults); + QFETCH(QVector<AnimationCallbackAndValue>, expectedValues); + + // WHEN + QVector<AnimationCallbackAndValue> callbacks = prepareCallbacks(mappingData, channelResults); + + // THEN + QCOMPARE(callbacks.size(), expectedValues.size()); + for (int i = 0; i < callbacks.size(); ++i) { + auto expected = expectedValues[i]; + auto actual = callbacks[i]; + + QCOMPARE(actual.callback, expected.callback); + QCOMPARE(actual.flags, expected.flags); + QCOMPARE(actual.value, expected.value); + } + } + void checkEvaluateClipAtLocalTime_data() { QTest::addColumn<Handler *>("handler"); @@ -1284,6 +1310,31 @@ private Q_SLOTS: QVector<char> suffixes; QVector<int> expectedResults; + // already sorted vec3, no component names, with and without offset + { + channel = Channel(); + channel.name = QLatin1String("Location"); + channel.channelComponents.resize(3); + // leave 'name' empty + + dataType = static_cast<int>(QVariant::Vector3D); + offset = 0; + // suffixes expected to be ignored + expectedResults = (QVector<int>() << 0 << 1 << 2); + + QTest::newRow("vec3 location, pre-sorted, no component names, offset = 0") + << channel << dataType << offset << suffixes << expectedResults; + + expectedResults.clear(); + + offset = 4; + expectedResults = (QVector<int>() << 4 << 5 << 6); + QTest::newRow("vec3 location, pre-sorted, no component names, offset = 4") + << channel << dataType << offset << suffixes << expectedResults; + + expectedResults.clear(); + } + // vec3 with and without offset { channel = Channel(); @@ -1622,6 +1673,7 @@ private Q_SLOTS: AnimationClip *clip; AnimatorEvaluationData animatorData; ClipEvaluationData clipData; + auto* clock = new Clock; { handler = new Handler(); @@ -1629,11 +1681,13 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = 0; - animatorData = evaluationDataForAnimator(animator, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = 0; + animatorData = evaluationDataForAnimator(animator, clock, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, @@ -1650,18 +1704,20 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = (clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip - animatorData = evaluationDataForAnimator(animator, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = (clip->duration()+1)*1e09; // +1 to ensure beyond end + animatorData = evaluationDataForAnimator(animator, nullptr, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, clipData.currentLoop); // Tested elsewhere clipData.isFinalFrame = true; - QTest::newRow("clip1.json, globalTime = duration") + QTest::newRow("clip1.json, elapsedTime = duration + 1") << handler << clip << animatorData << clipData; } @@ -1671,18 +1727,43 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 0; // Infinite loops auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = 2.0 * clip->duration() * 1.0e9; - animatorData = evaluationDataForAnimator(animator, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = 2.0 * clip->duration() * 1.0e9; + animatorData = evaluationDataForAnimator(animator, clock, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, clipData.currentLoop); // Tested elsewhere clipData.isFinalFrame = false; - QTest::newRow("clip1.json, globalTime = 2 * duration, loops = infinite") + QTest::newRow("clip1.json, elapsedTime = 2 * duration, loops = infinite") + << handler << clip << animatorData << clipData; + } + + { + handler = new Handler(); + clip = createAnimationClipLoader(handler, QUrl("qrc:/clip1.json")); + const qint64 globalStartTimeNS = 0; + const int loops = 2; + auto animator = createClipAnimator(handler, globalStartTimeNS, loops); + animator->setCurrentLoop(0); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = (2.0 * clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip + animatorData = evaluationDataForAnimator(animator, nullptr, elapsedTimeNS); // Tested elsewhere + + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, + animatorData.playbackRate, + clip->duration(), + animatorData.loopCount, + clipData.currentLoop); // Tested elsewhere + clipData.isFinalFrame = true; + + QTest::newRow("clip1.json, elapsedTime = 2 * duration + 1, loops = 2") << handler << clip << animatorData << clipData; } @@ -1692,18 +1773,20 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 2; auto animator = createClipAnimator(handler, globalStartTimeNS, loops); - const qint64 globalTimeNS = (2.0 * clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip - animatorData = evaluationDataForAnimator(animator, globalTimeNS); // Tested elsewhere + animator->setCurrentLoop(1); + clipData.currentLoop = animator->currentLoop(); + const qint64 elapsedTimeNS = (clip->duration() + 1.0) * 1.0e9; // +1 to ensure beyond end of clip + animatorData = evaluationDataForAnimator(animator, nullptr, elapsedTimeNS); // Tested elsewhere - clipData.localTime = localTimeFromGlobalTime(animatorData.globalTime, - animatorData.startTime, + clipData.localTime = localTimeFromElapsedTime(animatorData.currentTime, + animatorData.elapsedTime, animatorData.playbackRate, clip->duration(), animatorData.loopCount, clipData.currentLoop); // Tested elsewhere clipData.isFinalFrame = true; - QTest::newRow("clip1.json, globalTime = 2 * duration + 1, loops = 2") + QTest::newRow("clip1.json, elapsedTime = duration + 1, loops = 2, current_loop = 1") << handler << clip << animatorData << clipData; } } @@ -1732,12 +1815,12 @@ private Q_SLOTS: { QTest::addColumn<Handler *>("handler"); QTest::addColumn<ClipAnimator *>("animator"); - QTest::addColumn<qint64>("globalTimeNS"); + QTest::addColumn<qint64>("elapsedTime"); QTest::addColumn<AnimatorEvaluationData>("expectedAnimatorData"); Handler *handler; ClipAnimator *animator; - qint64 globalTimeNS; + qint64 elapsedTimeNS; AnimatorEvaluationData expectedAnimatorData; { @@ -1745,15 +1828,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 0; + elapsedTimeNS = 0; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 0.0; - expectedAnimatorData.globalTime = 0.0; + expectedAnimatorData.elapsedTime = 0.0; - QTest::newRow("globalStartTime = 0, globalTime = 0, loops = 1") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 0, elapsedTime = 0, loops = 1") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } { @@ -1761,15 +1843,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 5; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 0; + elapsedTimeNS = 0; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 0.0; - expectedAnimatorData.globalTime = 0.0; + expectedAnimatorData.elapsedTime = 0.0; - QTest::newRow("globalStartTime = 0, globalTime = 0, loops = 5") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 0, elapsedTime = 0, loops = 5") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } { @@ -1777,15 +1858,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 0; const int loops = 1; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 5000000000; + elapsedTimeNS = 5000000000; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 0.0; - expectedAnimatorData.globalTime = 5.0; + expectedAnimatorData.elapsedTime = 5.0; - QTest::newRow("globalStartTime = 0, globalTime = 5, loops = 1") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 0, elapsedTime = 5, loops = 1") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } { @@ -1793,15 +1873,14 @@ private Q_SLOTS: const qint64 globalStartTimeNS = 3000000000; const int loops = 1; animator = createClipAnimator(handler, globalStartTimeNS, loops); - globalTimeNS = 5000000000; + elapsedTimeNS = 2000000000; expectedAnimatorData.loopCount = loops; expectedAnimatorData.playbackRate = 1.0; // hard-wired for now - expectedAnimatorData.startTime = 3.0; - expectedAnimatorData.globalTime = 5.0; + expectedAnimatorData.elapsedTime = 2.0; - QTest::newRow("globalStartTime = 3, globalTime = 5, loops = 1") - << handler << animator << globalTimeNS << expectedAnimatorData; + QTest::newRow("globalStartTime = 3, elapsedTime = 2, loops = 1") + << handler << animator << elapsedTimeNS << expectedAnimatorData; } } @@ -1810,17 +1889,16 @@ private Q_SLOTS: // GIVEN QFETCH(Handler *, handler); QFETCH(ClipAnimator *, animator); - QFETCH(qint64, globalTimeNS); + QFETCH(qint64, elapsedTime); QFETCH(AnimatorEvaluationData, expectedAnimatorData); // WHEN - AnimatorEvaluationData actualAnimatorData = evaluationDataForAnimator(animator, globalTimeNS); + AnimatorEvaluationData actualAnimatorData = evaluationDataForAnimator(animator, nullptr, elapsedTime); // THEN QCOMPARE(actualAnimatorData.loopCount, expectedAnimatorData.loopCount); QVERIFY(fuzzyCompare(actualAnimatorData.playbackRate, expectedAnimatorData.playbackRate) == true); - QVERIFY(fuzzyCompare(actualAnimatorData.startTime, expectedAnimatorData.startTime) == true); - QVERIFY(fuzzyCompare(actualAnimatorData.globalTime, expectedAnimatorData.globalTime) == true); + QVERIFY(fuzzyCompare(actualAnimatorData.elapsedTime, expectedAnimatorData.elapsedTime) == true); // Cleanup delete handler; @@ -2304,6 +2382,27 @@ private Q_SLOTS: QTest::addRow("Multiple channels with repeats") << handler << channelMapper << expectedResults; } + + { + auto handler = new Handler(); + const int jointCount = 10; + auto skeleton = createSkeleton(handler, jointCount); + auto channelMapping = createChannelMapping(handler, skeleton->peerId()); + QVector<ChannelMapping *> channelMappings; + channelMappings.push_back(channelMapping); + + auto channelMapper = createChannelMapper(handler, + QVector<Qt3DCore::QNodeId>() << channelMapping->peerId()); + + QVector<ChannelNameAndType> expectedResults; + for (int i = 0; i < jointCount; ++i) { + expectedResults.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), i }); + expectedResults.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), i }); + expectedResults.push_back({ QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), i }); + } + + QTest::addRow("Skeleton, 10 joints") << handler << channelMapper << expectedResults; + } } void checkBuildRequiredChannelsAndTypes() @@ -2369,6 +2468,35 @@ private Q_SLOTS: QTest::newRow("vec3 location, quaterion rotation, pbr metal-rough") << allChannels << expectedResults; } + + { + QVector<ChannelNameAndType> allChannels; + const int jointCount = 4; + for (int i = 0; i < jointCount; ++i) { + allChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), i }); + allChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), i }); + allChannels.push_back({ QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), i }); + } + + QVector<ComponentIndices> expectedResults; + expectedResults.push_back({ 0, 1, 2 }); + expectedResults.push_back({ 3, 4, 5, 6 }); + expectedResults.push_back({ 7, 8, 9 }); + + expectedResults.push_back({ 10, 11, 12 }); + expectedResults.push_back({ 13, 14, 15, 16 }); + expectedResults.push_back({ 17, 18, 19 }); + + expectedResults.push_back({ 20, 21, 22 }); + expectedResults.push_back({ 23, 24, 25, 26 }); + expectedResults.push_back({ 27, 28, 29 }); + + expectedResults.push_back({ 30, 31, 32 }); + expectedResults.push_back({ 33, 34, 35, 36 }); + expectedResults.push_back({ 37, 38, 39 }); + + QTest::newRow("skeleton, 4 joints") << allChannels << expectedResults; + } } void checkAssignChannelComponentIndices() @@ -2517,6 +2645,54 @@ private Q_SLOTS: QTest::newRow("location, rotation, albedo (missing), metal-rough") << targetChannels << targetIndices << clip << expectedResults; } + + { + QVector<ChannelNameAndType> targetChannels; + const int jointCount = 4; + for (int i = 0; i < jointCount; ++i) { + targetChannels.push_back({ QLatin1String("Location"), static_cast<int>(QVariant::Vector3D), i }); + targetChannels.push_back({ QLatin1String("Rotation"), static_cast<int>(QVariant::Quaternion), i }); + targetChannels.push_back({ QLatin1String("Scale"), static_cast<int>(QVariant::Vector3D), i }); + } + + QVector<ComponentIndices> targetIndices; + targetIndices.push_back({ 0, 1, 2 }); + targetIndices.push_back({ 3, 4, 5, 6 }); + targetIndices.push_back({ 7, 8, 9 }); + + targetIndices.push_back({ 10, 11, 12 }); + targetIndices.push_back({ 13, 14, 15, 16 }); + targetIndices.push_back({ 17, 18, 19 }); + + targetIndices.push_back({ 20, 21, 22 }); + targetIndices.push_back({ 23, 24, 25, 26 }); + targetIndices.push_back({ 27, 28, 29 }); + + targetIndices.push_back({ 30, 31, 32 }); + targetIndices.push_back({ 33, 34, 35, 36 }); + targetIndices.push_back({ 37, 38, 39 }); + + auto *clip = new AnimationClip(); + clip->setDataType(AnimationClip::File); + clip->setSource(QUrl("qrc:/clip5.json")); + clip->loadAnimation(); + + ComponentIndices expectedResults = { 4, 6, 5, // Location, joint 0 (y/z swapped in clip5.json) + 0, 1, 3, 2, // Rotation, joint 0 (y/z swapped in clip5.json) + 7, 8, 9, // Scale, joint 0 + 14, 16, 15, // Location, joint 1 (y/z swapped in clip5.json) + 10, 11, 13, 12, // Rotation, joint 1 (y/z swapped in clip5.json) + 17, 18, 19, // Scale, joint 1 + 24, 26, 25, // Location, joint 2 (y/z swapped in clip5.json) + 20, 21, 23, 22, // Rotation, joint 2 (y/z swapped in clip5.json) + 27, 28, 29, // Scale, joint 2 + 34, 36, 35, // Location, joint 3 (y/z swapped in clip5.json) + 30, 31, 33, 32, // Rotation, joint 3 (y/z swapped in clip5.json) + 37, 38, 39 }; // Scale, joint 3 + + QTest::newRow("skeleton (SQT), 4 joints") + << targetChannels << targetIndices << clip << expectedResults; + } } void checkGenerateClipFormatIndices() diff --git a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp index 3265de167..c0e1581f9 100644 --- a/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp +++ b/tests/auto/animation/blendedclipanimator/tst_blendedclipanimator.cpp @@ -63,7 +63,8 @@ private Q_SLOTS: QCOMPARE(backendBlendedClipAnimator.blendTreeRootId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.mapperId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.isRunning(), false); - QCOMPARE(backendBlendedClipAnimator.startTime(), 0); + QCOMPARE(backendBlendedClipAnimator.lastLocalTime(), 0.0); + QCOMPARE(backendBlendedClipAnimator.nsSincePreviousFrame(0), 0); QCOMPARE(backendBlendedClipAnimator.currentLoop(), 0); QCOMPARE(backendBlendedClipAnimator.loops(), 1); @@ -82,6 +83,7 @@ private Q_SLOTS: backendBlendedClipAnimator.setMapperId(Qt3DCore::QNodeId::createId()); backendBlendedClipAnimator.setRunning(true); backendBlendedClipAnimator.setStartTime(28); + backendBlendedClipAnimator.setLastLocalTime(0.28); backendBlendedClipAnimator.cleanup(); // THEN @@ -89,7 +91,8 @@ private Q_SLOTS: QCOMPARE(backendBlendedClipAnimator.blendTreeRootId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.mapperId(), Qt3DCore::QNodeId()); QCOMPARE(backendBlendedClipAnimator.isRunning(), false); - QCOMPARE(backendBlendedClipAnimator.startTime(), 0); + QCOMPARE(backendBlendedClipAnimator.lastLocalTime(), 0.0); + QCOMPARE(backendBlendedClipAnimator.nsSincePreviousFrame(0), 0); QCOMPARE(backendBlendedClipAnimator.currentLoop(), 0); QCOMPARE(backendBlendedClipAnimator.loops(), 1); } diff --git a/tests/auto/animation/channelmapping/tst_channelmapping.cpp b/tests/auto/animation/channelmapping/tst_channelmapping.cpp index 478406336..a947d4a2d 100644 --- a/tests/auto/animation/channelmapping/tst_channelmapping.cpp +++ b/tests/auto/animation/channelmapping/tst_channelmapping.cpp @@ -31,8 +31,10 @@ #include <Qt3DAnimation/private/handler_p.h> #include <Qt3DAnimation/private/channelmapping_p.h> #include <Qt3DAnimation/qchannelmapping.h> +#include <Qt3DAnimation/qskeletonmapping.h> #include <Qt3DAnimation/private/qchannelmapping_p.h> #include <Qt3DCore/qentity.h> +#include <Qt3DCore/qskeleton.h> #include <Qt3DCore/private/qnode_p.h> #include <Qt3DCore/private/qscene_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> @@ -66,6 +68,23 @@ private Q_SLOTS: QCOMPARE(backendMapping.channelName(), mapping.channelName()); QCOMPARE(backendMapping.targetId(), mapping.target()->id()); QCOMPARE(backendMapping.property(), mapping.property()); + QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType); + + // GIVEN + Qt3DAnimation::Animation::ChannelMapping backendSkeletonMapping; + backendSkeletonMapping.setHandler(&handler); + Qt3DAnimation::QSkeletonMapping skeletonMapping; + auto skeleton = new Qt3DCore::QSkeleton; + skeletonMapping.setSkeleton(skeleton); + + // WHEN + simulateInitialization(&skeletonMapping, &backendSkeletonMapping); + + // THEN + QCOMPARE(backendSkeletonMapping.peerId(), skeletonMapping.id()); + QCOMPARE(backendSkeletonMapping.isEnabled(), skeletonMapping.isEnabled()); + QCOMPARE(backendSkeletonMapping.skeletonId(), skeletonMapping.skeleton()->id()); + QCOMPARE(backendSkeletonMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::SkeletonMappingType); } void checkInitialAndCleanedUpState() @@ -81,6 +100,8 @@ private Q_SLOTS: QCOMPARE(backendMapping.channelName(), QString()); QCOMPARE(backendMapping.targetId(), Qt3DCore::QNodeId()); QCOMPARE(backendMapping.property(), QString()); + QCOMPARE(backendMapping.skeletonId(), Qt3DCore::QNodeId()); + QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType); // GIVEN Qt3DAnimation::QChannelMapping mapping; @@ -91,6 +112,7 @@ private Q_SLOTS: // WHEN simulateInitialization(&mapping, &backendMapping); + backendMapping.setSkeletonId(Qt3DCore::QNodeId::createId()); backendMapping.cleanup(); // THEN @@ -98,6 +120,8 @@ private Q_SLOTS: QCOMPARE(backendMapping.channelName(), QString()); QCOMPARE(backendMapping.targetId(), Qt3DCore::QNodeId()); QCOMPARE(backendMapping.property(), QString()); + QCOMPARE(backendMapping.skeletonId(), Qt3DCore::QNodeId()); + QCOMPARE(backendMapping.mappingType(), Qt3DAnimation::Animation::ChannelMapping::ChannelMappingType); } void checkPropertyChanges() @@ -146,6 +170,16 @@ private Q_SLOTS: // THEN QCOMPARE(backendMapping.property(), property); + + // WHEN + const auto skeletonId = Qt3DCore::QNodeId::createId(); + updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); + updateChange->setPropertyName("skeleton"); + updateChange->setValue(QVariant::fromValue(skeletonId)); + backendMapping.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendMapping.skeletonId(), skeletonId); } }; diff --git a/tests/auto/animation/clipanimator/tst_clipanimator.cpp b/tests/auto/animation/clipanimator/tst_clipanimator.cpp index e837a2a82..168cba050 100644 --- a/tests/auto/animation/clipanimator/tst_clipanimator.cpp +++ b/tests/auto/animation/clipanimator/tst_clipanimator.cpp @@ -30,6 +30,7 @@ #include <Qt3DAnimation/private/clipanimator_p.h> #include <Qt3DAnimation/qanimationcliploader.h> #include <Qt3DAnimation/qclipanimator.h> +#include <Qt3DAnimation/qclock.h> #include <Qt3DCore/private/qnode_p.h> #include <Qt3DCore/private/qscene_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> @@ -50,8 +51,10 @@ private Q_SLOTS: backendAnimator.setHandler(&handler); Qt3DAnimation::QClipAnimator animator; auto clip = new Qt3DAnimation::QAnimationClipLoader(); + auto clock = new Qt3DAnimation::QClock(); animator.setClip(clip); + animator.setClock(clock); animator.setLoopCount(10); // WHEN @@ -61,6 +64,7 @@ private Q_SLOTS: QCOMPARE(backendAnimator.peerId(), animator.id()); QCOMPARE(backendAnimator.isEnabled(), animator.isEnabled()); QCOMPARE(backendAnimator.clipId(), clip->id()); + QCOMPARE(backendAnimator.clockId(), clock->id()); QCOMPARE(backendAnimator.isRunning(), animator.isRunning()); QCOMPARE(backendAnimator.loops(), animator.loopCount()); } @@ -76,23 +80,28 @@ private Q_SLOTS: QVERIFY(backendAnimator.peerId().isNull()); QCOMPARE(backendAnimator.isEnabled(), false); QCOMPARE(backendAnimator.clipId(), Qt3DCore::QNodeId()); + QCOMPARE(backendAnimator.clockId(), Qt3DCore::QNodeId()); QCOMPARE(backendAnimator.isRunning(), false); QCOMPARE(backendAnimator.loops(), 1); // GIVEN Qt3DAnimation::QClipAnimator animator; auto clip = new Qt3DAnimation::QAnimationClipLoader(); + auto clock = new Qt3DAnimation::QClock(); animator.setClip(clip); + animator.setClock(clock); animator.setRunning(true); animator.setLoopCount(25); // WHEN simulateInitialization(&animator, &backendAnimator); backendAnimator.setClipId(Qt3DCore::QNodeId::createId()); + backendAnimator.setClockId(Qt3DCore::QNodeId::createId()); backendAnimator.cleanup(); // THEN QCOMPARE(backendAnimator.clipId(), Qt3DCore::QNodeId()); + QCOMPARE(backendAnimator.clockId(), Qt3DCore::QNodeId()); QCOMPARE(backendAnimator.isEnabled(), false); QCOMPARE(backendAnimator.isRunning(), false); QCOMPARE(backendAnimator.loops(), 1); @@ -126,6 +135,16 @@ private Q_SLOTS: QCOMPARE(backendAnimator.clipId(), newClip->id()); // WHEN + auto clock = new Qt3DAnimation::QClock(); + updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); + updateChange->setPropertyName("clock"); + updateChange->setValue(QVariant::fromValue(clock->id())); + backendAnimator.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendAnimator.clockId(), clock->id()); + + // WHEN updateChange = QSharedPointer<Qt3DCore::QPropertyUpdatedChange>::create(Qt3DCore::QNodeId()); updateChange->setPropertyName("running"); updateChange->setValue(true); diff --git a/tests/auto/animation/clock/clock.pro b/tests/auto/animation/clock/clock.pro new file mode 100644 index 000000000..26b7a4b21 --- /dev/null +++ b/tests/auto/animation/clock/clock.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_clock + +QT += core-private 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_clock.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/clock/tst_clock.cpp b/tests/auto/animation/clock/tst_clock.cpp new file mode 100644 index 000000000..a81adfe7b --- /dev/null +++ b/tests/auto/animation/clock/tst_clock.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DAnimation/qclock.h> +#include <Qt3DAnimation/private/clock_p.h> +#include <Qt3DCore/private/qnode_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qbackendnode_p.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> + +class tst_Clock: public Qt3DCore::QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + void checkPeerPropertyMirroring() + { + // GIVEN + Qt3DAnimation::Animation::Clock backendClock; + Qt3DAnimation::QClock clock; + + clock.setPlaybackRate(10.5); + + // WHEN + simulateInitialization(&clock, &backendClock); + + // THEN + QCOMPARE(backendClock.playbackRate(), clock.playbackRate()); + } + + void checkInitialAndCleanedUpState() + { + // GIVEN + Qt3DAnimation::Animation::Clock backendClock; + + // THEN + QCOMPARE(backendClock.playbackRate(), 1.0); + + // GIVEN + Qt3DAnimation::QClock clock; + clock.setPlaybackRate(10.5); + + // WHEN + simulateInitialization(&clock, &backendClock); + backendClock.cleanup(); + + // THEN + QCOMPARE(backendClock.playbackRate(), 1.0); + } + + void checkSceneChangeEvents() + { + // GIVEN + Qt3DAnimation::Animation::Clock backendClock; + + { + // WHEN + const bool newValue = false; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("enabled"); + change->setValue(newValue); + backendClock.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendClock.isEnabled(), newValue); + } + { + // WHEN + const double newPlaybackRateValue = 2.0; + const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId()); + change->setPropertyName("playbackRate"); + change->setValue(newPlaybackRateValue); + backendClock.sceneChangeEvent(change); + + // THEN + QCOMPARE(backendClock.playbackRate(), newPlaybackRateValue); + } + } +}; + +QTEST_APPLESS_MAIN(tst_Clock) + +#include "tst_clock.moc" diff --git a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp index 79d18b7cf..ce37ffc76 100644 --- a/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp +++ b/tests/auto/animation/findrunningclipanimatorsjob/tst_findrunningclipanimatorsjob.cpp @@ -72,6 +72,7 @@ public: channelMapping->setPropertyName(propertyName); channelMapping->setChannelName(channelName); channelMapping->setType(type); + channelMapping->setMappingType(ChannelMapping::ChannelMappingType); return channelMapping; } diff --git a/tests/auto/animation/qcallbackmapping/qcallbackmapping.pro b/tests/auto/animation/qcallbackmapping/qcallbackmapping.pro new file mode 100644 index 000000000..2ec002878 --- /dev/null +++ b/tests/auto/animation/qcallbackmapping/qcallbackmapping.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qcallbackmapping + +QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qcallbackmapping.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp b/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp new file mode 100644 index 000000000..6a1c8da8c --- /dev/null +++ b/tests/auto/animation/qcallbackmapping/tst_qcallbackmapping.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DAnimation/qcallbackmapping.h> +#include <Qt3DAnimation/private/qcallbackmapping_p.h> +#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qentity.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <QObject> +#include <QSignalSpy> +#include <testpostmanarbiter.h> + +class DummyCallback : public Qt3DAnimation::QAnimationCallback +{ +public: + void valueChanged(const QVariant &) override { } +}; + +class tst_QCallbackMapping : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QCallbackMapping mapping; + + // THEN + QCOMPARE(mapping.channelName(), QString()); + QCOMPARE(mapping.callback(), static_cast<Qt3DAnimation::QAnimationCallback *>(nullptr)); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QCallbackMapping mapping; + + { + // WHEN + QSignalSpy spy(&mapping, SIGNAL(channelNameChanged(QString))); + const QString newValue(QStringLiteral("Rotation")); + mapping.setChannelName(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(mapping.channelName(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + mapping.setChannelName(newValue); + + // THEN + QCOMPARE(mapping.channelName(), newValue); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN + auto newValue = new DummyCallback(); + mapping.setCallback(QVariant::Quaternion, newValue); + + // THEN - no signals for callback + QCOMPARE(mapping.callback(), newValue); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DAnimation::QCallbackMapping mapping; + auto callback = new DummyCallback(); + + mapping.setChannelName(QStringLiteral("Location")); + mapping.setCallback(QVariant::Vector3D, callback); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mapping); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QCallbackMappingData>>(creationChanges.first()); + const Qt3DAnimation::QCallbackMappingData data = creationChangeData->data; + + QCOMPARE(mapping.id(), creationChangeData->subjectId()); + QCOMPARE(mapping.isEnabled(), true); + QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::CallbackMapping); + QCOMPARE(mapping.channelName(), data.channelName); + QCOMPARE(mapping.callback(), data.callback); + QCOMPARE(QVariant::Vector3D, data.type); + } + + // WHEN + mapping.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mapping); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QCallbackMappingData>>(creationChanges.first()); + const Qt3DAnimation::QCallbackMappingData data = creationChangeData->data; + + QCOMPARE(mapping.id(), creationChangeData->subjectId()); + QCOMPARE(mapping.isEnabled(), false); + QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::CallbackMapping); + QCOMPARE(mapping.channelName(), data.channelName); + QCOMPARE(mapping.callback(), data.callback); + QCOMPARE(QVariant::Vector3D, data.type); + } + } + + void checkPropertyUpdateChanges() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QCallbackMapping mapping; + arbiter.setArbiterOnNode(&mapping); + + { + // WHEN + mapping.setChannelName(QStringLiteral("Scale")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "channelName"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toString(), mapping.channelName()); + + arbiter.events.clear(); + + // WHEN + mapping.setChannelName(QStringLiteral("Scale")); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + + { + // WHEN + auto callback = new DummyCallback(); + mapping.setCallback(QVariant::Vector3D, callback, Qt3DAnimation::QAnimationCallback::OnThreadPool); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 3); + auto change = arbiter.events.at(0).staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "type"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), QVariant::Vector3D); + + change = arbiter.events.at(1).staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "callback"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(reinterpret_cast<DummyCallback *>(change->value().value<void *>()), callback); + + change = arbiter.events.at(2).staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "callbackFlags"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().toInt(), static_cast<int>(Qt3DAnimation::QAnimationCallback::OnThreadPool)); + + arbiter.events.clear(); + + // WHEN + mapping.setCallback(QVariant::Vector3D, callback, Qt3DAnimation::QAnimationCallback::OnThreadPool); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } +}; + +QTEST_MAIN(tst_QCallbackMapping) + +#include "tst_qcallbackmapping.moc" diff --git a/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp b/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp index 9d356de4c..cab5fda6f 100644 --- a/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp +++ b/tests/auto/animation/qchannelmapping/tst_qchannelmapping.cpp @@ -29,6 +29,7 @@ #include <QtTest/QTest> #include <Qt3DAnimation/qchannelmapping.h> #include <Qt3DAnimation/private/qchannelmapping_p.h> +#include <Qt3DAnimation/private/qchannelmappingcreatedchange_p.h> #include <Qt3DCore/qpropertyupdatedchange.h> #include <Qt3DCore/qentity.h> #include <Qt3DCore/qnodecreatedchange.h> @@ -142,13 +143,14 @@ private Q_SLOTS: { QCOMPARE(creationChanges.size(), 2); // 1 for mapping, 1 for target - const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QChannelMappingData>>(creationChanges.first()); + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QChannelMappingData>>(creationChanges.first()); const Qt3DAnimation::QChannelMappingData data = creationChangeData->data; QCOMPARE(mapping.id(), creationChangeData->subjectId()); QCOMPARE(mapping.isEnabled(), true); QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::ChannelMapping); QCOMPARE(mapping.channelName(), data.channelName); QCOMPARE(mapping.target()->id(), data.targetId); QCOMPARE(mapping.property(), data.property); @@ -166,13 +168,14 @@ private Q_SLOTS: { QCOMPARE(creationChanges.size(), 2); // 1 for mapping, 1 for target - const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QChannelMappingData>>(creationChanges.first()); + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QChannelMappingData>>(creationChanges.first()); const Qt3DAnimation::QChannelMappingData data = creationChangeData->data; QCOMPARE(mapping.id(), creationChangeData->subjectId()); QCOMPARE(mapping.isEnabled(), false); QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::ChannelMapping); QCOMPARE(mapping.channelName(), data.channelName); QCOMPARE(mapping.target()->id(), data.targetId); QCOMPARE(mapping.property(), data.property); diff --git a/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp b/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp index 1ed4b8f13..6a46b7008 100644 --- a/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp +++ b/tests/auto/animation/qclipanimator/tst_qclipanimator.cpp @@ -30,6 +30,7 @@ #include <QtTest/QTest> #include <Qt3DAnimation/qanimationcliploader.h> #include <Qt3DAnimation/qchannelmapper.h> +#include <Qt3DAnimation/qclock.h> #include <Qt3DAnimation/qclipanimator.h> #include <Qt3DAnimation/private/qanimationclip_p.h> #include <Qt3DAnimation/private/qclipanimator_p.h> @@ -49,6 +50,7 @@ private Q_SLOTS: { qRegisterMetaType<Qt3DAnimation::QAbstractAnimationClip*>(); qRegisterMetaType<Qt3DAnimation::QChannelMapper*>(); + qRegisterMetaType<Qt3DAnimation::QClock*>(); } void checkDefaultConstruction() @@ -59,6 +61,7 @@ private Q_SLOTS: // THEN QCOMPARE(animator.clip(), static_cast<Qt3DAnimation::QAbstractAnimationClip *>(nullptr)); QCOMPARE(animator.channelMapper(), static_cast<Qt3DAnimation::QChannelMapper *>(nullptr)); + QCOMPARE(animator.clock(), static_cast<Qt3DAnimation::QClock*>(nullptr)); QCOMPARE(animator.loopCount(), 1); } @@ -111,6 +114,27 @@ private Q_SLOTS: { // WHEN + QSignalSpy spy(&animator, SIGNAL(clockChanged(Qt3DAnimation::QClock *))); + auto clock = new Qt3DAnimation::QClock(); + animator.setClock(clock); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(animator.clock(), clock); + QCOMPARE(clock->parent(), &animator); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + animator.setClock(clock); + + // THEN + QCOMPARE(animator.clock(), clock); + QCOMPARE(spy.count(), 0); + } + + { + // WHEN QSignalSpy spy(&animator, SIGNAL(loopCountChanged(int))); const int newValue = 5; animator.setLoopCount(newValue); @@ -138,6 +162,8 @@ private Q_SLOTS: animator.setClip(clip); auto mapper = new Qt3DAnimation::QChannelMapper(); animator.setChannelMapper(mapper); + auto clock = new Qt3DAnimation::QClock(); + animator.setClock(clock); // WHEN QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; @@ -148,7 +174,7 @@ private Q_SLOTS: // THEN { - QCOMPARE(creationChanges.size(), 3); + QCOMPARE(creationChanges.size(), 4); const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QClipAnimatorData>>(creationChanges.first()); const Qt3DAnimation::QClipAnimatorData data = creationChangeData->data; @@ -159,6 +185,7 @@ private Q_SLOTS: QCOMPARE(animator.metaObject(), creationChangeData->metaObject()); QCOMPARE(animator.clip()->id(), data.clipId); QCOMPARE(animator.channelMapper()->id(), data.mapperId); + QCOMPARE(animator.clock()->id(), data.clockId); QCOMPARE(animator.loopCount(), data.loops); } @@ -171,7 +198,7 @@ private Q_SLOTS: // THEN { - QCOMPARE(creationChanges.size(), 3); + QCOMPARE(creationChanges.size(), 4); const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QClipAnimatorData>>(creationChanges.first()); @@ -240,6 +267,32 @@ private Q_SLOTS: QCOMPARE(arbiter.events.size(), 0); } + // GIVEN + auto clock = new Qt3DAnimation::QClock; + { + // WHEN + animator.setClock(clock); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "clock"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), clock->id()); + + arbiter.events.clear(); + } + + { + // WHEN + animator.setClock(clock); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + { // WHEN animator.setLoopCount(10); diff --git a/tests/auto/animation/qclock/qclock.pro b/tests/auto/animation/qclock/qclock.pro new file mode 100644 index 000000000..2b1194860 --- /dev/null +++ b/tests/auto/animation/qclock/qclock.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qclock + +QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qclock.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/qclock/tst_qclock.cpp b/tests/auto/animation/qclock/tst_qclock.cpp new file mode 100644 index 000000000..34c70da7b --- /dev/null +++ b/tests/auto/animation/qclock/tst_qclock.cpp @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QTest> +#include <Qt3DAnimation/qclock.h> +#include <Qt3DAnimation/private/qclock_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <QObject> +#include <QSignalSpy> +#include <testpostmanarbiter.h> + +class tst_QClock : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase() + { + qRegisterMetaType<Qt3DAnimation::QClock*>(); + } + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QClock clock; + + // THEN + QCOMPARE(clock.playbackRate(), 1.0); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QClock clock; + + // WHEN + QSignalSpy spy(&clock, SIGNAL(playbackRateChanged(double))); + const double newValue = 5.5; + clock.setPlaybackRate(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(clock.playbackRate(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + clock.setPlaybackRate(newValue); + + // THEN + QCOMPARE(clock.playbackRate(), newValue); + QCOMPARE(spy.count(), 0); + } + + void checkCreationData() + { + // GIVEN + Qt3DAnimation::QClock clock; + clock.setPlaybackRate(10.f); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&clock); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QClockData>>(creationChanges.first()); + const Qt3DAnimation::QClockData data = creationChangeData->data; + + QCOMPARE(clock.id(), creationChangeData->subjectId()); + QCOMPARE(clock.isEnabled(), true); + QCOMPARE(clock.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(clock.metaObject(), creationChangeData->metaObject()); + QCOMPARE(clock.playbackRate(), data.playbackRate); + } + + // WHEN + clock.setEnabled(false); + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&clock); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 1); + + const auto creationChangeData = qSharedPointerCast<Qt3DCore::QNodeCreatedChange<Qt3DAnimation::QClockData>>(creationChanges.first()); + + QCOMPARE(clock.id(), creationChangeData->subjectId()); + QCOMPARE(clock.isEnabled(), false); + QCOMPARE(clock.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(clock.metaObject(), creationChangeData->metaObject()); + } + } + + void checkPropertyUpdate() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QClock clock; + arbiter.setArbiterOnNode(&clock); + + { + // WHEN + clock.setPlaybackRate(10.5); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "playbackRate"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().value<double>(), clock.playbackRate()); + + arbiter.events.clear(); + } + + { + // WHEN + clock.setPlaybackRate(10.5f); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } +}; + +QTEST_MAIN(tst_QClock) + +#include "tst_qclock.moc" diff --git a/tests/auto/animation/qskeletonmapping/qskeletonmapping.pro b/tests/auto/animation/qskeletonmapping/qskeletonmapping.pro new file mode 100644 index 000000000..c00252557 --- /dev/null +++ b/tests/auto/animation/qskeletonmapping/qskeletonmapping.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_qskeletonmapping + +QT += 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_qskeletonmapping.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/qskeletonmapping/tst_qskeletonmapping.cpp b/tests/auto/animation/qskeletonmapping/tst_qskeletonmapping.cpp new file mode 100644 index 000000000..452292e9e --- /dev/null +++ b/tests/auto/animation/qskeletonmapping/tst_qskeletonmapping.cpp @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DAnimation/qskeletonmapping.h> +#include <Qt3DAnimation/private/qskeletonmapping_p.h> +#include <Qt3DCore/qskeleton.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/qentity.h> +#include <Qt3DCore/qnodecreatedchange.h> +#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> +#include <QObject> +#include <QSignalSpy> +#include <testpostmanarbiter.h> + +class tst_QSkeletonMapping : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase() + { + qRegisterMetaType<Qt3DCore::QAbstractSkeleton*>(); + } + + void checkDefaultConstruction() + { + // GIVEN + Qt3DAnimation::QSkeletonMapping mapping; + + // THEN + QCOMPARE(mapping.skeleton(), static_cast<Qt3DCore::QAbstractSkeleton *>(nullptr)); + } + + void checkPropertyChanges() + { + // GIVEN + Qt3DAnimation::QSkeletonMapping mapping; + + { + // WHEN + QSignalSpy spy(&mapping, SIGNAL(skeletonChanged(Qt3DCore::QAbstractSkeleton*))); + auto newValue = new Qt3DCore::QSkeleton(); + mapping.setSkeleton(newValue); + + // THEN + QVERIFY(spy.isValid()); + QCOMPARE(mapping.skeleton(), newValue); + QCOMPARE(spy.count(), 1); + + // WHEN + spy.clear(); + mapping.setSkeleton(newValue); + + // THEN + QCOMPARE(mapping.skeleton(), newValue); + QCOMPARE(spy.count(), 0); + } + } + + void checkCreationData() + { + // GIVEN + Qt3DAnimation::QSkeletonMapping mapping; + auto target = new Qt3DCore::QSkeleton; + + mapping.setSkeleton(target); + + // WHEN + QVector<Qt3DCore::QNodeCreatedChangeBasePtr> creationChanges; + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mapping); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // 1 for mapping, 1 for skeleton + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QSkeletonMappingData>>(creationChanges.first()); + const Qt3DAnimation::QSkeletonMappingData data = creationChangeData->data; + + QCOMPARE(mapping.id(), creationChangeData->subjectId()); + QCOMPARE(mapping.isEnabled(), true); + QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::SkeletonMapping); + QCOMPARE(mapping.skeleton()->id(), data.skeletonId); + } + + // WHEN + mapping.setEnabled(false); + + { + Qt3DCore::QNodeCreatedChangeGenerator creationChangeGenerator(&mapping); + creationChanges = creationChangeGenerator.creationChanges(); + } + + // THEN + { + QCOMPARE(creationChanges.size(), 2); // 1 for mapping, 1 for skeleton + + const auto creationChangeData = qSharedPointerCast<Qt3DAnimation::QChannelMappingCreatedChange<Qt3DAnimation::QSkeletonMappingData>>(creationChanges.first()); + const Qt3DAnimation::QSkeletonMappingData data = creationChangeData->data; + + QCOMPARE(mapping.id(), creationChangeData->subjectId()); + QCOMPARE(mapping.isEnabled(), false); + QCOMPARE(mapping.isEnabled(), creationChangeData->isNodeEnabled()); + QCOMPARE(mapping.metaObject(), creationChangeData->metaObject()); + QCOMPARE(creationChangeData->type(), Qt3DAnimation::QChannelMappingCreatedChangeBase::SkeletonMapping); + QCOMPARE(mapping.skeleton()->id(), data.skeletonId); + } + } + + void checkPropertyUpdateChanges() + { + // GIVEN + TestArbiter arbiter; + Qt3DAnimation::QSkeletonMapping mapping; + arbiter.setArbiterOnNode(&mapping); + + { + // WHEN + auto target = new Qt3DCore::QSkeleton(); + mapping.setSkeleton(target); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 1); + auto change = arbiter.events.first().staticCast<Qt3DCore::QPropertyUpdatedChange>(); + QCOMPARE(change->propertyName(), "skeleton"); + QCOMPARE(change->type(), Qt3DCore::PropertyUpdated); + QCOMPARE(change->value().value<Qt3DCore::QNodeId>(), mapping.skeleton()->id()); + + arbiter.events.clear(); + + // WHEN + mapping.setSkeleton(target); + QCoreApplication::processEvents(); + + // THEN + QCOMPARE(arbiter.events.size(), 0); + } + } +}; + +QTEST_MAIN(tst_QSkeletonMapping) + +#include "tst_qskeletonmapping.moc" diff --git a/tests/auto/animation/skeleton/skeleton.pro b/tests/auto/animation/skeleton/skeleton.pro new file mode 100644 index 000000000..b36278bdf --- /dev/null +++ b/tests/auto/animation/skeleton/skeleton.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +TARGET = tst_skeleton + +QT += core-private 3dcore 3dcore-private 3danimation 3danimation-private testlib + +CONFIG += testcase + +SOURCES += \ + tst_skeleton.cpp + +include(../../core/common/common.pri) diff --git a/tests/auto/animation/skeleton/tst_skeleton.cpp b/tests/auto/animation/skeleton/tst_skeleton.cpp new file mode 100644 index 000000000..9e3cfef6d --- /dev/null +++ b/tests/auto/animation/skeleton/tst_skeleton.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QTest> +#include <Qt3DCore/qjoint.h> +#include <Qt3DCore/qskeleton.h> +#include <Qt3DAnimation/private/skeleton_p.h> +#include <Qt3DAnimation/private/handler_p.h> +#include <Qt3DCore/private/qscene_p.h> +#include <Qt3DCore/qpropertyupdatedchange.h> +#include <Qt3DCore/private/qbackendnode_p.h> +#include <qbackendnodetester.h> +#include <testpostmanarbiter.h> + +using namespace Qt3DCore; +using namespace Qt3DAnimation; +using namespace Qt3DAnimation::Animation; + +class tst_Skeleton : public QBackendNodeTester +{ + Q_OBJECT + +private Q_SLOTS: + void checkPeerPropertyMirroring() + { + // GIVEN + Handler handler; + Skeleton backendSkeleton; + backendSkeleton.setHandler(&handler); + QSkeleton skeleton; + auto rootJoint = new QJoint(); + rootJoint->setName(QLatin1String("rootJoint")); + auto childJoint = new QJoint(); + childJoint->setName(QLatin1String("childJoint")); + rootJoint->addChildJoint(childJoint); + skeleton.setRootJoint(rootJoint); + + // WHEN + simulateInitialization(&skeleton, &backendSkeleton); + + // THEN - nothing mirrored from frontend + QCOMPARE(backendSkeleton.peerId(), skeleton.id()); + QCOMPARE(backendSkeleton.isEnabled(), skeleton.isEnabled()); + QCOMPARE(backendSkeleton.jointNames().size(), 0); + QCOMPARE(backendSkeleton.jointLocalPoses().size(), 0); + } + + void checkInitialAndCleanedUpState() + { + // GIVEN + Handler handler; + Skeleton backendSkeleton; + backendSkeleton.setHandler(&handler); + + // THEN + QVERIFY(backendSkeleton.peerId().isNull()); + QCOMPARE(backendSkeleton.isEnabled(), false); + QCOMPARE(backendSkeleton.jointNames().size(), 0); + QCOMPARE(backendSkeleton.jointLocalPoses().size(), 0); + + // GIVEN + const QVector<QString> names = (QVector<QString>() + << QLatin1String("root") + << QLatin1String("child1") + << QLatin1String("child2")); + const QVector<Sqt> localPoses = (QVector<Sqt>() << Sqt() << Sqt() << Sqt()); + + // WHEN + backendSkeleton.setJointNames(names); + backendSkeleton.setJointLocalPoses(localPoses); + backendSkeleton.cleanup(); + + // THEN + QCOMPARE(backendSkeleton.isEnabled(), false); + QCOMPARE(backendSkeleton.jointNames().size(), 0); + QCOMPARE(backendSkeleton.jointLocalPoses().size(), 0); + } + + void checkPropertyChanges() + { + // GIVEN + Handler handler; + Skeleton backendSkeleton; + backendSkeleton.setHandler(&handler); + QPropertyUpdatedChangePtr updateChange; + + // WHEN + updateChange = QPropertyUpdatedChangePtr::create(QNodeId()); + updateChange->setPropertyName("enabled"); + updateChange->setValue(true); + backendSkeleton.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendSkeleton.isEnabled(), true); + + // GIVEN + const QVector<QString> names = (QVector<QString>() + << QLatin1String("root") + << QLatin1String("child1") + << QLatin1String("child2")); + const QVector<Sqt> localPoses = (QVector<Sqt>() << Sqt() << Sqt() << Sqt()); + + // WHEN + JointNamesAndLocalPoses namesAndPoses; + namesAndPoses.names = names; + namesAndPoses.localPoses = localPoses; + + updateChange = QPropertyUpdatedChangePtr::create(QNodeId()); + updateChange->setPropertyName("jointNamesAndLocalPoses"); + updateChange->setValue(QVariant::fromValue(namesAndPoses)); + backendSkeleton.sceneChangeEvent(updateChange); + + // THEN + QCOMPARE(backendSkeleton.jointNames(), names); + QCOMPARE(backendSkeleton.jointLocalPoses(), localPoses); + } +}; + +QTEST_APPLESS_MAIN(tst_Skeleton) + +#include "tst_skeleton.moc" |