1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the Qt3D module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL3$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see http://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at http://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPLv3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or later as published by the Free |
28 | ** Software Foundation and appearing in the file LICENSE.GPL included in |
29 | ** the packaging of this file. Please review the following information to |
30 | ** ensure the GNU General Public License version 2.0 requirements will be |
31 | ** met: http://www.gnu.org/licenses/gpl-2.0.html. |
32 | ** |
33 | ** $QT_END_LICENSE$ |
34 | ** |
35 | ****************************************************************************/ |
36 | |
37 | #include "clipblendnode_p.h" |
38 | #include <Qt3DAnimation/qclipblendnodecreatedchange.h> |
39 | #include <Qt3DAnimation/qabstractanimationclip.h> |
40 | |
41 | QT_BEGIN_NAMESPACE |
42 | |
43 | namespace Qt3DAnimation { |
44 | |
45 | namespace Animation { |
46 | |
47 | ClipBlendNode::ClipBlendNode(BlendType blendType) |
48 | : BackendNode(ReadOnly) // Makes sense for now at least |
49 | , m_manager(nullptr) |
50 | , m_blendType(blendType) |
51 | { |
52 | } |
53 | |
54 | ClipBlendNode::~ClipBlendNode() |
55 | { |
56 | } |
57 | |
58 | void ClipBlendNode::setClipBlendNodeManager(ClipBlendNodeManager *manager) |
59 | { |
60 | m_manager = manager; |
61 | } |
62 | |
63 | void ClipBlendNode::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change) |
64 | { |
65 | Q_UNUSED(change); |
66 | } |
67 | |
68 | ClipBlendNode::BlendType Animation::ClipBlendNode::blendType() const |
69 | { |
70 | return m_blendType; |
71 | } |
72 | |
73 | void ClipBlendNode::setClipResults(Qt3DCore::QNodeId animatorId, const ClipResults &clipResults) |
74 | { |
75 | // Do we already have an entry for this animator? |
76 | const int animatorIndex = m_animatorIds.indexOf(t: animatorId); |
77 | if (animatorIndex == -1) { |
78 | // Nope, add it |
79 | m_animatorIds.push_back(t: animatorId); |
80 | m_clipResults.push_back(t: clipResults); |
81 | } else { |
82 | m_clipResults[animatorIndex] = clipResults; |
83 | } |
84 | } |
85 | |
86 | ClipResults ClipBlendNode::clipResults(Qt3DCore::QNodeId animatorId) const |
87 | { |
88 | const int animatorIndex = m_animatorIds.indexOf(t: animatorId); |
89 | if (animatorIndex != -1) |
90 | return m_clipResults[animatorIndex]; |
91 | return ClipResults(); |
92 | } |
93 | |
94 | /* |
95 | \fn QVector<Qt3DCore::QNodeId> ClipBlendNode::currentDependencyIds() const |
96 | \internal |
97 | |
98 | Each subclass of ClipBlendNode must implement this function such that it |
99 | returns a vector of the ids of ClipBlendNodes upon which is it dependent |
100 | in order to be able to evaluate given its current internal state. |
101 | |
102 | For example, a subclass implementing a simple lerp blend between two |
103 | other nodes, would always return the ids of the nodes between which it |
104 | is lerping. |
105 | |
106 | A more generalised lerp node that is capable of lerping between a |
107 | series of nodes would return the ids of the two nodes that correspond |
108 | to the blend values which sandwich the currently set blend value. |
109 | |
110 | The animation handler will submit a job that uses this function to |
111 | build a list of clips that must be evaluated in order to later |
112 | evaluate the entire blend tree. In this way, the clips can all be |
113 | evaluated in one pass, and the tree in a subsequent pass. |
114 | */ |
115 | |
116 | /* |
117 | \fn QVector<Qt3DCore::QNodeId> ClipBlendNode::allDependencyIds() const |
118 | \internal |
119 | |
120 | Similar to currentDependencyIds() but returns the ids of all potential |
121 | dependency nodes, not just those that are dependencies given the current |
122 | internal state. For example a generalised lerp node would return the ids |
123 | of all nodes that can participate in the lerp for any value of the blend |
124 | parameter. Not just those bounding the current blend value. |
125 | */ |
126 | |
127 | /* |
128 | \internal |
129 | |
130 | Fetches the ClipResults from the nodes listed in the dependencyIds |
131 | and passes them to the doBlend() virtual function which should be |
132 | implemented in subclasses to perform the actual blend operation. |
133 | The results are then inserted into the clip results for this blend |
134 | node indexed by the \a animatorId. |
135 | */ |
136 | void ClipBlendNode::blend(Qt3DCore::QNodeId animatorId) |
137 | { |
138 | // Obtain the clip results from each of the dependencies |
139 | const QVector<Qt3DCore::QNodeId> dependencyNodeIds = currentDependencyIds(); |
140 | const int dependencyCount = dependencyNodeIds.size(); |
141 | QVector<ClipResults> blendData; |
142 | blendData.reserve(asize: dependencyCount); |
143 | for (const auto dependencyId : dependencyNodeIds) { |
144 | ClipBlendNode *dependencyNode = clipBlendNodeManager()->lookupNode(id: dependencyId); |
145 | ClipResults blendDataElement = dependencyNode->clipResults(animatorId); |
146 | blendData.push_back(t: blendDataElement); |
147 | } |
148 | |
149 | // Ask the blend node to perform the actual blend operation on the data |
150 | // from the dependencies |
151 | ClipResults blendedResults = doBlend(blendData); |
152 | setClipResults(animatorId, clipResults: blendedResults); |
153 | } |
154 | |
155 | } // Animation |
156 | |
157 | } // Qt3DAnimation |
158 | |
159 | QT_END_NAMESPACE |
160 | |