Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
REveScene.cxx
Go to the documentation of this file.
1// @(#)root/eve7:$Id$
2// Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007, 2018
3
4/*************************************************************************
5 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <ROOT/REveScene.hxx>
13#include <ROOT/REveViewer.hxx>
14#include <ROOT/REveManager.hxx>
15#include <ROOT/REveTrans.hxx>
17#include <ROOT/REveClient.hxx>
18#include <ROOT/RWebWindow.hxx>
19
20#include <cassert>
21
22#include <nlohmann/json.hpp>
23
24using namespace ROOT::Experimental;
25namespace REX = ROOT::Experimental;
26
27/** \class REveScene
28\ingroup REve
29Eve representation of TGLScene.
30The GLScene is owned by this class - it is created on construction
31time and deleted at destruction.
32
33Normally all objects are positioned directly in global scene-space.
34By setting the fHierarchical flag, positions of children get
35calculated by multiplying the transformation matrices of all parents.
36*/
37
38////////////////////////////////////////////////////////////////////////////////
39/// Constructor.
40
41REveScene::REveScene(const std::string& n, const std::string& t) :
42 REveElement(n, t)
43{
44 fScene = this;
45}
46
47////////////////////////////////////////////////////////////////////////////////
48/// Destructor.
49
51{
53
56}
57//------------------------------------------------------------------------------
58
59int REveScene::WriteCoreJson(nlohmann::json &j, Int_t rnr_offset)
60{
61 j["Mandatory"] = fMandatory;
62 j["IsOverlay"] = fIsOverlay;
63
64 return REveElement::WriteCoreJson(j, rnr_offset);
65}
66
67//------------------------------------------------------------------------------
68
69void REveScene::AddSubscriber(std::unique_ptr<REveClient> &&sub)
70{
71 assert(sub.get() != nullptr && fAcceptingChanges == kFALSE);
72
73 fSubscribers.emplace_back(std::move(sub));
74
75 // XXX Here should send out the package to the new subscriber,
76 // In principle can expect a new one in short time?
77 // Keep streamed data until next begin change, maybe.
78}
79
81{
82 auto pred = [&](std::unique_ptr<REveClient> &client) {
83 return client->fId == id;
84 };
85
86 fSubscribers.erase(std::remove_if(fSubscribers.begin(), fSubscribers.end(), pred), fSubscribers.end());
87}
88
89// Add Button in client gui with this command
90void REveScene::AddCommand(const std::string &name, const std::string &icon, const REveElement *element, const std::string &action)
91{
92 static const REveException eh("REveScene::AddCommand ");
93 if (element->GetElementId() && element->IsA())
94 {
95 fCommands.emplace_back(name, icon, element, action);
96 }
97 else
98 {
99 throw eh + "Element id and dictionary has to be defined";
100 }
101}
102
104{
105 if (fAcceptingChanges) return;
106
107 if (HasSubscribers()) {
109 /*
110 for (auto &&client : fSubscribers) {
111 REX::gEve->SceneSubscriberProcessingChanges(client->fId);
112 }
113 */
114 }
115}
116
118{
119 assert(fAcceptingChanges);
120
121 fChangedElements.push_back(element);
122}
123
125{
126 fRemovedElements.push_back(id);
127}
128
130{
131 if ( ! fAcceptingChanges) return;
132
134}
135
137{
138 fOutputJson.clear();
139 fOutputBinary.clear();
140
141 fElsWithBinaryData.clear();
143
144 nlohmann::json jarr = nlohmann::json::array();
145
146 nlohmann::json jhdr = {};
147 jhdr["content"] = "REveScene::StreamElements";
148 jhdr["fSceneId"] = fElementId;
149
150 if (!fCommands.empty()) {
151 jhdr["commands"] = nlohmann::json::array();
152 for (auto &&cmd : fCommands) {
153 nlohmann::json jcmd = {};
154 jcmd["name"] = cmd.fName;
155 jcmd["icon"] = cmd.fIcon;
156 jcmd["elementid"] = cmd.fElementId;
157 jcmd["elementclass"] = cmd.fElementClass;
158 jcmd["func"] = cmd.fAction; // SL: may be not needed on client side, can use name
159 jhdr["commands"].push_back(jcmd);
160 }
161 }
162
163 jarr.push_back(jhdr);
164
165 StreamJsonRecurse(this, jarr);
166 // for (auto &c : fChildren)
167 // {
168 // StreamJsonRecurse(c, jarr);
169 // }
170
172 Int_t off = 0;
173
174 for (auto &&e : fElsWithBinaryData)
175 {
176 auto rd_size = e->fRenderData->Write(&fOutputBinary[off], fOutputBinary.size() - off);
177 off += rd_size;
178 }
179 assert(off == fTotalBinarySize);
180
181 jarr.front()["fTotalBinarySize"] = fTotalBinarySize;
182
183 fOutputJson = jarr.dump();
184}
185
186void REveScene::StreamJsonRecurse(REveElement *el, nlohmann::json &jarr)
187{
188 nlohmann::json jobj = {};
189 Int_t rd_size = el->WriteCoreJson(jobj, fTotalBinarySize);
190 jarr.push_back(jobj);
191
192 // If this is another scene, do not stream additional details.
193 // It should be requested / subscribed to independently.
194
195 if (el->fScene == el && el != this)
196 {
197 return;
198 }
199
200 if (rd_size > 0)
201 {
202 assert (rd_size % 4 == 0);
203
204 fTotalBinarySize += rd_size;
205 fElsWithBinaryData.push_back(el);
206 }
207
208 for (auto &&c : el->fChildren)
209 {
210 // Stream only objects element el is a mother of.
211 //
212 // XXXX This is spooky side effect of multi-parenting.
213 //
214 // In particular screwed up for selection.
215 // Selection now streams element ids and implied selected ids
216 // and secondary-ids as part of core json.
217 //
218 // I wonder how this screws up REveProjectionManager (should
219 // we hold a map of already streamed ids?).
220 //
221 // Do uncles and aunts and figure out a clean way for backrefs.
222
223 if (c->GetMother() == el)
224 {
225 StreamJsonRecurse(c, jarr);
226 }
227 }
228}
229
230////////////////////////////////////////////////////////////////////////////////
231//
232/// Prepare data for sending element changes
233//
234////////////////////////////////////////////////////////////////////////////////
235
237{
238 fElsWithBinaryData.clear();
240
241 nlohmann::json jarr = nlohmann::json::array();
242
243 nlohmann::json jhdr = {};
244 jhdr["content"] = "ElementsRepresentaionChanges";
245 jhdr["fSceneId"] = fElementId;
246
247 jhdr["removedElements"] = nlohmann::json::array();
248 for (auto &re : fRemovedElements)
249 jhdr["removedElements"].push_back(re);
250
251 jhdr["numRepresentationChanged"] = fChangedElements.size();
252
253 // jarr.push_back(jhdr);
254
255 for (auto &el: fChangedElements)
256 {
257 UChar_t bits = el->GetChangeBits();
258
259 nlohmann::json jobj = {};
260 jobj["fElementId"] = el->GetElementId();
261 jobj["changeBit"] = bits;
262
263 if (bits & kCBElementAdded || bits & kCBObjProps)
264 {
265 if (gDebug > 0 && bits & kCBElementAdded)
266 {
267 Info("REveScene::StreamRepresentationChanges", "new element change %s %d\n",
268 el->GetCName(), bits);
269 }
270
271 Int_t rd_size = el->WriteCoreJson(jobj, fTotalBinarySize);
272 if (rd_size) {
273 assert (rd_size % 4 == 0);
274 fTotalBinarySize += rd_size;
275 fElsWithBinaryData.push_back(el);
276 }
277 }
278 else
279 {
280 if (bits & kCBVisibility)
281 {
282 jobj["fRnrSelf"] = el->GetRnrSelf();
283 jobj["fRnrChildren"] = el->GetRnrChildren();
284 }
285
286 if (bits & kCBColorSelection)
287 {
288 el->WriteCoreJson(jobj, -1);
289 }
290
291 if (bits & kCBTransBBox)
292 {
293 }
294 }
295
296 jarr.push_back(jobj);
297
298 el->ClearStamps();
299 }
300
301 fChangedElements.clear();
302 fRemovedElements.clear();
303
304 // render data for total change
306 Int_t off = 0;
307
308 for (auto &e : fElsWithBinaryData) {
309 auto rd_size = e->fRenderData->Write(&fOutputBinary[off], fOutputBinary.size() - off);
310
311 off += rd_size;
312 }
313 assert(off == fTotalBinarySize);
314
315 jhdr["fTotalBinarySize"] = fTotalBinarySize;
316
317 nlohmann::json msg = { {"header", jhdr}, {"arr", jarr}};
318 fOutputJson = msg.dump();
319
320 if (gDebug > 0)
321 Info("REveScene::StreamRepresentationChanges", "class: %s changes %s ...", GetCName(), msg.dump(1).c_str() );
322}
323
325{
326 for (auto && client : fSubscribers) {
327 if (!fOutputJson.empty()) {
328 if (gDebug > 0)
329 printf(" sending json, len = %d --> to conn_id = %d\n", (int) fOutputJson.size(), client->fId);
330 client->fWebWindow->Send(client->fId, fOutputJson);
331 }
332 if (fTotalBinarySize) {
333 if (gDebug > 0)
334 printf(" sending binary, len = %d --> to conn_id = %d\n", fTotalBinarySize, client->fId);
335 client->fWebWindow->SendBinary(client->fId, &fOutputBinary[0], fTotalBinarySize);
336 }
338 }
339 fOutputJson.clear();
340 fOutputBinary.clear();
342}
343
345{
346 if (gDebug > 0)
347 ::Info("REveScene::IsChanged","%s (changed_or_added=%d, removed=%d)", GetCName(),
348 (int) fChangedElements.size(), (int) fRemovedElements.size());
349
350 return ! (fChangedElements.empty() && fRemovedElements.empty());
351}
352
353
354/** \class REveSceneList
355\ingroup REve
356List of Scenes providing common operations on REveScene collections.
357*/
358
359////////////////////////////////////////////////////////////////////////////////
360/// Constructor.
361
362REveSceneList::REveSceneList(const std::string& n, const std::string& t) :
363 REveElement(n, t)
364{
365 SetChildClass(TClass::GetClass<REveScene>());
366}
367
368////////////////////////////////////////////////////////////////////////////////
369/// Destroy all scenes and their contents.
370/// The object with non-zero deny-destroy will still survive.
371
373{
374 auto i = fChildren.begin();
375 while (i != fChildren.end())
376 {
377 REveScene* s = (REveScene*) *(i++);
378 s->DestroyElements();
379 s->DestroyOrWarn();
380 }
381}
382
383////////////////////////////////////////////////////////////////////////////////
384/// Loop-wrapers over Scene children, element type checked on insertion.
385
387{
388 for (auto &c: fChildren)
389 {
390 static_cast<REveScene*>(c)->BeginAcceptingChanges();
391 }
392}
393
395{
396 for (auto &c: fChildren)
397 {
398 static_cast<REveScene*>(c)->EndAcceptingChanges();
399 }
400}
401
403{
404 for (auto &el : fChildren)
405 {
406 if (((REveScene*) el)->IsChanged())
407 return true;
408 }
409 return false;
410}
#define c(i)
Definition RSha256.hxx:101
#define e(i)
Definition RSha256.hxx:103
unsigned char UChar_t
Definition RtypesCore.h:38
constexpr Bool_t kFALSE
Definition RtypesCore.h:94
constexpr Bool_t kTRUE
Definition RtypesCore.h:93
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:218
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
char name[80]
Definition TGX11.cxx:110
Int_t gDebug
Definition TROOT.cxx:597
virtual void DestroyOrWarn()
Destroy this element. Prints a warning if deny-destroy is in force.
TClass * IsA() const
Return class for this element Return REveElement class in case dicitonary is not exisiting.
virtual Int_t WriteCoreJson(nlohmann::json &cj, Int_t rnr_offset)
Write core json.
const char * GetCName() const
virtual void DestroyElements()
Destroy all children of this element.
ElementId_t GetElementId() const
virtual void RemoveElement(REveElement *el)
Remove el from the list of children.
REveException Exception-type thrown by Eve classes.
Definition REveTypes.hxx:43
REveSceneList * GetScenes() const
void SceneSubscriberWaitingResponse(unsigned cinnId)
REveViewerList * GetViewers() const
REveSceneList(const REveSceneList &)=delete
void BeginAcceptingChanges()
Loop-wrapers over Scene children, element type checked on insertion.
void DestroyScenes()
Destroy all scenes and their contents.
std::vector< std::unique_ptr< REveClient > > fSubscribers
!
Definition REveScene.hxx:72
void AddCommand(const std::string &name, const std::string &icon, const REveElement *element, const std::string &action)
Definition REveScene.cxx:90
void AddSubscriber(std::unique_ptr< REveClient > &&sub)
Definition REveScene.cxx:69
std::vector< char > fOutputBinary
!
Definition REveScene.hxx:76
~REveScene() override
Destructor.
Definition REveScene.cxx:50
void SceneElementRemoved(ElementId_t id)
void StreamRepresentationChanges()
Prepare data for sending element changes.
void StreamJsonRecurse(REveElement *el, nlohmann::json &jobj)
std::vector< SceneCommand > fCommands
!
Definition REveScene.hxx:79
Int_t WriteCoreJson(nlohmann::json &cj, Int_t rnr_offset) override
Write core json.
Definition REveScene.cxx:59
std::vector< ElementId_t > fRemovedElements
!
Definition REveScene.hxx:70
void SceneElementChanged(REveElement *element)
void RemoveSubscriber(unsigned int)
Definition REveScene.cxx:80
void SceneDestructing(REveScene *scene)
Callback done from a REveScene destructor allowing proper removal of the scene from affected viewers.
const Int_t n
Definition legend1.C:16
R__EXTERN REveManager * gEve