Overte C++ Documentation
AvatarManager.h
1 //
2 // AvatarManager.h
3 // interface/src/avatar
4 //
5 // Created by Stephen Birarda on 1/23/2014.
6 // Copyright 2014 High Fidelity, Inc.
7 // Copyright 2023 Overte e.V.
8 //
9 // Distributed under the Apache License, Version 2.0.
10 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
11 // SPDX-License-Identifier: Apache-2.0
12 //
13 
14 #ifndef hifi_AvatarManager_h
15 #define hifi_AvatarManager_h
16 
17 #include <set>
18 
19 #include <QtCore/QHash>
20 #include <QtCore/QObject>
21 
22 #include <AvatarHashMap.h>
23 #include <PhysicsEngine.h>
24 #include <PIDController.h>
25 #include <SimpleMovingAverage.h>
26 #include <shared/RateCounter.h>
27 #include <avatars-renderer/ScriptAvatar.h>
28 #include <AudioInjectorManager.h>
29 #include <workload/Space.h>
30 #include <EntitySimulation.h> // for SetOfEntities
31 #include <ScriptValue.h>
32 
33 #include "AvatarMotionState.h"
34 #include "DetailedMotionState.h"
35 #include "MyAvatar.h"
36 #include "OtherAvatar.h"
37 
38 class ScriptEngine;
39 using SortedAvatar = std::pair<float, std::shared_ptr<Avatar>>;
40 
41 /*@jsdoc
42  * The <code>AvatarManager</code> API provides information about avatars within the current domain. The avatars available are
43  * those that Interface has displayed and therefore knows about.
44  *
45  * <p><strong>Warning:</strong> This API is also provided to Interface, client entity, and avatar scripts as the synonym,
46  * "<code>AvatarList</code>". For assignment client scripts, see the separate {@link AvatarList} API.</p>
47  *
48  * @namespace AvatarManager
49  *
50  * @hifi-interface
51  * @hifi-client-entity
52  * @hifi-avatar
53  *
54  * @borrows AvatarList.getAvatar as getAvatar
55  * @comment AvatarList.getAvatarIdentifiers as getAvatarIdentifiers - Don't borrow because behavior is slightly different.
56  * @comment AvatarList.getAvatarsInRange as getAvatarsInRange - Don't borrow because behavior is slightly different.
57  * @borrows AvatarList.avatarAddedEvent as avatarAddedEvent
58  * @borrows AvatarList.avatarRemovedEvent as avatarRemovedEvent
59  * @borrows AvatarList.avatarSessionChangedEvent as avatarSessionChangedEvent
60  * @borrows AvatarList.isAvatarInRange as isAvatarInRange
61  * @borrows AvatarList.sessionUUIDChanged as sessionUUIDChanged
62  * @borrows AvatarList.processAvatarDataPacket as processAvatarDataPacket
63  * @borrows AvatarList.processAvatarIdentityPacket as processAvatarIdentityPacket
64  * @borrows AvatarList.processBulkAvatarTraits as processBulkAvatarTraits
65  * @borrows AvatarList.processKillAvatar as processKillAvatar
66  */
67 
68 class AvatarManager : public AvatarHashMap {
69  Q_OBJECT
70  SINGLETON_DEPENDENCY
71 
72 public:
73 
74  /*@jsdoc
75  * Gets the IDs of all avatars known about in the domain.
76  * Your own avatar is included in the list as a <code>null</code> value.
77  * @function AvatarManager.getAvatarIdentifiers
78  * @returns {Uuid[]} The IDs of all known avatars in the domain.
79  * @example <caption>Report the IDS of all avatars within the domain.</caption>
80  * var avatars = AvatarManager.getAvatarIdentifiers();
81  * print("Avatars in the domain: " + JSON.stringify(avatars));
82  * // A null item is included for your avatar.
83  */
84 
85  /*@jsdoc
86  * Gets the IDs of all avatars known about within a specified distance from a point.
87  * Your own avatar's ID is included in the list if it is in range.
88  * @function AvatarManager.getAvatarsInRange
89  * @param {Vec3} position - The point about which the search is performed.
90  * @param {number} range - The search radius.
91  * @returns {Uuid[]} The IDs of all known avatars within the search distance from the position.
92  * @example <caption>Report the IDs of all avatars within 10m of your avatar.</caption>
93  * var RANGE = 10;
94  * var avatars = AvatarManager.getAvatarsInRange(MyAvatar.position, RANGE);
95  * print("Nearby avatars: " + JSON.stringify(avatars));
96  * print("Own avatar: " + MyAvatar.sessionUUID);
97  */
98 
100  static void registerMetaTypes(ScriptEngine* engine);
101 
102  virtual ~AvatarManager();
103 
104  void init();
105  void setSpace(workload::SpacePointer& space );
106 
107  std::shared_ptr<MyAvatar> getMyAvatar() { return _myAvatar; }
108  glm::vec3 getMyAvatarPosition() const { return _myAvatar->getWorldPosition(); }
109 
110  /*@jsdoc
111  * @comment Uses the base class's JSDoc.
112  */
113  // Null/Default-constructed QUuids will return MyAvatar
114  Q_INVOKABLE virtual ScriptAvatarData* getAvatar(QUuid avatarID) override { return new ScriptAvatar(getAvatarBySessionID(avatarID)); }
115 
116  AvatarSharedPointer getAvatarBySessionID(const QUuid& sessionID) const override;
117 
118  int getNumAvatarsUpdated() const { return _numAvatarsUpdated; }
119  int getNumAvatarsNotUpdated() const { return _numAvatarsNotUpdated; }
120  int getNumHeroAvatars() const { return _numHeroAvatars; }
121  int getNumHeroAvatarsUpdated() const { return _numHeroAvatarsUpdated; }
122  float getAvatarSimulationTime() const { return _avatarSimulationTime; }
123 
124  void updateMyAvatar(float deltaTime);
125  void updateOtherAvatars(float deltaTime);
126 
127  void setMyAvatarDataPacketsPaused(bool puase);
128 
129  void postUpdate(float deltaTime, const render::ScenePointer& scene);
130 
131  void clearOtherAvatars() override;
132  void deleteAllAvatars();
133 
134  void getObjectsToRemoveFromPhysics(VectorOfMotionStates& motionStates);
135  void getObjectsToAddToPhysics(VectorOfMotionStates& motionStates);
136  void getObjectsToChange(VectorOfMotionStates& motionStates);
137 
138  void handleChangedMotionStates(const VectorOfMotionStates& motionStates);
139  void handleCollisionEvents(const CollisionEvents& collisionEvents);
140 
141  /*@jsdoc
142  * Gets the amount of avatar mixer data being generated by an avatar other than your own.
143  * @function AvatarManager.getAvatarDataRate
144  * @param {Uuid} sessionID - The ID of the avatar whose data rate you're retrieving.
145  * @param {AvatarDataRate} [rateName=""] - The type of avatar mixer data to get the data rate of.
146  * @returns {number} The data rate in kbps; <code>0</code> if the avatar is your own.
147  */
148  Q_INVOKABLE float getAvatarDataRate(const QUuid& sessionID, const QString& rateName = QString("")) const;
149 
150  /*@jsdoc
151  * Gets the update rate of avatar mixer data being generated by an avatar other than your own.
152  * @function AvatarManager.getAvatarUpdateRate
153  * @param {Uuid} sessionID - The ID of the avatar whose update rate you're retrieving.
154  * @param {AvatarUpdateRate} [rateName=""] - The type of avatar mixer data to get the update rate of.
155  * @returns {number} The update rate in Hz; <code>0</code> if the avatar is your own.
156  */
157  Q_INVOKABLE float getAvatarUpdateRate(const QUuid& sessionID, const QString& rateName = QString("")) const;
158 
159  /*@jsdoc
160  * Gets the simulation rate of an avatar other than your own.
161  * @function AvatarManager.getAvatarSimulationRate
162  * @param {Uuid} sessionID - The ID of the avatar whose simulation you're retrieving.
163  * @param {AvatarSimulationRate} [rateName=""] - The type of avatar data to get the simulation rate of.
164  * @returns {number} The simulation rate in Hz; <code>0</code> if the avatar is your own.
165  */
166  Q_INVOKABLE float getAvatarSimulationRate(const QUuid& sessionID, const QString& rateName = QString("")) const;
167 
168  /*@jsdoc
169  * Find the first avatar intersected by a {@link PickRay}.
170  * @function AvatarManager.findRayIntersection
171  * @param {PickRay} ray - The ray to use for finding avatars.
172  * @param {Uuid[]} [avatarsToInclude=[]] - If not empty then search is restricted to these avatars.
173  * @param {Uuid[]} [avatarsToDiscard=[]] - Avatars to ignore in the search.
174  * @param {boolean} [pickAgainstMesh=true] - If <code>true</code> then the exact intersection with the avatar mesh is
175  * calculated, if <code>false</code> then the intersection is approximate.
176  * @returns {RayToAvatarIntersectionResult} The result of the search for the first intersected avatar.
177  * @example <caption>Find the first avatar directly in front of you.</caption>
178  * var pickRay = {
179  * origin: MyAvatar.position,
180  * direction: Quat.getFront(MyAvatar.orientation)
181  * };
182  *
183  * var intersection = AvatarManager.findRayIntersection(pickRay);
184  * if (intersection.intersects) {
185  * print("Avatar found: " + JSON.stringify(intersection));
186  * } else {
187  * print("No avatar found.");
188  * }
189  */
190  Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersection(const PickRay& ray,
191  const ScriptValue& avatarIdsToInclude = ScriptValue(),
192  const ScriptValue& avatarIdsToDiscard = ScriptValue(),
193  bool pickAgainstMesh = true);
194  /*@jsdoc
195  * @function AvatarManager.findRayIntersectionVector
196  * @param {PickRay} ray - Ray.
197  * @param {Uuid[]} avatarsToInclude - Avatars to include.
198  * @param {Uuid[]} avatarsToDiscard - Avatars to discard.
199  * @param {boolean} pickAgainstMesh - Pick against mesh.
200  * @returns {RayToAvatarIntersectionResult} Intersection result.
201  * @deprecated This function is deprecated and will be removed.
202  */
203  Q_INVOKABLE RayToAvatarIntersectionResult findRayIntersectionVector(const PickRay& ray,
204  const QVector<EntityItemID>& avatarsToInclude,
205  const QVector<EntityItemID>& avatarsToDiscard,
206  bool pickAgainstMesh);
207 
208  /*@jsdoc
209  * @function AvatarManager.findParabolaIntersectionVector
210  * @param {PickParabola} pick - Pick.
211  * @param {Uuid[]} avatarsToInclude - Avatars to include.
212  * @param {Uuid[]} avatarsToDiscard - Avatars to discard.
213  * @returns {ParabolaToAvatarIntersectionResult} Intersection result.
214  * @deprecated This function is deprecated and will be removed.
215  */
216  Q_INVOKABLE ParabolaToAvatarIntersectionResult findParabolaIntersectionVector(const PickParabola& pick,
217  const QVector<EntityItemID>& avatarsToInclude,
218  const QVector<EntityItemID>& avatarsToDiscard);
219 
220  /*@jsdoc
221  * @function AvatarManager.getAvatarSortCoefficient
222  * @param {string} name - Name.
223  * @returns {number} Value.
224  * @deprecated This function is deprecated and will be removed.
225  */
226  // TODO: remove this HACK once we settle on optimal default sort coefficients
227  Q_INVOKABLE float getAvatarSortCoefficient(const QString& name);
228 
229  /*@jsdoc
230  * @function AvatarManager.setAvatarSortCoefficient
231  * @param {string} name - Name
232  * @param {number} value - Value.
233  * @deprecated This function is deprecated and will be removed.
234  */
235  Q_INVOKABLE void setAvatarSortCoefficient(const QString& name, const ScriptValue& value);
236 
237  /*@jsdoc
238  * Gets PAL (People Access List) data for one or more avatars. Using this method is faster than iterating over each avatar
239  * and obtaining data about each individually.
240  * @function AvatarManager.getPalData
241  * @param {string[]} [avatarIDs=[]] - The IDs of the avatars to get the PAL data for. If empty, then PAL data is obtained
242  * for all avatars.
243  * @returns {Object<"data", AvatarManager.PalData[]>} An array of objects, each object being the PAL data for an avatar.
244  * @example <caption>Report the PAL data for an avatar nearby.</caption>
245  * var palData = AvatarManager.getPalData();
246  * print("PAL data for one avatar: " + JSON.stringify(palData.data[0]));
247  */
248  Q_INVOKABLE QVariantMap getPalData(const QStringList& specificAvatarIdentifiers = QStringList());
249 
250  float getMyAvatarSendRate() const { return _myAvatarSendRate.rate(); }
251 
252  void queuePhysicsChange(const OtherAvatarPointer& avatar);
253  void buildPhysicsTransaction(PhysicsEngine::Transaction& transaction);
254  void handleProcessedPhysicsTransaction(PhysicsEngine::Transaction& transaction);
255  void removeDeadAvatarEntities(const SetOfEntities& deadEntities);
256 
257  void accumulateGrabPositions(std::map<QUuid, GrabLocationAccumulator>& grabAccumulators);
258 
259 public slots:
260  /*@jsdoc
261  * @function AvatarManager.updateAvatarRenderStatus
262  * @param {boolean} shouldRenderAvatars - Should render avatars.
263  * @deprecated This function is deprecated and will be removed.
264  */
265  void updateAvatarRenderStatus(bool shouldRenderAvatars);
266 
267  /*@jsdoc
268  * Displays other avatars skeletons debug graphics.
269  * @function AvatarManager.setEnableDebugDrawOtherSkeletons
270  * @param {boolean} enabled - <code>true</code> to show the debug graphics, <code>false</code> to hide.
271  */
272  void setEnableDebugDrawOtherSkeletons(bool isEnabled) {
273  _drawOtherAvatarSkeletons = isEnabled;
274  }
275 
276 protected:
277  AvatarSharedPointer addAvatar(const QUuid& sessionUUID, const QWeakPointer<Node>& mixerWeakPointer) override;
278  DetailedMotionState* createDetailedMotionState(OtherAvatarPointer avatar, int32_t jointIndex);
279  void rebuildAvatarPhysics(PhysicsEngine::Transaction& transaction, const OtherAvatarPointer& avatar);
280  void removeDetailedAvatarPhysics(PhysicsEngine::Transaction& transaction, const OtherAvatarPointer& avatar);
281  void rebuildDetailedAvatarPhysics(PhysicsEngine::Transaction& transaction, const OtherAvatarPointer& avatar);
282 
283 private:
284  explicit AvatarManager(QObject* parent = 0);
285  explicit AvatarManager(const AvatarManager& other);
286 
287  AvatarSharedPointer newSharedAvatar(const QUuid& sessionUUID) override;
288 
289  // called only from the AvatarHashMap thread - cannot be called while this thread holds the
290  // hash lock, since handleRemovedAvatar needs a write lock on the entity tree and the entity tree
291  // frequently grabs a read lock on the hash to get a given avatar by ID
292  void handleRemovedAvatar(const AvatarSharedPointer& removedAvatar,
293  KillAvatarReason removalReason = KillAvatarReason::NoReason) override;
294  void handleTransitAnimations(AvatarTransit::Status status);
295 
296  using SetOfOtherAvatars = std::set<OtherAvatarPointer>;
297  SetOfOtherAvatars _otherAvatarsToChangeInPhysics;
298 
299  std::shared_ptr<MyAvatar> _myAvatar;
300  quint64 _lastSendAvatarDataTime = 0; // Controls MyAvatar send data rate.
301 
302  std::list<QWeakPointer<AudioInjector>> _collisionInjectors;
303 
304  RateCounter<> _myAvatarSendRate;
305  int _numAvatarsUpdated { 0 };
306  int _numAvatarsNotUpdated { 0 };
307  int _numHeroAvatars{ 0 };
308  int _numHeroAvatarsUpdated{ 0 };
309  float _avatarSimulationTime { 0.0f };
310  bool _shouldRender { true };
311  bool _myAvatarDataPacketsPaused { false };
312 
313  mutable std::mutex _spaceLock;
314  workload::SpacePointer _space;
315 
316  AvatarTransit::TransitConfig _transitConfig;
317  bool _drawOtherAvatarSkeletons { false };
318 };
319 
320 #endif // hifi_AvatarManager_h
Provides an engine-independent interface for a scripting engine.
Definition: ScriptEngine.h:93
[ScriptInterface] Provides an engine-independent interface for QScriptValue
Definition: ScriptValue.h:40