Overte C++ Documentation
Scene.h
1 //
2 // Scene.h
3 // render/src/render
4 //
5 // Created by Sam Gateau on 1/11/15.
6 // Copyright 2014 High Fidelity, Inc.
7 // Copyright 2024 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 //
12 
13 #ifndef hifi_render_Scene_h
14 #define hifi_render_Scene_h
15 
16 #include "Item.h"
17 #include "SpatialTree.h"
18 #include "Stage.h"
19 #include "Selection.h"
20 #include "Transition.h"
21 #include "HighlightStyle.h"
22 
23 namespace render {
24 
25 class RenderEngine;
26 class Scene;
27 
28 // Transaction is the mechanism to make any change to the scene.
29 // Whenever a new item need to be reset,
30 // or when an item changes its position or its size
31 // or when an item's payload has to be be updated with new states (coming from outside the scene knowledge)
32 // or when an item is destroyed
33 // These changes must be expressed through the corresponding command from the Transaction
34 // THe Transaction is then queued on the Scene so all the pending transactions can be consolidated and processed at the time
35 // of updating the scene before it s rendered.
36 //
37 
38 
39 class Transaction {
40  friend class Scene;
41 public:
42 
43  typedef std::function<void(ItemID, const Transition*)> TransitionQueryFunc;
44  typedef std::function<void()> TransitionFinishedFunc;
45  typedef std::function<void(HighlightStyle const*)> SelectionHighlightQueryFunc;
46 
47  Transaction() {}
48  ~Transaction() {}
49 
50  // Item transactions
51  void resetItem(ItemID id, const PayloadPointer& payload);
52  void removeItem(ItemID id);
53  bool hasRemovedItems() const { return !_removedItems.empty(); }
54  template <class T> void updateItem(ItemID id, std::function<void(T&)> func) {
55  updateItem(id, std::make_shared<UpdateFunctor<T>>(func));
56  }
57  void updateItem(ItemID id, const UpdateFunctorPointer& functor);
58  void updateItem(ItemID id) { updateItem(id, nullptr); }
59 
60  // Transition (applied to an item) transactions
61  void resetTransitionOnItem(ItemID id, Transition::Type transition, ItemID boundId = render::Item::INVALID_ITEM_ID);
62  void removeTransitionFromItem(ItemID id);
63  void setTransitionFinishedOperator(ItemID id, TransitionFinishedFunc func);
64  void queryTransitionOnItem(ItemID id, TransitionQueryFunc func);
65 
66  // Selection transactions
67  void resetSelection(const Selection& selection);
68 
69  void resetSelectionHighlight(const std::string& selectionName, const HighlightStyle& style = HighlightStyle());
70  void removeHighlightFromSelection(const std::string& selectionName);
71  void querySelectionHighlight(const std::string& selectionName, const SelectionHighlightQueryFunc& func);
72 
73  void reserve(const std::vector<Transaction>& transactionContainer);
74  void merge(const std::vector<Transaction>& transactionContainer);
75  void merge(std::vector<Transaction>&& transactionContainer);
76  void merge(const Transaction& transaction);
77  void merge(Transaction&& transaction);
78  void clear();
79 
80 protected:
81 
82  using Reset = std::tuple<ItemID, PayloadPointer>;
83  using Remove = ItemID;
84  using Update = std::tuple<ItemID, UpdateFunctorPointer>;
85 
86  using TransitionReset = std::tuple<ItemID, Transition::Type, ItemID>;
87  using TransitionRemove = ItemID;
88  using TransitionFinishedOperator = std::tuple<ItemID, TransitionFinishedFunc>;
89  using TransitionQuery = std::tuple<ItemID, TransitionQueryFunc>;
90 
91  using SelectionReset = Selection;
92 
93  using HighlightReset = std::tuple<std::string, HighlightStyle>;
94  using HighlightRemove = std::string;
95  using HighlightQuery = std::tuple<std::string, SelectionHighlightQueryFunc>;
96 
97  using Resets = std::vector<Reset>;
98  using Removes = std::vector<Remove>;
99  using Updates = std::vector<Update>;
100 
101  using TransitionResets = std::vector<TransitionReset>;
102  using TransitionRemoves = std::vector<TransitionRemove>;
103  using TransitionFinishedOperators = std::vector<TransitionFinishedOperator>;
104  using TransitionQueries = std::vector<TransitionQuery>;
105 
106  using SelectionResets = std::vector<SelectionReset>;
107 
108  using HighlightResets = std::vector<HighlightReset>;
109  using HighlightRemoves = std::vector<HighlightRemove>;
110  using HighlightQueries = std::vector<HighlightQuery>;
111 
112  Resets _resetItems;
113  Removes _removedItems;
114  Updates _updatedItems;
115 
116  TransitionResets _resetTransitions;
117  TransitionRemoves _removeTransitions;
118  TransitionFinishedOperators _transitionFinishedOperators;
119  TransitionQueries _queriedTransitions;
120 
121  SelectionResets _resetSelections;
122 
123  HighlightResets _highlightResets;
124  HighlightRemoves _highlightRemoves;
125  HighlightQueries _highlightQueries;
126 };
127 typedef std::vector<Transaction> TransactionQueue;
128 
129 
130 // Scene is a container for Items
131 // Items are introduced, modified or erased in the scene through Transaction
132 // Once per Frame, the Transaction are all flushed
133 // During the flush the standard buckets are updated
134 // Items are notified accordingly on any update message happening
135 class Scene {
136 public:
137 
138  Scene(glm::vec3 origin, float size);
139  ~Scene();
140 
141  // This call is thread safe, can be called from anywhere to allocate a new ID
142  ItemID allocateID();
143 
144  // Check that the ID is valid and allocated for this scene, this a threadsafe call
145  bool isAllocatedID(const ItemID& id) const;
146 
147  // THis is the total number of allocated items, this a threadsafe call
148  size_t getNumItems() const { return _numAllocatedItems.load(); }
149 
150  // Enqueue transaction to the scene
151  void enqueueTransaction(const Transaction& transaction);
152 
153  // Enqueue transaction to the scene
154  void enqueueTransaction(Transaction&& transaction);
155 
156  // Enqueue end of frame transactions boundary
157  uint32_t enqueueFrame();
158 
159  // Process the pending transactions queued
160  void processTransactionQueue();
161 
162  // Access a particular selection (empty if doesn't exist)
163  // Thread safe
164  Selection getSelection(const Selection::Name& name) const;
165 
166  // Check if a particular selection is empty (returns true if doesn't exist)
167  // Thread safe
168  bool isSelectionEmpty(const Selection::Name& name) const;
169 
170  // Add a single item to a selection by name
171  // Thread safe
172  void addItemToSelection(const std::string& selectionName, ItemID itemID);
173 
174  // Remove a selection by name
175  // Thread safe
176  void removeSelection(const std::string& selectionName);
177 
178  // This next call are NOT threadsafe, you have to call them from the correct thread to avoid any potential issues
179 
180  // Access a particular item from its ID
181  // WARNING, There is No check on the validity of the ID, so this could return a bad Item
182  const Item& getItem(const ItemID& id) const { return _items[id]; }
183 
184  // Same as getItem, checking if the id is valid
185  const Item getItemSafe(const ItemID& id) const { if (isAllocatedID(id)) { return _items[id]; } else { return Item(); } }
186 
187  // Access the spatialized items
188  const ItemSpatialTree& getSpatialTree() const { return _masterSpatialTree; }
189 
190  // Access non-spatialized items (layered objects, backgrounds)
191  const ItemIDSet& getNonspatialSet() const { return _masterNonspatialSet; }
192 
193  // Access a particular Stage (empty if doesn't exist)
194  // Thread safe
195  StagePointer getStage(const Stage::Name& name) const;
196  template <class T>
197  std::shared_ptr<T> getStage(const Stage::Name& name = T::getName()) const {
198  auto stage = getStage(name);
199  return (stage ? std::static_pointer_cast<T>(stage) : std::shared_ptr<T>());
200  }
201  void resetStage(const Stage::Name& name, const StagePointer& stage);
202 
203  void setItemTransition(ItemID id, Index transitionId);
204  void removeItemTransition(ItemID id);
205 
206  HighlightStyle getOutlineStyle(ItemID id, const ViewFrustum& viewFrustum, uint16_t height) { return _items[id].getOutlineStyle(viewFrustum, height); }
207 
208 protected:
209 
210  // Thread safe elements that can be accessed from anywhere
211  std::atomic<unsigned int> _IDAllocator{ 1 }; // first valid itemID will be One
212  std::atomic<unsigned int> _numAllocatedItems{ 1 }; // num of allocated items, matching the _items.size()
213  std::mutex _transactionQueueMutex;
214  TransactionQueue _transactionQueue;
215 
216 
217  std::mutex _transactionFramesMutex;
218  using TransactionFrames = std::vector<Transaction>;
219  TransactionFrames _transactionFrames;
220  uint32_t _transactionFrameNumber{ 0 };
221 
222  // Process one transaction frame
223  void processTransactionFrame(const Transaction& transaction);
224 
225  // The actual database
226  // database of items is protected for editing by a mutex
227  std::mutex _itemsMutex;
228  Item::Vector _items;
229  ItemSpatialTree _masterSpatialTree;
230  ItemIDSet _masterNonspatialSet;
231 
232  void resetItems(const Transaction::Resets& transactions);
233  void resetTransitionFinishedOperator(const Transaction::TransitionFinishedOperators& transactions);
234  void removeItems(const Transaction::Removes& transactions);
235  void updateItems(const Transaction::Updates& transactions);
236 
237  void resetTransitionItems(const Transaction::TransitionResets& transactions);
238  void removeTransitionItems(const Transaction::TransitionRemoves& transactions);
239  void queryTransitionItems(const Transaction::TransitionQueries& transactions);
240 
241  void resetHighlights(const Transaction::HighlightResets& transactions);
242  void removeHighlights(const Transaction::HighlightRemoves& transactions);
243  void queryHighlights(const Transaction::HighlightQueries& transactions);
244 
245  void collectSubItems(ItemID parentId, ItemIDs& subItems) const;
246 
247  // The Selection map
248  mutable std::mutex _selectionsMutex; // mutable so it can be used in the thread safe getSelection const method
249  SelectionMap _selections;
250 
251  std::unordered_map<int32_t, std::vector<Transaction::TransitionFinishedFunc>> _transitionFinishedOperatorMap;
252 
253  void resetSelections(const Transaction::SelectionResets& transactions);
254  // More actions coming to selections soon:
255  // void removeFromSelection(const Selection& selection);
256  // void appendToSelection(const Selection& selection);
257  // void mergeWithSelection(const Selection& selection);
258 
259  // The Stage map
260  mutable std::mutex _stagesMutex; // mutable so it can be used in the thread safe getStage const method
261  StageMap _stages;
262 
263 
264  friend class RenderEngine;
265 };
266 
267 typedef std::shared_ptr<Scene> ScenePointer;
268 typedef std::vector<ScenePointer> Scenes;
269 
270 }
271 
272 #endif // hifi_render_Scene_h