Qt 3D: Is Easing available for animation? - qt

I am examining 3D capabilities of Qt 6.0.1 . I have copied a sample project, but it gives error that "easing" does not have members for line easing.type :Easing.InQuad:
Here is code:
SequentialAnimation on y {
loops: Animation.Infinite
NumberAnimation {
duration: 3000
to: -150
from: 150
easing.type :Easing.InQuad
}
NumberAnimation {
duration: 3000
to: 150
from: -150
easing.type :Easing.OutQuad
}
}
Why may this happen? Does it mean that suggested example is not working?

I have used to trust IDE too much.
This is really a false positive from IDE. Code runs fine, animation seems correct.
This question may be closed.

Related

Drawer animation in QML

How to change the animation (i.e duration and easing curve) of the Drawer type in QML?
I've tried this :
PropertyAnimation{
easing.type: Easing.InOutQuad
easing.amplitude: 1000
easing.period : 1000
}
But it has no effect.(Sorry but the diversity of animation types in QML has got me confused and I'm unable to try all possible options)
You'll need to override the Popup::enter transition as documented here:
https://doc.qt.io/qt-5/qml-qtquick-controls2-popup.html#enter-prop
Note, the drawer implementation makes a lot of assumptions about how it gets on and off screen so it is easy to break it if you aren't careful.
You can see the default ones here:
https://github.com/qt/qtquickcontrols2/blob/dev/src/imports/controls/Drawer.qml
enter: Transition { SmoothedAnimation { velocity: 5 } }
exit: Transition { SmoothedAnimation { velocity: 5 } }
So, start from there and slowly tweak until you get what you want.

Property Binding on Animated Property vs Multiple Animations

Consider this example:
import QtQuick 2.7
import QtQuick.Controls 2.0
ApplicationWindow {
id: appWindow
width: 1024
height: 800
visible: true
Rectangle {
id: rect1
property bool active: true
opacity: active ? 1 : 0
height: 300 * opacity
width: 300 * opacity
Behavior on opacity { NumberAnimation { duration: 1000 } }
MouseArea { anchors.fill: parent; onClicked: parent.active = false }
color: 'cornflowerblue'
}
Rectangle {
id: rect2
property bool active: true
x: 305
opacity: active ? 1 : 0
height: active ? 300 : 0
width: active ? 300 : 0
Behavior on opacity { NumberAnimation { duration: 1000 } }
Behavior on height { NumberAnimation { duration: 1000 } }
Behavior on width { NumberAnimation { duration: 1000 } }
MouseArea { anchors.fill: parent; onClicked: parent.active = false }
color: 'steelblue'
}
}
I have two Rectangles with the same observable behavior: when clicked, they fade both in opacity and size.
Internally, it differs in the amount of Animations, that are running concurrently - either 1 or 3:
As of now, I mainly use the pattern form rect1 and only in cases where the bindings would get unneccessarily complex rect2. However I wonder, if the animation system has some magic, that optimizes the animation of a single property, while the binding might be less performant.
In which usecases it is beneficial to use pattern rect1 and when it would be wiser to use the method of rect2?
EDIT There is also a third option which moves, what possible, to the render thread via OpacityAnimator. Now I can't bind to the opacity anymore, as it will jump to 0 at the end of the animation.
Rectangle {
id: rect3
property bool active: true
opacity: active ? 1 : 0
height: active ? 300 : 0
x: 610
width: height
Behavior on opacity { OpacityAnimator { duration: 1000 } }
Behavior on height { NumberAnimation { duration: 1000 } }
MouseArea { anchors.fill: parent; onClicked: parent.active = false }
color: 'dodgerblue'
}
EDIT 2 To adress the Answer of Ansh Kumar:
This is an excerpt from the QML Profiler. You can see, that during the animation of rect2 there are neither bindings nor JavaScript running, unlike during the times where height and width are (efficiently) bound to the opacity in rect1 or the width is (efficiently) bound to the height in rect3.
Further the source of the animations shows little trace of JS. I couldn't examine it into all it's depths, but it seems, that only a ScriptAction gets a QQMLScriptString and the rest has only the cost of converting the input from var to the right type (if a type is specified by using a concrete animation such as NumberAnimation).
Further, as far as I can see, there is not a loop per animation involved, but all animations feature some kind of update()-function or so, that is called (when running/registered) by a single loop (AnimationTimer). But this is where I am already unsure about.
Now the question remains: Is the implementation of the animations more efficient than the optimized JS environment especially as multiple objects are created and stuff.
There are two types of bindings in QML: optimized and non-optimized bindings. It is a good idea to keep binding expressions as simple as possible, since the QML engine makes use of an optimized binding expression evaluator which can evaluate simple binding expressions without needing to switch into a full JavaScript execution environment. These optimized bindings are evaluated far more efficiently than more complex (non-optimized) bindings. The basic requirement for optimization of bindings is that the type information of every symbol accessed must be known at compile time.
Bindings are quickest when they know the type of objects and properties they are working with. Animating a property will cause any bindings which reference that property to be re-evaluated. Usually, this is what is desired. The opacity, height and width in rect2 are re-evaluated into a full JavaScript execution environment whereas in rect1; width and height goes through an optimized binding expression evaluator and optimized to give more efficient binding since their type of object is known at compile time. Check binding and also animations for more details.
EDIT
You were right about evaluation being done in C++ environment. I found following informations.
Rendering engine should achieve a consistent 60 frames-per-second refresh rate. 60 FPS means that there is approximately 16 milliseconds (exactly 16.6667 milliseconds) between each frame in which processing can be done, which includes the processing required to upload the draw primitives to the graphics hardware. This shows that the animation is in sync with the vertical refresh, so once every 16.66 ms, and exactly once pr frame.
while (animationIsRunning) {
processEvents();
advanceAnimations();
paintQMLScene();
swapAndBlockForNextVSync();
}
So, in rect1 you have set duration: 1000 and binded height with opacity (height: 300 * opacity) similarly width with opacity, so binding should be called around 60 times ? If you see QML profiler output of statistics you will find following
As expected number of calls are around 60 (exactly 63). Now if you change duration to 2000, number of calls will be doubled.
Since, 300 * opacity has to be calculated, so QML should call JavaScript environment around 60 times (when duration: 1000)
As expected it was called around 60 times.
What about the NumberAnimation, is it implemented in JavaScript or C++ ? Definitely, you were right about it being implemented in C++, Here is the link to its declaration . So, in rect1 we have used NumberAnimation one time and in rect2 we have used it 3 times. So, total of 4 instances of NumberAnimation should be created.
So, rect1 has a total of around 120 bindings and JavaScript calls whereas in in rect2 there is no binding and JavaScript calls, so animation of rect2 should be faster, but the question is, will there be any significant improvements? Since, free version of QtCreator does not comes with CPU analyzer I was not able to study that part of the question (CPU Usage Qt). If anyone has commercial version of Qt, please update me about my hypothesis. I really think that rect2 is the best for usage as number of calls are reduced.

RangeSlider onFirstChange non-existent property

I'm using RangeSlider for my project in QML. My range slider code is as follows:
RangeSlider {
id: rangeSLider
first.value: 0.0
second.value: 1.0
anchors.horizontalCenter: parent.horizontalCenter
width: 275
onFirstChanged: console.log("Change")
}
When I run this code, I get an error. The error is:
Cannot assign to non-existent property "onFirstChanged"
I want to change a text in a parent QML file. So I thought I'd use onFirstChange and onSecondChange functions to do that, but it did not work.
How can I do this?
For future reference, please provide a MCVE. It helps other people help you a lot easier. In this case, I'd like to see a QML snippet I could look at using qmlscene (including showing what imports you use, this is important!)
Assuming you are using QtQuickControls 2's RangeSlider, The first and second properties are constant. This means that those values themselves do not change, but rather, the members of those properties (e.g. first.value) change instead. So you want to connect the change signal to the first/second/ instance, rather than on the RangeSlider itself, something like this:
RangeSlider {
from: 1
to: 100
first.value: 30
second.value: 70
Connections {
target: first
onValueChanged: console.log("first.value changed!")
}
}
Here is the syntax for RangeSlider of Qt 5.11 (Qt QuickControls 2.4):
RangeSlider {
from: 0
to: 100
first.value: 25
second.value: 75
first.onValueChanged: console.debug("RangeSlider first value is " + first.value)
second.onValueChanged: console.debug("RangeSlider second value is " + second.value)
}
Source: http://doc.qt.io/qt-5.11/qml-qtquick-controls2-rangeslider.html

QML Moving text with timer

I need to create moving text on the screen continuously from right to left, I have implemented it using QML Timer and Text element.
The below code works fine but I am concerned about the below code causing more cpu or memory usage mainly because the timer is triggered every 33 ms. I have to use this in my places in my application and in multiple instances, like inside many grid windows.
Is this right approach? or does anything exist better than this?
Rectangle{
width:parent.width
height:parent.height
color: "#333333"
Timer {
id: resetTimer
interval: 33
repeat: true
running: true
onTriggered: {
console.log("triggred");
moving_text.x = moving_text.x-1
if(moving_text.x<-1*moving_text.paintedWidth)
moving_text.x=parent.width
}
}
Text{
id:moving_text
x:parent.width
text:"Moving text"
color: "white"
}
}
Why to make things so complected. You could use NumberAnimation on x as follows:
import QtQuick 2.0
Rectangle{
id: root
width:250
height:250
color: "#333333"
Text{
id:moving_text
x:parent.width
text:"Moving text"
color: "white"
NumberAnimation on x{
from: root.width
to: -1*moving_text.width
loops: Animation.Infinite
duration: 3000
}
}
}
As for your concern about memory and cpu usage, you should compare both the methods and check which one suits you. But my personal recommendation is to use NumberAnimation.

QML Animation with both "velocity" and infinite "loops"

I'm trying to put together an animation in which I get to specify the velocity (rather than the duration) and which loops forever. I came up with two non-working examples:
FirstTry.qml
import Qt 4.7
Rectangle {
width: 100; height: 100
Text {
text: "hello"
NumberAnimation on x {
to: 50;
loops: Animation.Infinite;
duration: 50 * Math.abs(to - from)
}
}
}
I get the following runtime warning while hello goes nuts on the screen (fair enough).
QDeclarativeExpression: Expression "(function() { return 50 * Math.abs(to - from) })" depends on non-NOTIFYable properties:
QDeclarativeNumberAnimation::to
QDeclarativeNumberAnimation::from
SecondTry.qml
import Qt 4.7
Rectangle {
width: 100; height: 100
Text {
text: "hello"
SmoothedAnimation on x {
to: 50;
loops: Animation.Infinite;
velocity: 50
}
}
}
This is more of a mistery -- SmoothedAnimation simply refuses to loop! The Animation runs once and then that's it.
So I have the following questions:
Is there a legal way to specify the velocity in the first example? I understand SmoothedAnimation is derived from NumberAnimation, so maybe it's possible in QML, not just in C++.
Is there a way to make SmoothedAnimation loop? Is the second example not working a bug or am I missing something?
Is there any other way to achieve these two behaviours at the same time?
just add "from" parameter explicitly:
import Qt 4.7
Rectangle {
width: 100; height: 100
Text {
text: "hello"
NumberAnimation on x {
from: 0;
to: 50;
loops: Animation.Infinite;
duration: 50 * Math.abs(to - from)
}
}
}
This is what I did as a temporary solution, I'm not sure if it's adequate, but it seem to be doing just what I needed.
SmoothedAnimation on x {
to: 50;
//loops: Animation.Infinite;
velocity: 50
onComplete: { restart (); }
}
I'm still interested in the answers to the questions, though.
Even if SmoothedAnimation doesn't accept loops parameter, you can place it inside SequentialAnimation and apply loops to this external cover. As an effect your smoothed animation will be played continuosly.

Resources