Overte C++ Documentation
EntityTreeRenderer.h
1 //
2 // EntityTreeRenderer.h
3 // interface/src
4 //
5 // Created by Brad Hefta-Gaub on 12/6/13.
6 // Copyright 2013 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_EntityTreeRenderer_h
15 #define hifi_EntityTreeRenderer_h
16 
17 #include <memory>
18 
19 #include <QtCore/QSet>
20 #include <QtCore/QStack>
21 #include <QtGui/QMouseEvent>
22 #include <QtCore/QSharedPointer>
23 
24 #include <AudioInjectorManager.h>
25 #include <EntityScriptingInterface.h> // for RayToEntityIntersectionResult
26 #include <EntityTree.h>
27 #include <PointerEvent.h>
28 #include <ScriptCache.h>
29 #include <TextureCache.h>
30 #include <OctreeProcessor.h>
31 #include <render/Forward.h>
32 #include <workload/Space.h>
33 
36 class Model;
37 class ScriptEngine;
38 class ZoneEntityItem;
39 class EntityItem;
40 class ScriptEngine;
41 class ScriptManager;
42 using ScriptEnginePointer = std::shared_ptr<ScriptEngine>;
43 using ScriptManagerPointer = std::shared_ptr<ScriptManager>;
44 
45 namespace render { namespace entities {
46  class EntityRenderer;
47  using EntityRendererPointer = std::shared_ptr<EntityRenderer>;
48  using EntityRendererWeakPointer = std::weak_ptr<EntityRenderer>;
49 
50 } }
51 
52 using EntityRenderer = render::entities::EntityRenderer;
53 using EntityRendererPointer = render::entities::EntityRendererPointer;
54 using EntityRendererWeakPointer = render::entities::EntityRendererWeakPointer;
55 class Model;
56 using ModelPointer = std::shared_ptr<Model>;
57 using ModelWeakPointer = std::weak_ptr<Model>;
58 
59 using CalculateEntityLoadingPriority = std::function<float(const EntityItem& item)>;
60 
61 // Generic client side Octree renderer class.
62 class EntityTreeRenderer : public OctreeProcessor, public Dependency {
63  Q_OBJECT
64 public:
65  static void setEntitiesShouldFadeFunction(std::function<bool()> func) { _entitiesShouldFadeFunction = func; }
66  static std::function<bool()> getEntitiesShouldFadeFunction() { return _entitiesShouldFadeFunction; }
67 
68  EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
69  AbstractScriptingServicesInterface* scriptingServices);
70  virtual ~EntityTreeRenderer();
71 
72  QSharedPointer<EntityTreeRenderer> getSharedFromThis() {
73  return qSharedPointerCast<EntityTreeRenderer>(sharedFromThis());
74  }
75 
76  virtual char getMyNodeType() const override { return NodeType::EntityServer; }
77  virtual PacketType getMyQueryMessageType() const override { return PacketType::EntityQuery; }
78  virtual PacketType getExpectedPacketType() const override { return PacketType::EntityData; }
79 
80  // Returns the priority at which an entity should be loaded. Higher values indicate higher priority.
81  static CalculateEntityLoadingPriority getEntityLoadingPriorityOperator() { return _calculateEntityLoadingPriorityFunc; }
82  static float getEntityLoadingPriority(const EntityItem& item) { return _calculateEntityLoadingPriorityFunc(item); }
83  static void setEntityLoadingPriorityFunction(CalculateEntityLoadingPriority fn) { _calculateEntityLoadingPriorityFunc = fn; }
84 
85  void setMouseRayPickID(unsigned int rayPickID) { _mouseRayPickID = rayPickID; }
86  unsigned int getMouseRayPickID() { return _mouseRayPickID; }
87  void setMouseRayPickResultOperator(std::function<RayToEntityIntersectionResult(unsigned int)> getPrevRayPickResultOperator) { _getPrevRayPickResultOperator = getPrevRayPickResultOperator; }
88  void setSetPrecisionPickingOperator(std::function<void(unsigned int, bool)> setPrecisionPickingOperator) { _setPrecisionPickingOperator = setPrecisionPickingOperator; }
89 
90  void shutdown();
91  void preUpdate();
92  void update(bool simulate);
93 
94  EntityTreePointer getTree() { return std::static_pointer_cast<EntityTree>(_tree); }
95 
96  void processEraseMessage(ReceivedMessage& message, const SharedNodePointer& sourceNode);
97 
98  virtual void init() override;
99 
101  virtual void clearDomainAndNonOwnedEntities() override;
102  virtual void clear() override;
103 
105  void reloadEntityScripts();
106 
107  void fadeOutRenderable(const EntityRendererPointer& renderable);
108 
109  // event handles which may generate entity related events
110  QUuid mousePressEvent(QMouseEvent* event);
111  void mouseReleaseEvent(QMouseEvent* event);
112  void mouseDoublePressEvent(QMouseEvent* event);
113  void mouseMoveEvent(QMouseEvent* event);
114 
117  void connectSignalsToSlots(EntityScriptingInterface* entityScriptingInterface);
118 
119  // For Scene.shouldRenderEntities
120  QList<EntityItemID>& getEntitiesLastInScene() { return _entityIDsLastInScene; }
121 
122  std::pair<bool, bool> getZoneInteractionProperties();
123 
124  bool wantsKeyboardFocus(const EntityItemID& id) const;
125  QObject* getEventHandler(const EntityItemID& id);
126  bool wantsHandControllerPointerEvents(const EntityItemID& id) const;
127  void setProxyWindow(const EntityItemID& id, QWindow* proxyWindow);
128  void setCollisionSound(const EntityItemID& id, const SharedSoundPointer& sound);
129  EntityItemPointer getEntity(const EntityItemID& id);
130  void deleteEntity(const EntityItemID& id) const;
131  void onEntityChanged(const EntityItemID& id);
132 
133  // Access the workload Space
134  workload::SpacePointer getWorkloadSpace() const { return _space; }
135 
136  EntityEditPacketSender* getPacketSender();
137 
138  static void setAddMaterialToEntityOperator(std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> addMaterialToEntityOperator) { _addMaterialToEntityOperator = addMaterialToEntityOperator; }
139  static void setRemoveMaterialFromEntityOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> removeMaterialFromEntityOperator) { _removeMaterialFromEntityOperator = removeMaterialFromEntityOperator; }
140  static bool addMaterialToEntity(const QUuid& entityID, graphics::MaterialLayer material, const std::string& parentMaterialName);
141  static bool removeMaterialFromEntity(const QUuid& entityID, graphics::MaterialPointer material, const std::string& parentMaterialName);
142 
143  static void setAddMaterialToAvatarOperator(std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> addMaterialToAvatarOperator) { _addMaterialToAvatarOperator = addMaterialToAvatarOperator; }
144  static void setRemoveMaterialFromAvatarOperator(std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> removeMaterialFromAvatarOperator) { _removeMaterialFromAvatarOperator = removeMaterialFromAvatarOperator; }
145  static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialLayer material, const std::string& parentMaterialName);
146  static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const std::string& parentMaterialName);
147 
148  size_t getPrevNumEntityUpdates() const { return _prevNumEntityUpdates; }
149  size_t getPrevTotalNeededEntityUpdates() const { return _prevTotalNeededEntityUpdates; }
150 
151 signals:
152  void enterEntity(const EntityItemID& entityItemID);
153  void leaveEntity(const EntityItemID& entityItemID);
154  void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
155 
156 public slots:
157  void addingEntity(const EntityItemID& entityID);
158  void deletingEntity(const EntityItemID& entityID);
159  void entityScriptChanging(const EntityItemID& entityID, const bool reload);
160  void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
161  void updateEntityRenderStatus(bool shouldRenderEntities);
162  void updateZone(const EntityItemID& id);
163 
164  // optional slots that can be wired to menu items
165  void setDisplayModelBounds(bool value) { _displayModelBounds = value; }
166  void setPrecisionPicking(bool value) { _setPrecisionPickingOperator(_mouseRayPickID, value); }
167  EntityRendererPointer renderableForEntityId(const EntityItemID& id) const;
168  render::ItemID renderableIdForEntityId(const EntityItemID& id) const;
169 
170  void handleSpaceUpdate(std::pair<int32_t, glm::vec4> proxyUpdate);
171 
172 protected:
173  virtual OctreePointer createTree() override {
174  EntityTreePointer newTree = std::make_shared<EntityTree>(true);
175  newTree->createRootElement();
176  return newTree;
177  }
178 
179 private:
180  void addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction);
181  void updateChangedEntities(const render::ScenePointer& scene, render::Transaction& transaction);
182  EntityRendererPointer renderableForEntity(const EntityItemPointer& entity) const { return renderableForEntityId(entity->getID()); }
183  render::ItemID renderableIdForEntity(const EntityItemPointer& entity) const { return renderableIdForEntityId(entity->getID()); }
184 
185  void resetPersistentEntitiesScriptEngine();
186  void resetNonPersistentEntitiesScriptEngine();
187  void setupEntityScriptEngineSignals(const ScriptManagerPointer& scriptManager);
188 
189  void findBestZoneAndMaybeContainingEntities(QSet<EntityItemID>& entitiesContainingAvatar);
190 
191  bool applyLayeredZones();
192  void stopDomainAndNonOwnedEntities();
193 
194  void checkAndCallPreload(const EntityItemID& entityID, bool reload = false, bool unloadFirst = false);
195 
196  EntityItemID _currentHoverOverEntityID;
197  EntityItemID _currentClickingOnEntityID;
198 
199  ScriptValueList createEntityArgs(const EntityItemID& entityID);
200  void checkEnterLeaveEntities();
201  void leaveDomainAndNonOwnedEntities();
202  void leaveAllEntities();
203  void forceRecheckEntities();
204 
205  glm::vec3 _avatarPosition { 0.0f };
206  bool _forceRecheckEntities { true };
207  QSet<EntityItemID> _currentEntitiesInside;
208 
209  bool _wantScripts;
210  ScriptManagerPointer _nonPersistentEntitiesScriptManager; // used for domain + non-owned avatar entities, cleared on domain switch
211  ScriptManagerPointer _persistentEntitiesScriptManager; // used for local + owned avatar entities, persists on domain switch, cleared on reload content
212 
213  void playEntityCollisionSound(const EntityItemPointer& entity, const Collision& collision);
214 
215  bool _lastPointerEventValid;
216  PointerEvent _lastPointerEvent;
217  AbstractViewStateInterface* _viewState;
218  AbstractScriptingServicesInterface* _scriptingServices;
219  bool _displayModelBounds;
220 
221  bool _shuttingDown { false };
222 
223  QMultiMap<QUrl, EntityItemID> _waitingOnPreload;
224 
225  unsigned int _mouseRayPickID;
226  std::function<RayToEntityIntersectionResult(unsigned int)> _getPrevRayPickResultOperator;
227  std::function<void(unsigned int, bool)> _setPrecisionPickingOperator;
228 
229  class LayeredZone {
230  public:
231  LayeredZone(std::shared_ptr<ZoneEntityItem> zone) : zone(zone), id(zone->getID()), volume(zone->getVolumeEstimate()) {}
232 
233  // We need to sort on volume AND id so that different clients sort zones with identical volumes the same way
234  bool operator<(const LayeredZone& r) const { return volume < r.volume || (volume == r.volume && id < r.id); }
235  bool operator==(const LayeredZone& r) const { return zone.lock() && zone.lock() == r.zone.lock(); }
236  bool operator!=(const LayeredZone& r) const { return !(*this == r); }
237  bool operator<=(const LayeredZone& r) const { return (*this < r) || (*this == r); }
238 
239  std::weak_ptr<ZoneEntityItem> zone;
240  QUuid id;
241  float volume;
242  };
243 
244  class LayeredZones : public std::vector<LayeredZone> {
245  public:
246  bool clearDomainAndNonOwnedZones();
247 
248  void sort() { std::sort(begin(), end(), std::less<LayeredZone>()); }
249  bool equals(const LayeredZones& other) const;
250  bool update(std::shared_ptr<ZoneEntityItem> zone, const glm::vec3& position, EntityTreeRenderer* entityTreeRenderer);
251 
252  void appendRenderIDs(render::ItemIDs& list, EntityTreeRenderer* entityTreeRenderer) const;
253  std::pair<bool, bool> getZoneInteractionProperties() const;
254  };
255 
256  LayeredZones _layeredZones;
257  uint64_t _lastZoneCheck { 0 };
258  const uint64_t ZONE_CHECK_INTERVAL = USECS_PER_MSEC * 100; // ~10hz
259  const float ZONE_CHECK_DISTANCE = 0.001f;
260 
261  float _avgRenderableUpdateCost { 0.0f };
262 
263  ReadWriteLockable _changedEntitiesGuard;
264  std::unordered_set<EntityItemID> _changedEntities;
265  size_t _prevNumEntityUpdates { 0 };
266  size_t _prevTotalNeededEntityUpdates { 0 };
267 
268  std::unordered_set<EntityRendererPointer> _renderablesToUpdate;
269  std::unordered_map<EntityItemID, EntityRendererPointer> _entitiesInScene;
270  std::unordered_map<EntityItemID, EntityItemWeakPointer> _entitiesToAdd;
271 
272  // For Scene.shouldRenderEntities
273  QList<EntityItemID> _entityIDsLastInScene;
274 
275  static int _entitiesScriptEngineCount;
276  static CalculateEntityLoadingPriority _calculateEntityLoadingPriorityFunc;
277  static std::function<bool()> _entitiesShouldFadeFunction;
278 
279  mutable std::mutex _spaceLock;
280  workload::SpacePointer _space{ new workload::Space() };
281  workload::Transaction::Updates _spaceUpdates;
282 
283  static std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> _addMaterialToEntityOperator;
284  static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromEntityOperator;
285  static std::function<bool(const QUuid&, graphics::MaterialLayer, const std::string&)> _addMaterialToAvatarOperator;
286  static std::function<bool(const QUuid&, graphics::MaterialPointer, const std::string&)> _removeMaterialFromAvatarOperator;
287 
288 };
289 
290 
291 #endif // hifi_EntityTreeRenderer_h
Interface provided by Application to other objects that need access to scripting services of the appl...
Definition: AbstractScriptingServicesInterface.h:26
Interface provided by Application to other objects that need access to the current view state details...
Definition: AbstractViewStateInterface.h:31
Utility for processing, packing, queueing and sending of outbound edit voxel messages.
Definition: EntityEditPacketSender.h:25
Definition: EntityItem.h:82
Abstract ID for editing model items. Used in EntityItem JS API.
Definition: EntityItemID.h:28
A generic 3D model displaying geometry loaded from a URL.
Definition: Model.h:84
Represents a 2D or 3D pointer to the scripting engine. Exposed as PointerEvent
Definition: PointerEvent.h:30
Provides an engine-independent interface for a scripting engine.
Definition: ScriptEngine.h:93
Manages a single scripting engine.
Definition: ScriptManager.h:281