1 | // Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "clipblendnode_p.h" |
5 | #include <Qt3DAnimation/qabstractanimationclip.h> |
6 | |
7 | QT_BEGIN_NAMESPACE |
8 | |
9 | namespace Qt3DAnimation { |
10 | |
11 | namespace Animation { |
12 | |
13 | ClipBlendNode::ClipBlendNode(BlendType blendType) |
14 | : BackendNode(ReadOnly) // Makes sense for now at least |
15 | , m_manager(nullptr) |
16 | , m_blendType(blendType) |
17 | { |
18 | } |
19 | |
20 | ClipBlendNode::~ClipBlendNode() |
21 | { |
22 | } |
23 | |
24 | void ClipBlendNode::setClipBlendNodeManager(ClipBlendNodeManager *manager) |
25 | { |
26 | m_manager = manager; |
27 | } |
28 | |
29 | ClipBlendNode::BlendType Animation::ClipBlendNode::blendType() const |
30 | { |
31 | return m_blendType; |
32 | } |
33 | |
34 | void ClipBlendNode::setClipResults(Qt3DCore::QNodeId animatorId, const ClipResults &clipResults) |
35 | { |
36 | // Do we already have an entry for this animator? |
37 | const qsizetype animatorIndex = m_animatorIds.indexOf(t: animatorId); |
38 | if (animatorIndex == -1) { |
39 | // Nope, add it |
40 | m_animatorIds.push_back(t: animatorId); |
41 | m_clipResults.push_back(t: clipResults); |
42 | } else { |
43 | m_clipResults[animatorIndex] = clipResults; |
44 | } |
45 | } |
46 | |
47 | ClipResults ClipBlendNode::clipResults(Qt3DCore::QNodeId animatorId) const |
48 | { |
49 | const qsizetype animatorIndex = m_animatorIds.indexOf(t: animatorId); |
50 | if (animatorIndex != -1) |
51 | return m_clipResults[animatorIndex]; |
52 | return ClipResults(); |
53 | } |
54 | |
55 | /* |
56 | \fn QList<Qt3DCore::QNodeId> ClipBlendNode::currentDependencyIds() const |
57 | \internal |
58 | |
59 | Each subclass of ClipBlendNode must implement this function such that it |
60 | returns a vector of the ids of ClipBlendNodes upon which is it dependent |
61 | in order to be able to evaluate given its current internal state. |
62 | |
63 | For example, a subclass implementing a simple lerp blend between two |
64 | other nodes, would always return the ids of the nodes between which it |
65 | is lerping. |
66 | |
67 | A more generalised lerp node that is capable of lerping between a |
68 | series of nodes would return the ids of the two nodes that correspond |
69 | to the blend values which sandwich the currently set blend value. |
70 | |
71 | The animation handler will submit a job that uses this function to |
72 | build a list of clips that must be evaluated in order to later |
73 | evaluate the entire blend tree. In this way, the clips can all be |
74 | evaluated in one pass, and the tree in a subsequent pass. |
75 | */ |
76 | |
77 | /* |
78 | \fn QList<Qt3DCore::QNodeId> ClipBlendNode::allDependencyIds() const |
79 | \internal |
80 | |
81 | Similar to currentDependencyIds() but returns the ids of all potential |
82 | dependency nodes, not just those that are dependencies given the current |
83 | internal state. For example a generalised lerp node would return the ids |
84 | of all nodes that can participate in the lerp for any value of the blend |
85 | parameter. Not just those bounding the current blend value. |
86 | */ |
87 | |
88 | /* |
89 | \internal |
90 | |
91 | Fetches the ClipResults from the nodes listed in the dependencyIds |
92 | and passes them to the doBlend() virtual function which should be |
93 | implemented in subclasses to perform the actual blend operation. |
94 | The results are then inserted into the clip results for this blend |
95 | node indexed by the \a animatorId. |
96 | */ |
97 | void ClipBlendNode::blend(Qt3DCore::QNodeId animatorId) |
98 | { |
99 | // Obtain the clip results from each of the dependencies |
100 | const QList<Qt3DCore::QNodeId> dependencyNodeIds = currentDependencyIds(); |
101 | const qsizetype dependencyCount = dependencyNodeIds.size(); |
102 | QList<ClipResults> blendData; |
103 | blendData.reserve(asize: dependencyCount); |
104 | for (const auto &dependencyId : dependencyNodeIds) { |
105 | ClipBlendNode *dependencyNode = clipBlendNodeManager()->lookupNode(id: dependencyId); |
106 | ClipResults blendDataElement = dependencyNode->clipResults(animatorId); |
107 | blendData.push_back(t: blendDataElement); |
108 | } |
109 | |
110 | // Ask the blend node to perform the actual blend operation on the data |
111 | // from the dependencies |
112 | ClipResults blendedResults = doBlend(blendData); |
113 | setClipResults(animatorId, clipResults: blendedResults); |
114 | } |
115 | |
116 | } // Animation |
117 | |
118 | } // Qt3DAnimation |
119 | |
120 | QT_END_NAMESPACE |
121 | |