1 // Copyright (C) 2013  James Turner
2 //
3 // This program is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU General Public License as
5 // published by the Free Software Foundation; either version 2 of the
6 // License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16 
17 #ifndef NASAL_MODEL_DATA_HXX
18 #define NASAL_MODEL_DATA_HXX
19 
20 #include <simgear/nasal/nasal.h>
21 #include <simgear/scene/model/modellib.hxx>
22 
23 class FGNasalModelData;
24 typedef SGSharedPtr<FGNasalModelData> FGNasalModelDataRef;
25 typedef std::list<FGNasalModelData*> FGNasalModelDataList;
26 
27 /** Nasal model data container.
28  * load and unload methods must be run in main thread (not thread-safe). */
29 class FGNasalModelData : public SGReferenced
30 {
31 public:
32     /** Constructor to be run in an arbitrary thread. */
33     FGNasalModelData( SGPropertyNode *root,
34                       const std::string& path,
35                       SGPropertyNode *prop,
36                       SGPropertyNode* load,
37                       SGPropertyNode* unload,
38                       osg::Node* branch );
39 
40     ~FGNasalModelData();
41 
42     /** Load hook. Always call from inside the main loop. */
43     void load();
44 
45     /** Unload hook. Always call from inside the main loop. */
46     void unload();
47 
48     /**
49      * Get osg scenegraph node of model
50      */
51     osg::Node* getNode();
52 
53     /**
54      * Get FGNasalModelData for model with the given module id. Every scenery
55      * model containing a nasal load or unload tag gets assigned a module id
56      * automatically.
57      *
58      * @param id    Module id
59      * @return model data or NULL if does not exists
60      */
61     static FGNasalModelData* getByModuleId(unsigned int id);
62 
63 private:
64     static unsigned int _max_module_id;
65     static FGNasalModelDataList _loaded_models;
66 
67     std::string _module, _path;
68     SGPropertyNode_ptr _root, _prop;
69     SGConstPropertyNode_ptr _load, _unload;
70     osg::ref_ptr<osg::Node> _branch;
71     unsigned int _module_id;
72 };
73 
74 /** Thread-safe proxy for FGNasalModelData.
75  * modelLoaded/destroy methods only register the requested
76  * operation. Actual (un)loading of Nasal module is deferred
77  * and done in the main loop. */
78 class FGNasalModelDataProxy : public simgear::SGModelData
79 {
80 public:
FGNasalModelDataProxy(SGPropertyNode * root=0)81     FGNasalModelDataProxy(SGPropertyNode *root = 0) :
82     _root(root), _data(0)
83     {
84     }
85 
86     ~FGNasalModelDataProxy();
87 
88     void modelLoaded( const std::string& path,
89                       SGPropertyNode *prop,
90                       osg::Node *branch );
91 
clone() const92     virtual FGNasalModelDataProxy* clone() const { return new FGNasalModelDataProxy(_root); }
93 
getErrorContext() const94     ErrorContext getErrorContext() const override
95     {
96         return {}; // return nothing for now, not yet clear if this proxy needs it
97     }
98 
99 protected:
100     SGPropertyNode_ptr _root;
101     FGNasalModelDataRef _data;
102 };
103 
104 #endif // of NASAL_MODEL_DATA_HXX
105