source: OGRE/trunk/ogrenew/OgreMain/include/OgreMaterial.h @ 657

Revision 657, 30.3 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

RevLine 
[657]1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#ifndef _Material_H__
26#define _Material_H__
27
28#include "OgrePrerequisites.h"
29
30#include "OgreResource.h"
31#include "OgreIteratorWrappers.h"
32#include "OgreCommon.h"
33#include "OgreColourValue.h"
34#include "OgreBlendMode.h"
35
36
37namespace Ogre {
38
39        // Forward declaration
40        class MaterialPtr;
41
42        /** Class encapsulates rendering properties of an object.
43    @remarks
44    Ogre's material class encapsulates ALL aspects of the visual appearance,
45    of an object. It also includes other flags which
46    might not be traditionally thought of as material properties such as
47    culling modes and depth buffer settings, but these affect the
48    appearance of the rendered object and are convenient to attach to the
49    material since it keeps all the settings in one place. This is
50    different to Direct3D which treats a material as just the colour
51    components (diffuse, specular) and not texture maps etc. An Ogre
52    Material can be thought of as equivalent to a 'Shader'.
53    @par
54    A Material can be rendered in multiple different ways depending on the
55    hardware available. You may configure a Material to use high-complexity
56    fragment shaders, but these won't work on every card; therefore a Technique
57    is an approach to creating the visual effect you are looking for. You are advised
58    to create fallback techniques with lower hardware requirements if you decide to
59    use advanced features. In addition, you also might want lower-detail techniques
60    for distant geometry.
61    @par
62    Each technique can be made up of multiple passes. A fixed-function pass
63    may combine multiple texture layers using multitexrtuing, but Ogre can
64    break that into multiple passes automatically if the active card cannot
65    handle that many simultaneous textures. Programmable passes, however, cannot
66    be split down automatically, so if the active graphics card cannot handle the
67    technique which contains these passes, OGRE will try to find another technique
68    which the card can do. If, at the end of the day, the card cannot handle any of the
69    techniques which are listed for the material, the engine will render the
70    geometry plain white, which should alert you to the problem.
71    @par
72    Ogre comes configured with a number of default settings for a newly
73    created material. These can be changed if you wish by retrieving the
74    default material settings through
75    SceneManager::getDefaultMaterialSettings. Any changes you make to the
76    Material returned from this method will apply to any materials created
77    from this point onward.
78    */
79    class _OgreExport Material : public Resource
80    {
81        friend class SceneManager;
82        friend class MaterialManager;
83
84    public:
85        /// distance list used to specify LOD
86        typedef std::vector<Real> LodDistanceList;
87        typedef ConstVectorIterator<LodDistanceList> LodDistanceIterator;
88    protected:
89
90
91        /** Internal method which sets the material up from the default settings.
92        */
93        void applyDefaults(void);
94
95        typedef std::vector<Technique*> Techniques;
96        Techniques mTechniques;
97        Techniques mSupportedTechniques;
98        typedef std::map<unsigned short, Technique*> BestTechniqueList;
99        BestTechniqueList mBestTechniqueList;
100
101        LodDistanceList mLodDistances;
102        bool mReceiveShadows;
103                bool mTransparencyCastsShadows;
104        /// Does this material require compilation?
105        bool mCompilationRequired;
106
107        /** Fixup the best technique list guarantees no gaps inside.
108        @remarks
109            Iterate over the best technique list, looking for gaps and filling them in
110            guarantees we've got a sequential list with entries in all indexes
111        */
112        void fixupBestTechniqueList(void);
113
114                /** Overridden from Resource.
115                */
116                void loadImpl(void);
117
118                /** Unloads the material, frees resources etc.
119                @see
120                Resource
121                */
122                void unloadImpl(void);
123                /// @copydoc Resource::calculateSize
124                size_t calculateSize(void) const { return 0; } // TODO
125    public:
126
127        /** Constructor - use resource manager's create method rather than this.
128        */
129                Material(ResourceManager* creator, const String& name, ResourceHandle handle,
130                        const String& group, bool isManual = false, ManualResourceLoader* loader = 0);
131
132        ~Material();
133        /** Assignment operator to allow easy copying between materials.
134        */
135        Material& operator=( const Material& rhs );
136
137        /** Determines if the material has any transparency with the rest of the scene (derived from
138            whether any Techniques say they involve transparency).
139        */
140        bool isTransparent(void) const;
141
142        /** Sets whether objects using this material will receive shadows.
143        @remarks
144            This method allows a material to opt out of receiving shadows, if
145            it would otherwise do so. Shadows will not be cast on any objects
146            unless the scene is set up to support shadows
147            (@see SceneManager::setShadowTechnique), and not all techniques cast
148            shadows on all objects. In any case, if you have a need to prevent
149            shadows being received by material, this is the method you call to
150            do it.
151        @note
152            Transparent materials never receive shadows despite this setting.
153            The default is to receive shadows.
154        */
155        void setReceiveShadows(bool enabled) { mReceiveShadows = enabled; }
156        /** Returns whether or not objects using this material will receive shadows. */
157        bool getReceiveShadows(void) const { return mReceiveShadows; }
158
159                /** Sets whether objects using this material be classified as opaque to the shadow caster system.
160                @remarks
161                This method allows a material to cast a shadow, even if it is transparent.
162                By default, transparent materials neither cast nor receive shadows. Shadows
163                will not be cast on any objects unless the scene is set up to support shadows
164                (@see SceneManager::setShadowTechnique), and not all techniques cast
165                shadows on all objects.
166                */
167                void setTransparencyCastsShadows(bool enabled) { mTransparencyCastsShadows = enabled; }
168                /** Returns whether or not objects using this material be classified as opaque to the shadow caster system. */
169                bool getTransparencyCastsShadows(void) const { return mTransparencyCastsShadows; }
170
171        /** Creates a new Technique for this Material.
172        @remarks
173            A Technique is a single way of rendering geometry in order to achieve the effect
174            you are intending in a material. There are many reason why you would want more than
175            one - the main one being to handle variable graphics card abilities; you might have
176            one technique which is impressive but only runs on 4th-generation graphics cards,
177            for example. In this case you will want to create at least one fallback Technique.
178            OGRE will work out which Techniques a card can support and pick the best one.
179        @par
180            If multiple Techniques are available, the order in which they are created is
181            important - the engine will consider lower-indexed Techniques to be preferable
182            to higher-indexed Techniques, ie when asked for the 'best' technique it will
183            return the first one in the technique list which is supported by the hardware.
184        */
185        Technique* createTechnique(void);
186        /** Gets the indexed technique. */
187        Technique* getTechnique(unsigned short index);
188                /** Retrieves the number of techniques. */
189        unsigned short getNumTechniques(void) const;
190        /** Removes the technique at the given index. */               
191        void removeTechnique(unsigned short index);             
192        /** Removes all the techniques in this Material. */
193        void removeAllTechniques(void);
194        typedef VectorIterator<Techniques> TechniqueIterator;
195        /** Get an iterator over the Techniques in this Material. */
196        TechniqueIterator getTechniqueIterator(void);
197        /** Gets an iterator over all the Techniques which are supported by the current card.
198        @remarks
199            The supported technique list is only available after this material has been compiled,
200            which typically happens on loading the material. Therefore, if this method returns
201            an empty list, try calling Material::load.
202        */
203        TechniqueIterator getSupportedTechniqueIterator(void);
204               
205                /** Gets the indexed supported technique. */
206        Technique* getSupportedTechnique(unsigned short index);
207                /** Retrieves the number of supported techniques. */
208        unsigned short getNumSupportedTechniques(void) const;
209
210        /** Gets the number of levels-of-detail this material has, based on
211            Technique::setLodIndex.
212        @remarks
213            Note that this will not be up to date until the material has been compiled.
214        */
215        unsigned short getNumLodLevels(void) const {
216            return static_cast<unsigned short>(mBestTechniqueList.size()); }
217
218        /** Gets the best supported technique.
219        @remarks
220            This method returns the lowest-index supported Technique in this material
221            (since lower-indexed Techniques are considered to be better than higher-indexed
222            ones).
223        @par
224            The best supported technique is only available after this material has been compiled,
225            which typically happens on loading the material. Therefore, if this method returns
226            NULL, try calling Material::load.
227                @param lodIndex The material lod index to use
228        */
229        Technique* getBestTechnique(unsigned short lodIndex = 0);
230
231
232        /** Creates a new copy of this material with the same settings but a new name.
233                @param newName The name for the cloned material
234                @param changeGroup If true, the resource group of the clone is changed
235                @param newGroup Only required if changeGroup is true; the new group to assign
236        */
237        MaterialPtr clone(const String& newName, bool changeGroup = false,
238                        const String& newGroup = StringUtil::BLANK) const;
239
240        /** Copies the details of this material into another, preserving the target's handle and name
241        (unlike operator=) but copying everything else.
242        @param mat Weak reference to material which will receive this material's settings.
243        */
244        void copyDetailsTo(MaterialPtr& mat) const;
245
246        /** 'Compiles' this Material.
247        @remarks
248            Compiling a material involves determining which Techniques are supported on the
249            card on which OGRE is currently running, and for fixed-function Passes within those
250            Techniques, splitting the passes down where they contain more TextureUnitState
251            instances than the current card has texture units.
252        @par
253            This process is automatically done when the Material is loaded, but may be
254            repeated if you make some procedural changes.
255        @param
256            autoManageTextureUnits If true, when a fixed function pass has too many TextureUnitState
257                entries than the card has texture units, the Pass in question will be split into
258                more than one Pass in order to emulate the Pass. If you set this to false and
259                this situation arises, an Exception will be thrown.
260        */
261        void compile(bool autoManageTextureUnits = true);
262
263        // -------------------------------------------------------------------------------
264        // The following methods are to make migration from previous versions simpler
265        // and to make code easier to write when dealing with simple materials
266        // They set the properties which have been moved to Pass for all Techniques and all Passes
267
268        /** Sets the ambient colour reflectance properties for every Pass in every Technique.
269        @note
270            This property has been moved to the Pass class, which is accessible via the
271            Technique. For simplicity, this method allows you to set these properties for
272            every current Technique, and for every current Pass within those Techniques. If
273            you need more precision, retrieve the Technique and Pass instances and set the
274            property there.
275        @see Pass::setAmbient
276        */
277        void setAmbient(Real red, Real green, Real blue);
278
279        /** Sets the ambient colour reflectance properties for every Pass in every Technique.
280        @note
281            This property has been moved to the Pass class, which is accessible via the
282            Technique. For simplicity, this method allows you to set these properties for
283            every current Technique, and for every current Pass within those Techniques. If
284            you need more precision, retrieve the Technique and Pass instances and set the
285            property there.
286        @see Pass::setAmbient
287        */
288        void setAmbient(const ColourValue& ambient);
289
290        /** Sets the diffuse colour reflectance properties of every Pass in every Technique.
291        @note
292            This property has been moved to the Pass class, which is accessible via the
293            Technique. For simplicity, this method allows you to set these properties for
294            every current Technique, and for every current Pass within those Techniques. If
295            you need more precision, retrieve the Technique and Pass instances and set the
296            property there.
297        @see Pass::setDiffuse
298        */
299        void setDiffuse(Real red, Real green, Real blue, Real alpha);
300
301        /** Sets the diffuse colour reflectance properties of every Pass in every Technique.
302        @note
303            This property has been moved to the Pass class, which is accessible via the
304            Technique. For simplicity, this method allows you to set these properties for
305            every current Technique, and for every current Pass within those Techniques. If
306            you need more precision, retrieve the Technique and Pass instances and set the
307            property there.
308        @see Pass::setDiffuse
309        */
310        void setDiffuse(const ColourValue& diffuse);
311
312        /** Sets the specular colour reflectance properties of every Pass in every Technique.
313        @note
314            This property has been moved to the Pass class, which is accessible via the
315            Technique. For simplicity, this method allows you to set these properties for
316            every current Technique, and for every current Pass within those Techniques. If
317            you need more precision, retrieve the Technique and Pass instances and set the
318            property there.
319        @see Pass::setSpecular
320        */
321        void setSpecular(Real red, Real green, Real blue, Real alpha);
322
323        /** Sets the specular colour reflectance properties of every Pass in every Technique.
324        @note
325            This property has been moved to the Pass class, which is accessible via the
326            Technique. For simplicity, this method allows you to set these properties for
327            every current Technique, and for every current Pass within those Techniques. If
328            you need more precision, retrieve the Technique and Pass instances and set the
329            property there.
330        @see Pass::setSpecular
331        */
332        void setSpecular(const ColourValue& specular);
333
334        /** Sets the shininess properties of every Pass in every Technique.
335        @note
336            This property has been moved to the Pass class, which is accessible via the
337            Technique. For simplicity, this method allows you to set these properties for
338            every current Technique, and for every current Pass within those Techniques. If
339            you need more precision, retrieve the Technique and Pass instances and set the
340            property there.
341        @see Pass::setShininess
342        */
343        void setShininess(Real val);
344
345        /** Sets the amount of self-illumination of every Pass in every Technique.
346        @note
347            This property has been moved to the Pass class, which is accessible via the
348            Technique. For simplicity, this method allows you to set these properties for
349            every current Technique, and for every current Pass within those Techniques. If
350            you need more precision, retrieve the Technique and Pass instances and set the
351            property there.
352        @see Pass::setSelfIllumination
353        */
354        void setSelfIllumination(Real red, Real green, Real blue);
355
356        /** Sets the amount of self-illumination of every Pass in every Technique.
357        @note
358            This property has been moved to the Pass class, which is accessible via the
359            Technique. For simplicity, this method allows you to set these properties for
360            every current Technique, and for every current Pass within those Techniques. If
361            you need more precision, retrieve the Technique and Pass instances and set the
362            property there.
363        @see Pass::setSelfIllumination
364        */
365        void setSelfIllumination(const ColourValue& selfIllum);
366
367                /** Sets whether or not each Pass renders with depth-buffer checking on or not.
368        @note
369            This property has been moved to the Pass class, which is accessible via the
370            Technique. For simplicity, this method allows you to set these properties for
371            every current Technique, and for every current Pass within those Techniques. If
372            you need more precision, retrieve the Technique and Pass instances and set the
373            property there.
374        @see Pass::setDepthCheckEnabled
375        */
376        void setDepthCheckEnabled(bool enabled);
377
378        /** Sets whether or not each Pass renders with depth-buffer writing on or not.
379        @note
380            This property has been moved to the Pass class, which is accessible via the
381            Technique. For simplicity, this method allows you to set these properties for
382            every current Technique, and for every current Pass within those Techniques. If
383            you need more precision, retrieve the Technique and Pass instances and set the
384            property there.
385        @see Pass::setDepthWriteEnabled
386        */
387        void setDepthWriteEnabled(bool enabled);
388
389        /** Sets the function used to compare depth values when depth checking is on.
390        @note
391            This property has been moved to the Pass class, which is accessible via the
392            Technique. For simplicity, this method allows you to set these properties for
393            every current Technique, and for every current Pass within those Techniques. If
394            you need more precision, retrieve the Technique and Pass instances and set the
395            property there.
396        @see Pass::setDepthFunction
397        */
398        void setDepthFunction( CompareFunction func );
399
400                /** Sets whether or not colour buffer writing is enabled for each Pass.
401        @note
402            This property has been moved to the Pass class, which is accessible via the
403            Technique. For simplicity, this method allows you to set these properties for
404            every current Technique, and for every current Pass within those Techniques. If
405            you need more precision, retrieve the Technique and Pass instances and set the
406            property there.
407        @see Pass::setColourWriteEnabled
408                */
409                void setColourWriteEnabled(bool enabled);
410
411        /** Sets the culling mode for each pass  based on the 'vertex winding'.
412        @note
413            This property has been moved to the Pass class, which is accessible via the
414            Technique. For simplicity, this method allows you to set these properties for
415            every current Technique, and for every current Pass within those Techniques. If
416            you need more precision, retrieve the Technique and Pass instances and set the
417            property there.
418        @see Pass::setCullingMode
419        */
420        void setCullingMode( CullingMode mode );
421
422        /** Sets the manual culling mode, performed by CPU rather than hardware.
423        @note
424            This property has been moved to the Pass class, which is accessible via the
425            Technique. For simplicity, this method allows you to set these properties for
426            every current Technique, and for every current Pass within those Techniques. If
427            you need more precision, retrieve the Technique and Pass instances and set the
428            property there.
429        @see Pass::setManualCullingMode
430        */
431        void setManualCullingMode( ManualCullingMode mode );
432
433        /** Sets whether or not dynamic lighting is enabled for every Pass.
434        @note
435            This property has been moved to the Pass class, which is accessible via the
436            Technique. For simplicity, this method allows you to set these properties for
437            every current Technique, and for every current Pass within those Techniques. If
438            you need more precision, retrieve the Technique and Pass instances and set the
439            property there.
440        @see Pass::setLightingEnabled
441        */
442        void setLightingEnabled(bool enabled);
443
444        /** Sets the type of light shading required
445        @note
446            This property has been moved to the Pass class, which is accessible via the
447            Technique. For simplicity, this method allows you to set these properties for
448            every current Technique, and for every current Pass within those Techniques. If
449            you need more precision, retrieve the Technique and Pass instances and set the
450            property there.
451        @see Pass::setShadingMode
452        */
453        void setShadingMode( ShadeOptions mode );
454
455        /** Sets the fogging mode applied to each pass.
456        @note
457            This property has been moved to the Pass class, which is accessible via the
458            Technique. For simplicity, this method allows you to set these properties for
459            every current Technique, and for every current Pass within those Techniques. If
460            you need more precision, retrieve the Technique and Pass instances and set the
461            property there.
462        @see Pass::setFog
463        */
464        void setFog(
465            bool overrideScene,
466            FogMode mode = FOG_NONE,
467            const ColourValue& colour = ColourValue::White,
468            Real expDensity = 0.001, Real linearStart = 0.0, Real linearEnd = 1.0 );
469
470        /** Sets the depth bias to be used for each Pass.
471        @note
472            This property has been moved to the Pass class, which is accessible via the
473            Technique. For simplicity, this method allows you to set these properties for
474            every current Technique, and for every current Pass within those Techniques. If
475            you need more precision, retrieve the Technique and Pass instances and set the
476            property there.
477        @see Pass::setDepthBias
478        */
479        void setDepthBias(ushort bias);
480
481        /** Set texture filtering for every texture unit in every Technique and Pass
482        @note
483            This property has been moved to the TextureUnitState class, which is accessible via the
484            Technique and Pass. For simplicity, this method allows you to set these properties for
485            every current TeextureUnitState, If you need more precision, retrieve the Technique,
486            Pass and TextureUnitState instances and set the property there.
487        @see TextureUnitState::setTextureFiltering
488        */
489        void setTextureFiltering(TextureFilterOptions filterType);
490        /** Sets the anisotropy level to be used for all textures.
491        @note
492            This property has been moved to the TextureUnitState class, which is accessible via the
493            Technique and Pass. For simplicity, this method allows you to set these properties for
494            every current TeextureUnitState, If you need more precision, retrieve the Technique,
495            Pass and TextureUnitState instances and set the property there.
496        @see TextureUnitState::setTextureAnisotropy
497        */
498        void setTextureAnisotropy(int maxAniso);
499
500        /** Sets the kind of blending every pass has with the existing contents of the scene.
501        @note
502            This property has been moved to the Pass class, which is accessible via the
503            Technique. For simplicity, this method allows you to set these properties for
504            every current Technique, and for every current Pass within those Techniques. If
505            you need more precision, retrieve the Technique and Pass instances and set the
506            property there.
507        @see Pass::setSceneBlending
508        */
509        void setSceneBlending( const SceneBlendType sbt );
510
511        /** Allows very fine control of blending every Pass with the existing contents of the scene.
512        @note
513            This property has been moved to the Pass class, which is accessible via the
514            Technique. For simplicity, this method allows you to set these properties for
515            every current Technique, and for every current Pass within those Techniques. If
516            you need more precision, retrieve the Technique and Pass instances and set the
517            property there.
518        @see Pass::setSceneBlending
519        */
520        void setSceneBlending( const SceneBlendFactor sourceFactor, const SceneBlendFactor destFactor);
521
522
523        /** Tells the material that it needs recompilation. */
524        void _notifyNeedsRecompile(void);
525
526        /** Sets the distance at which level-of-detail (LOD) levels come into effect.
527        @remarks
528            You should only use this if you have assigned LOD indexes to the Technique
529            instances attached to this Material. If you have done so, you should call this
530            method to determine the distance at which the lowe levels of detail kick in.
531            The decision about what distance is actually used is a combination of this
532            and the LOD bias applied to both the current Camera and the current Entity.
533        @param lodDistances A vector of Reals which indicate the distance at which to
534            switch to lower details. They are listed in LOD index order, starting at index
535            1 (ie the first level down from the highest level 0, which automatically applies
536            from a distance of 0).
537        */
538        void setLodLevels(const LodDistanceList& lodDistances);
539        /** Gets an iterator over the list of distances at which each LOD comes into effect.
540        @remarks
541            Note that the iterator returned from this method is not totally anagolous to
542            the one passed in by calling setLodLevels - the list includes a zero
543            entry at the start (since the highest LOD starts at distance 0), and
544            the other distances are held as their squared value for efficiency.
545        */
546        LodDistanceIterator getLodDistanceIterator(void) const;
547
548        /** Gets the LOD index to use at the given distance. */
549        unsigned short getLodIndex(Real d) const;
550        /** Gets the LOD index to use at the given squared distance. */
551        unsigned short getLodIndexSquaredDepth(Real squaredDepth) const;
552
553        /** @copydoc Resource::touch
554        */
555        void touch(void)
556        {
557            if (mCompilationRequired)
558                compile();
559            // call superclass
560            Resource::touch();
561        }
562
563            /** Gets the compilation status of the material.
564        @return True if the material needs recompilation.
565        */
566            bool getCompilationRequired() const
567            {
568                    return mCompilationRequired;
569            }
570
571
572    };
573
574        /** Specialisation of SharedPtr to allow SharedPtr to be assigned to MaterialPtr
575        @note Has to be a subclass since we need operator=.
576        We could templatise this instead of repeating per Resource subclass,
577        except to do so requires a form VC6 does not support i.e.
578        ResourceSubclassPtr<T> : public SharedPtr<T>
579        */
580        class _OgreExport MaterialPtr : public SharedPtr<Material>
581        {
582        public:
583                MaterialPtr() : SharedPtr<Material>() {}
584                explicit MaterialPtr(Material* rep) : SharedPtr<Material>(rep) {}
585                MaterialPtr(const MaterialPtr& r) : SharedPtr<Material>(r) {}
586                MaterialPtr(const ResourcePtr& r) : SharedPtr<Material>()
587                {
588                        // lock & copy other mutex pointer
589                        OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
590                        OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
591                        pRep = static_cast<Material*>(r.getPointer());
592                        pUseCount = r.useCountPointer();
593                        if (pUseCount)
594                        {
595                                ++(*pUseCount);
596                        }
597                }
598
599                /// Operator used to convert a ResourcePtr to a MaterialPtr
600                MaterialPtr& operator=(const ResourcePtr& r)
601                {
602                        if (pRep == static_cast<Material*>(r.getPointer()))
603                                return *this;
604                        release();
605                        // lock & copy other mutex pointer
606                        OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
607                        OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
608                        pRep = static_cast<Material*>(r.getPointer());
609                        pUseCount = r.useCountPointer();
610                        if (pUseCount)
611                        {
612                                ++(*pUseCount);
613                        }
614                        return *this;
615                }
616        };
617
618} //namespace
619
620#endif
Note: See TracBrowser for help on using the repository browser.