Layer 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  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
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. #ifndef OSGTERRAIN_LAYER
  14. #define OSGTERRAIN_LAYER 1
  15. #include <osg/Image>
  16. #include <osg/Shape>
  17. #include <osg/Array>
  18. #include <osg/TransferFunction>
  19. #include <osgTerrain/Locator>
  20. #include <osgTerrain/ValidDataOperator>
  21. namespace osgTerrain {
  22. #define MAXIMUM_NUMBER_OF_LEVELS 30
  23. /** Extact the setname and filename from a compound string in the from set:setname:filename".
  24. * Returns a setname of "" when non set:setname: entry is present.*/
  25. extern OSGTERRAIN_EXPORT void extractSetNameAndFileName(const std::string& compoundstring, std::string& setname, std::string& filename);
  26. /** Create a compound string in the form set:setname:filename, or just filename if setname is "".*/
  27. extern OSGTERRAIN_EXPORT std::string createCompoundSetNameAndFileName(const std::string& setname, const std::string& filename);
  28. class OSGTERRAIN_EXPORT Layer : public osg::Object
  29. {
  30. public:
  31. Layer();
  32. /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
  33. Layer(const Layer&,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
  34. META_Object(osgTerrain, Layer);
  35. /** Set the name of this layer. */
  36. void setSetName(const std::string& setname) { setName(setname); }
  37. /** Get the name of this layer. */
  38. const std::string& getSetName() const { return getName(); }
  39. /** Set the file name of the data associated with this layer. */
  40. virtual void setFileName(const std::string& filename) { _filename = filename; }
  41. /** Get the file name of the layer. */
  42. virtual const std::string& getFileName() const { return _filename; }
  43. /** Return the compound name of the layer in the form set::name::filename string.*/
  44. std::string getCompoundName() const { return createCompoundSetNameAndFileName(getName(), getFileName()); }
  45. void setLocator(Locator* locator) { _locator = locator; }
  46. template<class T> void setLocator(const osg::ref_ptr<T>& locator) { setLocator(locator.get()); }
  47. Locator* getLocator() { return _locator.get(); }
  48. const Locator* getLocator() const { return _locator.get(); }
  49. void setMinLevel(unsigned int minLevel) { _minLevel = minLevel; }
  50. unsigned int getMinLevel() const { return _minLevel; }
  51. void setMaxLevel(unsigned int maxLevel) { _maxLevel = maxLevel; }
  52. unsigned int getMaxLevel() const { return _maxLevel; }
  53. /** Set the data validation operator. */
  54. void setValidDataOperator(ValidDataOperator* validDataOp) { _validDataOperator = validDataOp; }
  55. /** Get the data validation operator. */
  56. ValidDataOperator* getValidDataOperator() { return _validDataOperator.get(); }
  57. /** Get the const data validation operator. */
  58. const ValidDataOperator* getValidDataOperator() const { return _validDataOperator.get(); }
  59. /** Get the number of columns. */
  60. virtual unsigned int getNumColumns() const { return 0; }
  61. /** Get the number of rows. */
  62. virtual unsigned int getNumRows() const { return 0; }
  63. void setDefaultValue(const osg::Vec4& value) { _defaultValue = value; }
  64. const osg::Vec4& getDefaultValue() const { return _defaultValue; }
  65. /** Set the minification texture filter to use when a texture is associated with this layer.*/
  66. void setMinFilter(osg::Texture::FilterMode filter) { _minFilter = filter; }
  67. /** Get the minification texture filter to use when a texture is associated with this layer.*/
  68. osg::Texture::FilterMode getMinFilter() const { return _minFilter; }
  69. /** Set the magnification texture filter to use when a texture is associated with this layer.*/
  70. void setMagFilter(osg::Texture::FilterMode filter) { _magFilter = filter; }
  71. /** Get the magnification texture filter to use when a texture is associated with this layer.*/
  72. osg::Texture::FilterMode getMagFilter() const { return _magFilter; }
  73. /** Return image associated with layer if supported. */
  74. virtual osg::Image* getImage() { return 0; }
  75. /** Return const image associated with layer if supported. */
  76. virtual const osg::Image* getImage() const { return 0; }
  77. virtual bool transform(float /*offset*/, float /*scale*/) { return false; }
  78. /**
  79. * Get the layer value at position i,j.
  80. * param i X-axis (or column) index.
  81. * param j Y-axis (or row) index.
  82. * param value Returned layer value.
  83. * @return true if value is valid, else false
  84. */
  85. virtual bool getValue(unsigned int /*i*/, unsigned int /*j*/, float& /*value*/) const { return false; }
  86. virtual bool getValue(unsigned int /*i*/, unsigned int /*j*/, osg::Vec2& /*value*/) const { return false; }
  87. virtual bool getValue(unsigned int /*i*/, unsigned int /*j*/, osg::Vec3& /*value*/) const { return false; }
  88. virtual bool getValue(unsigned int /*i*/, unsigned int /*j*/, osg::Vec4& /*value*/) const { return false; }
  89. inline bool getValidValue(unsigned int i, unsigned int j, float& value) const
  90. {
  91. if (getValue(i,j,value)) return _validDataOperator.valid() ? (*_validDataOperator)(value) : true;
  92. return false;
  93. }
  94. inline bool getValidValue(unsigned int i, unsigned int j, osg::Vec2& value) const
  95. {
  96. if (getValue(i,j,value)) return _validDataOperator.valid() ? (*_validDataOperator)(value) : true;
  97. return false;
  98. }
  99. inline bool getValidValue(unsigned int i, unsigned int j, osg::Vec3& value) const
  100. {
  101. if (getValue(i,j,value)) return _validDataOperator.valid() ? (*_validDataOperator)(value) : true;
  102. return false;
  103. }
  104. inline bool getValidValue(unsigned int i, unsigned int j, osg::Vec4& value) const
  105. {
  106. if (getValue(i,j,value)) return _validDataOperator.valid() ? (*_validDataOperator)(value) : true;
  107. return false;
  108. }
  109. /**
  110. * Compute column,row indices from normalized coordinates.
  111. * @param[in] ndc_x Normalized X-axis coordinate.
  112. * @param[in] ndc_y Normalized Y-axis coordinate.
  113. * @param[out] i Returned X-axis (or column) index.
  114. * @param[out] j Returned Y-axis (or row) index.
  115. * @param[out] ir Returned X-axis fraction.
  116. * @param[out] jr Returned Y-axis fraction.
  117. */
  118. inline void computeIndices(double ndc_x, double ndc_y, unsigned int& i, unsigned int& j, double& ir, double& jr) const
  119. {
  120. ndc_x *= double(getNumColumns()-1);
  121. ndc_y *= double(getNumRows()-1);
  122. i = (unsigned int)(ndc_x);
  123. j = (unsigned int)(ndc_y);
  124. ir = ndc_x - double(i);
  125. jr = ndc_y - double(j);
  126. }
  127. /**
  128. * Calculate the interpolated layer value at the given normalized coordinates.
  129. * @param[in] ndc_x Normalized X-axis coordinate.
  130. * @param[in] ndc_y Normalized Y-axis coordinate.
  131. * @param[out] value Returned layer value.
  132. * @return true if value is valid, else false
  133. */
  134. inline bool getInterpolatedValue(double ndc_x, double ndc_y, float& value) const
  135. {
  136. unsigned int i,j;
  137. double ir, jr;
  138. computeIndices(ndc_x, ndc_y, i, j, ir, jr);
  139. value = 0.0f;
  140. double div = 0.0f;
  141. float v,r;
  142. r = (1.0f-ir)*(1.0f-jr);
  143. if (r>0.0 && getValue(i,j,v))
  144. {
  145. value += v*r;
  146. div += r;
  147. }
  148. r = (ir)*(1.0f-jr);
  149. if (r>0.0 && getValue(i+1,j,v))
  150. {
  151. value += v*r;
  152. div += r;
  153. }
  154. r = (ir)*(jr);
  155. if (r>0.0 && getValue(i+1,j+1,v))
  156. {
  157. value += v*r;
  158. div += r;
  159. }
  160. r = (1.0f-ir)*(jr);
  161. if (r>0.0 && getValue(i,j+1,v))
  162. {
  163. value += v*r;
  164. div += r;
  165. }
  166. if (div != 0.0)
  167. {
  168. value /= div;
  169. return true;
  170. }
  171. value = 0.0;
  172. return false;
  173. }
  174. inline bool getInterpolatedValidValue(double ndc_x, double ndc_y, float& value) const
  175. {
  176. unsigned int i,j;
  177. double ir, jr;
  178. computeIndices(ndc_x, ndc_y, i, j, ir, jr);
  179. value = 0.0f;
  180. double div = 0.0f;
  181. float v,r;
  182. r = (1.0f-ir)*(1.0f-jr);
  183. if (r>0.0 && getValidValue(i,j,v))
  184. {
  185. value += v*r;
  186. div += r;
  187. }
  188. r = (ir)*(1.0f-jr);
  189. if (r>0.0 && getValidValue(i+1,j,v))
  190. {
  191. value += v*r;
  192. div += r;
  193. }
  194. r = (ir)*(jr);
  195. if (r>0.0 && getValidValue(i+1,j+1,v))
  196. {
  197. value += v*r;
  198. div += r;
  199. }
  200. r = (1.0f-ir)*(jr);
  201. if (r>0.0 && getValidValue(i,j+1,v))
  202. {
  203. value += v*r;
  204. div += r;
  205. }
  206. if (div != 0.0)
  207. {
  208. value /= div;
  209. return true;
  210. }
  211. value = 0.0;
  212. return false;
  213. }
  214. /** increment the modified count."*/
  215. virtual void dirty() {}
  216. /** Set the modified count value. */
  217. virtual void setModifiedCount(unsigned int /*value*/) {}
  218. /** Get modified count value. */
  219. virtual unsigned int getModifiedCount() const { return 0; }
  220. virtual osg::BoundingSphere computeBound(bool treatAsElevationLayer) const;
  221. protected:
  222. virtual ~Layer();
  223. std::string _filename;
  224. osg::ref_ptr<Locator> _locator;
  225. unsigned int _minLevel;
  226. unsigned int _maxLevel;
  227. osg::ref_ptr<ValidDataOperator> _validDataOperator;
  228. osg::Vec4 _defaultValue;
  229. osg::Texture::FilterMode _minFilter;
  230. osg::Texture::FilterMode _magFilter;
  231. };
  232. class OSGTERRAIN_EXPORT ImageLayer : public Layer
  233. {
  234. public:
  235. ImageLayer(osg::Image* image=0);
  236. /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
  237. ImageLayer(const ImageLayer& imageLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
  238. META_Object(osgTerrain, ImageLayer);
  239. void setFileName(const std::string& filename) { _filename = filename; if (_image.valid()) _image->setFileName(filename); }
  240. virtual const std::string& getFileName() const { return _image.get() ? _image->getFileName() : _filename; }
  241. virtual bool transform(float offset, float scale);
  242. void setImage(osg::Image* image);
  243. template<class T> void setImage(const osg::ref_ptr<T>& image) { return setImage(image.get()); }
  244. /** Return image associated with layer. */
  245. virtual osg::Image* getImage() { return _image.get(); }
  246. /** Return const image associated with layer. */
  247. virtual const osg::Image* getImage() const { return _image.get(); }
  248. virtual unsigned int getNumColumns() const { return _image.valid() ? _image->s() : 0; }
  249. virtual unsigned int getNumRows() const { return _image.valid() ? _image->t() : 0; }
  250. virtual bool getValue(unsigned int i, unsigned int j, float& value) const;
  251. virtual bool getValue(unsigned int i, unsigned int j, osg::Vec2& value) const;
  252. virtual bool getValue(unsigned int i, unsigned int j, osg::Vec3& value) const;
  253. virtual bool getValue(unsigned int i, unsigned int j, osg::Vec4& value) const;
  254. virtual void dirty();
  255. virtual void setModifiedCount(unsigned int value);
  256. virtual unsigned int getModifiedCount() const;
  257. protected:
  258. virtual ~ImageLayer() {}
  259. osg::ref_ptr<osg::Image> _image;
  260. };
  261. class OSGTERRAIN_EXPORT ContourLayer : public Layer
  262. {
  263. public:
  264. ContourLayer(osg::TransferFunction1D* tf=0);
  265. /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
  266. ContourLayer(const ContourLayer& tfLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
  267. META_Object(osgTerrain, ContourLayer);
  268. virtual bool transform(float offset, float scale);
  269. void setTransferFunction(osg::TransferFunction1D* tf);
  270. template<class T> void setTransferFunction(const osg::ref_ptr<T>& tf) { return setTransferFunction(tf.get()); }
  271. osg::TransferFunction1D* getTransferFunction() { return _tf.get(); }
  272. const osg::TransferFunction1D* getTransferFunction() const { return _tf.get(); }
  273. /** Return image associated with layer. */
  274. virtual osg::Image* getImage() { return _tf.valid() ? _tf->getImage() : 0; }
  275. /** Return const image associated with layer. */
  276. virtual const osg::Image* getImage() const { return _tf.valid() ? _tf->getImage() : 0; }
  277. virtual unsigned int getNumColumns() const { return _tf.valid() ? _tf->getNumberImageCells() : 0; }
  278. virtual unsigned int getNumRows() const { return _tf.valid() ? 1 : 0; }
  279. virtual bool getValue(unsigned int i, unsigned int j, float& value) const;
  280. virtual bool getValue(unsigned int i, unsigned int j, osg::Vec2& value) const;
  281. virtual bool getValue(unsigned int i, unsigned int j, osg::Vec3& value) const;
  282. virtual bool getValue(unsigned int i, unsigned int j, osg::Vec4& value) const;
  283. virtual void dirty();
  284. virtual void setModifiedCount(unsigned int value);
  285. virtual unsigned int getModifiedCount() const;
  286. protected:
  287. virtual ~ContourLayer() {}
  288. osg::ref_ptr<osg::TransferFunction1D> _tf;
  289. };
  290. class OSGTERRAIN_EXPORT HeightFieldLayer : public Layer
  291. {
  292. public:
  293. HeightFieldLayer(osg::HeightField* hf=0);
  294. /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
  295. HeightFieldLayer(const HeightFieldLayer& hfLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
  296. META_Object(osgTerrain, HeightFieldLayer);
  297. void setFileName(const std::string& filename) { _filename = filename; }
  298. virtual const std::string& getFileName() const { return _filename; }
  299. virtual bool transform(float offset, float scale);
  300. void setHeightField(osg::HeightField* hf);
  301. template<class T> void setHeightField(const osg::ref_ptr<T>& hf) { return setHeightField(hf.get()); }
  302. osg::HeightField* getHeightField() { return _heightField.get(); }
  303. const osg::HeightField* getHeightField() const { return _heightField.get(); }
  304. virtual unsigned int getNumColumns() const { return _heightField.valid() ? _heightField->getNumColumns() : 0; }
  305. virtual unsigned int getNumRows() const { return _heightField.valid() ? _heightField->getNumRows() : 0; }
  306. virtual bool getValue(unsigned int i, unsigned int j, float& value) const;
  307. virtual bool getValue(unsigned int i, unsigned int j, osg::Vec2& value) const;
  308. virtual bool getValue(unsigned int i, unsigned int j, osg::Vec3& value) const;
  309. virtual bool getValue(unsigned int i, unsigned int j, osg::Vec4& value) const;
  310. virtual void dirty();
  311. virtual void setModifiedCount(unsigned int value);
  312. virtual unsigned int getModifiedCount() const;
  313. protected:
  314. virtual ~HeightFieldLayer() {}
  315. unsigned int _modifiedCount;
  316. osg::ref_ptr<osg::HeightField> _heightField;
  317. };
  318. class OSGTERRAIN_EXPORT ProxyLayer : public Layer
  319. {
  320. public:
  321. ProxyLayer();
  322. /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
  323. ProxyLayer(const ProxyLayer& proxyLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
  324. META_Object(osgTerrain, ProxyLayer);
  325. /** Return image associated with layer if supported. */
  326. virtual osg::Image* getImage()
  327. {
  328. return _implementation.valid() ? _implementation->getImage() : 0;
  329. }
  330. /** Return const image associated with layer if supported. */
  331. virtual const osg::Image* getImage() const
  332. {
  333. return _implementation.valid() ? _implementation->getImage() : 0;
  334. }
  335. /** Set the implementation layer that does the actual work.*/
  336. void setImplementation(Layer* layer) { _implementation = layer; }
  337. /** Get the implementation layer that does the actual work.*/
  338. Layer* getImplementation() { return _implementation.get(); }
  339. /** Get the const implementation layer that does the actual work.*/
  340. const Layer* getImplementation() const { return _implementation.get(); }
  341. virtual void setFileName(const std::string& filename);
  342. virtual const std::string& getFileName() const { return _filename; }
  343. virtual unsigned int getNumColumns() const;
  344. virtual unsigned int getNumRows() const;
  345. virtual bool transform(float offset, float scale);
  346. virtual bool getValue(unsigned int i, unsigned int j, float& value) const;
  347. virtual bool getValue(unsigned int i, unsigned int j, osg::Vec2& value) const;
  348. virtual bool getValue(unsigned int i, unsigned int j, osg::Vec3& value) const;
  349. virtual bool getValue(unsigned int i, unsigned int j, osg::Vec4& value) const;
  350. virtual void dirty();
  351. virtual void setModifiedCount(unsigned int value);
  352. virtual unsigned int getModifiedCount() const;
  353. virtual osg::BoundingSphere computeBound(bool treatAsElevationLayer) const;
  354. protected:
  355. virtual ~ProxyLayer();
  356. osg::ref_ptr<Layer> _implementation;
  357. };
  358. class OSGTERRAIN_EXPORT CompositeLayer : public Layer
  359. {
  360. public:
  361. CompositeLayer();
  362. /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
  363. CompositeLayer(const CompositeLayer& compositeLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
  364. META_Object(osgTerrain, CompositeLayer);
  365. void clear();
  366. /** Set the set name of layer 'i'. */
  367. void setSetName(unsigned int i, const std::string& setname) { _layers[i].setname = setname; if (_layers[i].layer.valid()) _layers[i].layer->setName(setname); }
  368. /** Get the set name of layer 'i'. */
  369. const std::string& getSetName(unsigned int i) const { return _layers[i].layer.valid() ? _layers[i].layer->getName() : _layers[i].setname; }
  370. /** Set the file name of the data associated with layer 'i'. */
  371. void setFileName(unsigned int i, const std::string& filename) { _layers[i].filename = filename; if (_layers[i].layer.valid()) _layers[i].layer->setFileName(filename); }
  372. /** Get the file name of the data associated with layer 'i'. */
  373. const std::string& getFileName(unsigned int i) const { return _layers[i].layer.valid() ? _layers[i].layer->getFileName() : _layers[i].filename; }
  374. void setCompoundName(unsigned int i, const std::string& compoundname);
  375. std::string getCompoundName(unsigned int i) const;
  376. void setLayer(unsigned int i, Layer* layer) { if (i>=_layers.size()) _layers.resize(i+1); _layers[i].layer = layer; }
  377. template<class T> void setLayer(unsigned int i, const osg::ref_ptr<T>& layer) { setLayer(i, layer.get()); }
  378. Layer* getLayer(unsigned int i) { return i<_layers.size() ? _layers[i].layer.get() : 0; }
  379. const Layer* getLayer(unsigned int i) const { return i<_layers.size() ? _layers[i].layer.get() : 0; }
  380. void addLayer(const std::string& compoundname);
  381. void addLayer(const std::string& setname, const std::string& filename);
  382. void addLayer(Layer* layer) { _layers.push_back(CompoundNameLayer(layer->getName(),layer->getFileName(),layer)); }
  383. template<class T> void addLayer(const osg::ref_ptr<T>& layer) { return addLayer(layer.get()); }
  384. void removeLayer(unsigned int i) { _layers.erase(_layers.begin()+i); }
  385. unsigned int getNumLayers() const { return static_cast<unsigned int>(_layers.size()); }
  386. protected:
  387. virtual ~CompositeLayer() {}
  388. struct CompoundNameLayer
  389. {
  390. CompoundNameLayer() {}
  391. CompoundNameLayer(const CompoundNameLayer& cnl):
  392. setname(cnl.setname),
  393. filename(cnl.filename),
  394. layer(cnl.layer) {}
  395. CompoundNameLayer(const std::string& sn, const std::string& fn, Layer* l):
  396. setname(sn),
  397. filename(fn),
  398. layer(l) {}
  399. CompoundNameLayer& operator = (const CompoundNameLayer& cnl)
  400. {
  401. if (&cnl==this) return *this;
  402. setname = cnl.setname;
  403. filename = cnl.filename;
  404. layer = cnl.layer;
  405. return *this;
  406. }
  407. std::string setname;
  408. std::string filename;
  409. osg::ref_ptr<Layer> layer;
  410. };
  411. typedef std::vector< CompoundNameLayer > Layers;
  412. Layers _layers;
  413. };
  414. class OSGTERRAIN_EXPORT SwitchLayer : public CompositeLayer
  415. {
  416. public:
  417. SwitchLayer();
  418. /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
  419. SwitchLayer(const SwitchLayer& switchLayer,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
  420. META_Object(osgTerrain, SwitchLayer);
  421. void setActiveLayer(int i) { _activeLayer = i; }
  422. int getActiveLayer() const { return _activeLayer; }
  423. /** Return image associated with layer if supported. */
  424. virtual osg::Image* getImage()
  425. {
  426. if (_activeLayer < 0) return 0;
  427. if (_activeLayer >= static_cast<int>(getNumLayers())) return 0;
  428. return _layers[_activeLayer].layer->getImage();
  429. }
  430. /** Return const image associated with layer if supported. */
  431. virtual const osg::Image* getImage() const
  432. {
  433. if (_activeLayer < 0) return 0;
  434. if (_activeLayer >= static_cast<int>(getNumLayers())) return 0;
  435. return _layers[_activeLayer].layer->getImage();
  436. }
  437. protected:
  438. virtual ~SwitchLayer() {}
  439. int _activeLayer;
  440. };
  441. }
  442. #endif