]> git.mxchange.org Git - simgear.git/blob - simgear/scene/material/EffectBuilder.hxx
New effects from Till Busch: crops, water, landmass
[simgear.git] / simgear / scene / material / EffectBuilder.hxx
1 // Copyright (C) 2009  Tim Moore timoore@redhat.com
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Library General Public
5 // License as published by the Free Software Foundation; either
6 // version 2 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Library 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 SIMGEAR_EFFECTBUILDER_HXX
18 #define SIMGEAR_EFFECTBUILDER_HXX 1
19
20 #include <algorithm>
21 #include <map>
22 #include <string>
23 #include <cstring>
24
25 #include <osgDB/Registry>
26
27 #include <simgear/props/props.hxx>
28 #include <simgear/structure/exception.hxx>
29 #include <simgear/structure/SGSharedPtr.hxx>
30 #include <simgear/structure/Singleton.hxx>
31
32 /**
33  * Support classes for parsing effects.
34  */
35
36 namespace simgear
37 {
38 class Effect;
39
40 /**
41  * Builder that returns an object, probably an OSG object.
42  */
43 template<typename T>
44 class EffectBuilder : public SGReferenced
45 {
46 public:
47     virtual ~EffectBuilder() {}
48     virtual T* build(Effect* effect, const SGPropertyNode*,
49                      const osgDB::ReaderWriter::Options* options) = 0;
50     static T* buildFromType(Effect* effect, const std::string& type,
51                             const SGPropertyNode*props,
52                             const osgDB::ReaderWriter::Options* options)
53     {
54         BuilderMap& builderMap = getMap();
55         typename BuilderMap::iterator iter = builderMap.find(type);
56         if (iter != builderMap.end())
57             return iter->second->build(effect, props, options);
58         else
59             return 0;
60     }
61     struct Registrar;
62     friend struct Registrar;
63     struct Registrar
64     {
65         Registrar(const std::string& type, EffectBuilder* builder)
66         {
67             getMap().insert(std::make_pair(type, builder));
68         }
69     };
70 protected:
71     typedef std::map<std::string, SGSharedPtr<EffectBuilder> > BuilderMap;
72     struct BuilderMapSingleton : public simgear::Singleton<BuilderMapSingleton>
73     {
74         BuilderMap _map;
75     };
76     static BuilderMap& getMap()
77     {
78         return BuilderMapSingleton::instance()->_map;
79     }
80 };
81
82 // Simple tables of strings and constants. The table intialization
83 // *must* be in alphabetical order.
84 template <typename T>
85 struct EffectNameValue
86 {
87     // Don't use std::pair because we want to use aggregate intialization.
88
89     const char* first;
90     T second;
91     class Compare
92     {
93     private:
94         static bool compare(const char* lhs, const char* rhs)
95         {
96             return std::strcmp(lhs, rhs) < 0;
97         }
98     public:
99         bool operator()(const EffectNameValue& lhs,
100                         const EffectNameValue& rhs) const
101         {
102             return compare(lhs.first, rhs.first);
103         }
104         bool operator()(const char* lhs, const EffectNameValue& rhs) const
105         {
106             return compare(lhs, rhs.first);
107         }
108         bool operator()(const EffectNameValue& lhs, const char* rhs) const
109         {
110             return compare (lhs.first, rhs);
111         }
112     };
113 };
114
115 template<typename ENV, typename T, int N>
116 bool findAttr(const ENV (&attrs)[N], const SGPropertyNode* prop, T& result)
117 {
118     if (!prop)
119         return false;
120     const char* name = prop->getStringValue();
121     if (!name)
122         return false;
123     std::pair<const ENV*, const ENV*> itrs
124         = std::equal_range(&attrs[0], &attrs[N], name, typename ENV::Compare());
125     if (itrs.first == itrs.second) {
126         return false;
127     } else {
128         result = itrs.first->second;
129         return true;
130     }
131 }
132
133 /**
134  * Given a property node from a pass, get its value either from it or
135  * from the effect parameters.
136  */
137
138 const SGPropertyNode* getEffectPropertyNode(Effect* effect,
139                                             const SGPropertyNode* prop);
140 /**
141  * Get a named child property from pass parameters or effect
142  * parameters.
143  */
144 const SGPropertyNode* getEffectPropertyChild(Effect* effect,
145                                              const SGPropertyNode* prop,
146                                              const char* name);
147
148 class BuilderException : public sg_exception
149 {
150 public:
151     BuilderException();
152     BuilderException(const char* message, const char* origin = 0);
153     BuilderException(const std::string& message, const std::string& = "");
154     virtual ~BuilderException() throw();
155 };
156 }
157 #endif