Overte C++ Documentation
Pick.h
1 //
2 // Created by Sam Gondelman 10/17/2017
3 // Copyright 2017 High Fidelity, Inc.
4 //
5 // Distributed under the Apache License, Version 2.0.
6 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
7 //
8 #ifndef hifi_Pick_h
9 #define hifi_Pick_h
10 
11 #include <memory>
12 #include <stdint.h>
13 #include <bitset>
14 
15 #include <QtCore/QUuid>
16 #include <QVector>
17 #include <QVariant>
18 
19 #include <shared/ReadWriteLockable.h>
20 #include <TransformNode.h>
21 #include <PickFilter.h>
22 
23 /*@jsdoc
24  * <p>The type of an intersection.</p>
25  * <table>
26  * <thead>
27  * <tr><th>Name</th><th>Value</th><th>Description</th></tr>
28  * </thead>
29  * <tbody>
30  * <tr><td>INTERSECTED_NONE</td><td><code>0</code></td><td>Intersected nothing.</td></tr>
31  * <tr><td>INTERSECTED_ENTITY</td><td><code>1</code></td><td>Intersected an entity.</td></tr>
32  * <tr><td>INTERSECTED_LOCAL_ENTITY</td><td><code>2</code></td><td>Intersected a local entity.</td></tr>
33  * <tr><td>INTERSECTED_AVATAR</td><td><code>3</code></td><td>Intersected an avatar.</td></tr>
34  * <tr><td>INTERSECTED_HUD</td><td><code>4</code></td><td>Intersected the HUD surface.</td></tr>
35  * </tbody>
36  * </table>
37  * @typedef {number} IntersectionType
38  */
39 enum IntersectionType {
40  NONE = 0,
41  ENTITY,
42  LOCAL_ENTITY,
43  AVATAR,
44  HUD
45 };
46 
47 class PickResult {
48 public:
49  PickResult() {}
50  PickResult(const QVariantMap& pickVariant) : pickVariant(pickVariant) {}
51  virtual ~PickResult() = default;
52 
53  virtual QVariantMap toVariantMap() const {
54  return pickVariant;
55  }
56 
57  virtual bool doesIntersect() const = 0;
58 
59  // for example: if we want the closest result, compare based on distance
60  // if we want all results, combine them
61  // must return a new pointer
62  virtual std::shared_ptr<PickResult> compareAndProcessNewResult(const std::shared_ptr<PickResult>& newRes) = 0;
63 
64  // returns true if this result contains any valid results with distance < maxDistance
65  // can also filter out results with distance >= maxDistance
66  virtual bool checkOrFilterAgainstMaxDistance(float maxDistance) = 0;
67 
68  QVariantMap pickVariant;
69 };
70 
71 using PickResultPointer = std::shared_ptr<PickResult>;
72 
73 class PickQuery : protected ReadWriteLockable {
74  Q_GADGET
75 public:
76  PickQuery(const PickFilter& filter, const float maxDistance, const bool enabled);
77  virtual ~PickQuery() = default;
78 
79  /*@jsdoc
80  * The <code>PickType</code> API provides constant numeric values that represent different types of picks.
81  *
82  * @namespace PickType
83  * @variation 0
84  *
85  * @hifi-interface
86  * @hifi-client-entity
87  * @hifi-avatar
88  *
89  * @property {number} Ray - Ray picks intersect a ray with objects in front of them, along their direction.
90  * @property {number} Parabola - Parabola picks intersect a parabola with objects in front of them, along their arc.
91  * @property {number} Stylus - Stylus picks provide "tapping" functionality on or into flat surfaces.
92  * @property {number} Collision - Collision picks intersect a collision volume with avatars and entities that have
93  * collisions.
94  */
95 
96  /*@jsdoc
97  * <p>A type of pick.</p>
98  * <table>
99  * <thead>
100  * <tr><th>Value</th><th>Description</th></tr>
101  * </thead>
102  * <tbody>
103  * <tr><td><code>{@link PickType(0)|PickType.Ray}</code></td><td>Ray picks intersect a ray with objects in front of
104  * them, along their direction.</td></tr>
105  * <tr><td><code>{@link PickType(0)|PickType.Parabola}</code></td><td>Parabola picks intersect a parabola with objects
106  * in front of them, along their arc.</td></tr>
107  * <tr><td><code>{@link PickType(0)|PickType.Stylus}</code></td><td>Stylus picks provide "tapping" functionality on or
108  * into flat surfaces.</td></tr>
109  * <tr><td><code>{@link PickType(0)|PickType.Collision}</code></td><td>Collision picks intersect a collision volume
110  * with avatars and entities that have collisions.</td></tr>
111  * </tbody>
112  * </table>
113  * @typedef {number} PickType
114  */
115  enum PickType {
116  Ray = 0,
117  Stylus,
118  Parabola,
119  Collision,
120  NUM_PICK_TYPES,
121  INVALID_PICK_TYPE = -1
122  };
123  Q_ENUM(PickType)
124 
125  enum JointState {
126  JOINT_STATE_NONE = 0,
127  JOINT_STATE_LEFT_HAND,
128  JOINT_STATE_RIGHT_HAND,
129  JOINT_STATE_MOUSE
130  };
131 
132  void enable(bool enabled = true);
133  void disable() { enable(false); }
134 
135  PickFilter getFilter() const;
136  float getMaxDistance() const;
137  bool isEnabled() const;
138  virtual PickType getType() const = 0;
139 
140  void setPrecisionPicking(bool precisionPicking);
141 
142  PickResultPointer getPrevPickResult() const;
143  void setPickResult(const PickResultPointer& pickResult);
144 
145  QVector<QUuid> getIgnoreItems() const;
146  QVector<QUuid> getIncludeItems() const;
147 
148  template <typename S>
149  QVector<S> getIgnoreItemsAs() const {
150  QVector<S> result;
151  withReadLock([&] {
152  for (const auto& uid : _ignoreItems) {
153  result.push_back(uid);
154  }
155  });
156  return result;
157  }
158 
159  template <typename S>
160  QVector<S> getIncludeItemsAs() const {
161  QVector<S> result;
162  withReadLock([&] {
163  for (const auto& uid : _includeItems) {
164  result.push_back(uid);
165  }
166  });
167  return result;
168  }
169 
170  void setIgnoreItems(const QVector<QUuid>& items);
171  void setIncludeItems(const QVector<QUuid>& items);
172 
173  virtual QVariantMap toVariantMap() const {
174  QVariantMap properties;
175 
176  properties["pickType"] = (int)getType();
177  properties["enabled"] = isEnabled();
178  properties["filter"] = (unsigned int)getFilter()._flags.to_ulong();
179  properties["maxDistance"] = getMaxDistance();
180 
181  if (parentTransform) {
182  auto transformNodeProperties = parentTransform->toVariantMap();
183  for (auto it = transformNodeProperties.cbegin(); it != transformNodeProperties.cend(); ++it) {
184  properties[it.key()] = it.value();
185  }
186  }
187 
188  return properties;
189  }
190 
191  void setScriptParameters(const QVariantMap& parameters);
192  QVariantMap getScriptParameters() const;
193 
194  virtual bool isLeftHand() const { return _jointState == JOINT_STATE_LEFT_HAND; }
195  virtual bool isRightHand() const { return _jointState == JOINT_STATE_RIGHT_HAND; }
196  virtual bool isMouse() const { return _jointState == JOINT_STATE_MOUSE; }
197 
198  void setJointState(JointState jointState) { _jointState = jointState; }
199 
200  virtual Transform getResultTransform() const = 0;
201 
202  std::shared_ptr<TransformNode> parentTransform;
203 
204 private:
205  PickFilter _filter;
206  const float _maxDistance;
207  bool _enabled;
208  PickResultPointer _prevResult;
209 
210  QVector<QUuid> _ignoreItems;
211  QVector<QUuid> _includeItems;
212 
213  // The parameters used to create this pick when created through a script
214  QVariantMap _scriptParameters;
215 
216  JointState _jointState { JOINT_STATE_NONE };
217 };
218 Q_DECLARE_METATYPE(PickQuery::PickType)
219 
220 template<typename T>
221 class Pick : public PickQuery {
222 public:
223  Pick(const T& mathPick, const PickFilter& filter, const float maxDistance, const bool enabled) : PickQuery(filter, maxDistance, enabled), _mathPick(mathPick) {}
224 
225  virtual T getMathematicalPick() const = 0;
226  virtual PickResultPointer getDefaultResult(const QVariantMap& pickVariant) const = 0;
227  virtual PickResultPointer getEntityIntersection(const T& pick) = 0;
228  virtual PickResultPointer getAvatarIntersection(const T& pick) = 0;
229  virtual PickResultPointer getHUDIntersection(const T& pick) = 0;
230 
231  QVariantMap toVariantMap() const override {
232  QVariantMap properties = PickQuery::toVariantMap();
233 
234  const QVariantMap mathPickProperties = _mathPick.toVariantMap();
235  for (auto it = mathPickProperties.cbegin(); it != mathPickProperties.cend(); ++it) {
236  properties[it.key()] = it.value();
237  }
238 
239  return properties;
240  }
241 
242 protected:
243  T _mathPick;
244 };
245 
246 namespace std {
247  template <>
248  struct hash<PickQuery::PickType> {
249  size_t operator()(const PickQuery::PickType& a) const {
250  return a;
251  }
252  };
253 }
254 
255 #endif // hifi_Pick_h