Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgrePanelGuiElement.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 
00026 #include "OgrePanelGuiElement.h"
00027 #include "OgreMaterial.h"
00028 #include "OgreTechnique.h"
00029 #include "OgrePass.h"
00030 #include "OgreStringConverter.h"
00031 #include "OgreHardwareBufferManager.h"
00032 
00033 namespace Ogre {
00034     //---------------------------------------------------------------------
00035     String PanelGuiElement::msTypeName = "Panel";
00036     PanelGuiElement::CmdTiling PanelGuiElement::msCmdTiling;
00037     PanelGuiElement::CmdTransparent PanelGuiElement::msCmdTransparent;
00038     //---------------------------------------------------------------------
00039     // vertex buffer bindings, set at compile time (we could look these up but no point)
00040     #define POSITION_BINDING 0
00041     #define TEXCOORD_BINDING 1
00042 
00043     //---------------------------------------------------------------------
00044     PanelGuiElement::PanelGuiElement(const String& name)
00045         : GuiContainer(name)
00046     {
00047         mTransparent = false;
00048         // Init tiling
00049         for (ushort i = 0; i < OGRE_MAX_TEXTURE_COORD_SETS; ++i)
00050         {
00051             mTileX[i] = 1.0f;
00052             mTileY[i] = 1.0f;
00053         }
00054 
00055         // Defer creation of texcoord buffer until we know how big it needs to be
00056         mNumTexCoordsInBuffer = 0;
00057 
00058         // No normals or colours
00059         if (createParamDictionary("PanelGuiElement"))
00060         {
00061             addBaseParameters();
00062         }
00063 
00064     }
00065     //---------------------------------------------------------------------
00066     PanelGuiElement::~PanelGuiElement()
00067     {
00068         delete mRenderOp.vertexData;
00069     }
00070     //---------------------------------------------------------------------
00071     void PanelGuiElement::initialise(void)
00072     {
00073         // Setup render op in advance
00074         mRenderOp.vertexData = new VertexData();
00075         // Vertex declaration: 1 position, add texcoords later depending on #layers
00076         // Create as separate buffers so we can lock & discard separately
00077         VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration;
00078         decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION);
00079 
00080         // Basic vertex data
00081         mRenderOp.vertexData->vertexStart = 0;
00082         mRenderOp.vertexData->vertexCount = 4;
00083 
00084         // Vertex buffer #1
00085         HardwareVertexBufferSharedPtr vbuf = 
00086             HardwareBufferManager::getSingleton().createVertexBuffer(
00087             decl->getVertexSize(POSITION_BINDING), mRenderOp.vertexData->vertexCount, 
00088             HardwareBuffer::HBU_STATIC_WRITE_ONLY// mostly static except during resizing
00089             );
00090         // Bind buffer
00091         mRenderOp.vertexData->vertexBufferBinding->setBinding(POSITION_BINDING, vbuf);
00092 
00093         // No indexes & issue as a strip
00094         mRenderOp.useIndexes = false;
00095         mRenderOp.operationType = RenderOperation::OT_TRIANGLE_STRIP;
00096     }
00097     //---------------------------------------------------------------------
00098     void PanelGuiElement::setTiling(Real x, Real y, ushort layer)
00099     {
00100         assert (layer < OGRE_MAX_TEXTURE_COORD_SETS);
00101         assert (x != 0 && y != 0);
00102 
00103         mTileX[layer] = x;
00104         mTileY[layer] = y;
00105 
00106         updateTextureGeometry();
00107 
00108     }
00109     //---------------------------------------------------------------------
00110     Real PanelGuiElement::getTileX(ushort layer) const
00111     {
00112         return mTileX[layer];
00113     }
00114     //---------------------------------------------------------------------
00115     Real PanelGuiElement::getTileY(ushort layer) const
00116     {
00117         return mTileY[layer];
00118     }
00119     //---------------------------------------------------------------------
00120     void PanelGuiElement::setTransparent(bool isTransparent)
00121     {
00122         mTransparent = isTransparent;
00123     }
00124     //---------------------------------------------------------------------
00125     bool PanelGuiElement::isTransparent(void) const
00126     {
00127         return mTransparent;
00128     }
00129     //---------------------------------------------------------------------
00130     const String& PanelGuiElement::getTypeName(void) const
00131     {
00132         return msTypeName;
00133     }
00134     //---------------------------------------------------------------------
00135     void PanelGuiElement::getRenderOperation(RenderOperation& op)
00136     {
00137         op = mRenderOp;
00138     }
00139     //---------------------------------------------------------------------
00140     void PanelGuiElement::setMaterialName(const String& matName)
00141     {
00142         GuiContainer::setMaterialName(matName);
00143         updateTextureGeometry();
00144     }
00145     //---------------------------------------------------------------------
00146     void PanelGuiElement::_updateRenderQueue(RenderQueue* queue)
00147     {
00148         if (mVisible)
00149         {
00150 
00151             if (!mTransparent && mpMaterial)
00152             {
00153                 GuiElement::_updateRenderQueue(queue);
00154             }
00155 
00156             // Also add children
00157             ChildIterator it = getChildIterator();
00158             while (it.hasMoreElements())
00159             {
00160                 // Give children ZOrder 1 higher than this
00161                 it.getNext()->_updateRenderQueue(queue);
00162             }
00163         }
00164     }
00165     //---------------------------------------------------------------------
00166     void PanelGuiElement::updatePositionGeometry(void)
00167     {
00168         /*
00169             0-----2
00170             |    /|
00171             |  /  |
00172             |/    |
00173             1-----3
00174         */
00175         Real left, right, top, bottom;
00176 
00177         /* Convert positions into -1, 1 coordinate space (homogenous clip space).
00178             - Left / right is simple range conversion
00179             - Top / bottom also need inverting since y is upside down - this means
00180               that top will end up greater than bottom and when computing texture
00181               coordinates, we have to flip the v-axis (ie. subtract the value from
00182               1.0 to get the actual correct value).
00183         */
00184         left = _getDerivedLeft() * 2 - 1;
00185         right = left + (mWidth * 2);
00186         top = -((_getDerivedTop() * 2) - 1);
00187         bottom =  top -  (mHeight * 2);
00188 
00189         HardwareVertexBufferSharedPtr vbuf = 
00190             mRenderOp.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING);
00191         Real* pPos = static_cast<Real*>(
00192             vbuf->lock(HardwareBuffer::HBL_DISCARD) );
00193         
00194         // Use -1 for Z position, furthest forward in homogenous clip space
00195         *pPos++ = left;
00196         *pPos++ = top;
00197         *pPos++ = -1;
00198 
00199         *pPos++ = left;
00200         *pPos++ = bottom;
00201         *pPos++ = -1;
00202 
00203         *pPos++ = right;
00204         *pPos++ = top;
00205         *pPos++ = -1;
00206 
00207         *pPos++ = right;
00208         *pPos++ = bottom;
00209         *pPos++ = -1;
00210         
00211         vbuf->unlock();
00212     }
00213     //---------------------------------------------------------------------
00214     void PanelGuiElement::updateTextureGeometry(void)
00215     {
00216         // Generate for as many texture layers as there are in material
00217         if (mpMaterial)
00218         {
00219             // Assume one technique and pass for the moment
00220             size_t numLayers = mpMaterial->getTechnique(0)->getPass(0)->getNumTextureUnitStates();
00221 
00222             VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration;
00223             // Check the number of texcoords we have in our buffer now
00224             if (mNumTexCoordsInBuffer > numLayers)
00225             {
00226                 // remove extras
00227                 for (size_t i = mNumTexCoordsInBuffer; i > numLayers; --i)
00228                 {
00229                     decl->removeElement(VES_TEXTURE_COORDINATES, i);
00230                 }
00231             }
00232             else if (mNumTexCoordsInBuffer < numLayers)
00233             {
00234                 // Add extra texcoord elements
00235                 size_t offset = VertexElement::getTypeSize(VET_FLOAT2) * mNumTexCoordsInBuffer;
00236                 for (size_t i = mNumTexCoordsInBuffer; i < numLayers; ++i)
00237                 {
00238                     decl->addElement(TEXCOORD_BINDING,
00239                         offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, i);
00240                     offset += VertexElement::getTypeSize(VET_FLOAT2);
00241                    
00242                 }
00243             }
00244 
00245             // if number of layers changed at all, we'll need to reallocate buffer
00246             if (mNumTexCoordsInBuffer != numLayers)
00247             {
00248                 // NB reference counting will take care of the old one if it exists
00249                 HardwareVertexBufferSharedPtr newbuf = 
00250                     HardwareBufferManager::getSingleton().createVertexBuffer(
00251                     decl->getVertexSize(TEXCOORD_BINDING), mRenderOp.vertexData->vertexCount, 
00252                     HardwareBuffer::HBU_STATIC_WRITE_ONLY // mostly static except during resizing
00253                     );
00254                 // Bind buffer, note this will unbind the old one and destroy the buffer it had
00255                 mRenderOp.vertexData->vertexBufferBinding->setBinding(TEXCOORD_BINDING, newbuf);
00256                 // Set num tex coords in use now
00257                 mNumTexCoordsInBuffer = numLayers;
00258             }
00259 
00260             // Get the tcoord buffer & lock
00261             HardwareVertexBufferSharedPtr vbuf = 
00262                 mRenderOp.vertexData->vertexBufferBinding->getBuffer(TEXCOORD_BINDING);
00263             Real* pVBStart = static_cast<Real*>(
00264                 vbuf->lock(HardwareBuffer::HBL_DISCARD) );
00265 
00266             size_t uvSize = VertexElement::getTypeSize(VET_FLOAT2) / sizeof(Real);
00267             size_t vertexSize = decl->getVertexSize(TEXCOORD_BINDING) / sizeof(Real);
00268             for (ushort i = 0; i < numLayers; ++i)
00269             {
00270                 // Calc upper tex coords
00271                 Real upperX = 1.0f * mTileX[i];
00272                 Real upperY = 1.0f * mTileY[i];
00273                 
00274                 /*
00275                     0-----2
00276                     |    /|
00277                     |  /  |
00278                     |/    |
00279                     1-----3
00280                 */
00281                 // Find start offset for this set
00282                 Real* pTex = pVBStart + (i * uvSize);
00283 
00284                 pTex[0] = 0.0f;
00285                 pTex[1] = 0.0f;
00286 
00287                 pTex += vertexSize; // jump by 1 vertex stride
00288                 pTex[0] = 0.0f;
00289                 pTex[1] = upperY;
00290 
00291                 pTex += vertexSize;
00292                 pTex[0] = upperX;
00293                 pTex[1] = 0.0f;
00294 
00295                 pTex += vertexSize;
00296                 pTex[0] = upperX;
00297                 pTex[1] = upperY;
00298             }
00299             vbuf->unlock();
00300         }
00301     }
00302     //-----------------------------------------------------------------------
00303     void PanelGuiElement::addBaseParameters(void)
00304     {
00305         GuiContainer::addBaseParameters();
00306         ParamDictionary* dict = getParamDictionary();
00307 
00308         dict->addParameter(ParameterDef("tiling", 
00309             "The number of times to repeat the background texture."
00310             , PT_STRING),
00311             &msCmdTiling);
00312 
00313         dict->addParameter(ParameterDef("transparent", 
00314             "Sets whether the panel is transparent, i.e. invisible itself "
00315             "but it's contents are still displayed."
00316             , PT_BOOL),
00317             &msCmdTransparent);
00318     }
00319     //-----------------------------------------------------------------------
00320     // Command objects
00321     //-----------------------------------------------------------------------
00322     String PanelGuiElement::CmdTiling::doGet(const void* target) const
00323     {
00324         // NB only returns 1st layer tiling
00325         String ret = "0 " + StringConverter::toString(
00326             static_cast<const PanelGuiElement*>(target)->getTileX() );
00327         ret += " " + StringConverter::toString(
00328             static_cast<const PanelGuiElement*>(target)->getTileY() );
00329         return ret;
00330     }
00331     void PanelGuiElement::CmdTiling::doSet(void* target, const String& val)
00332     {
00333         // 3 params: <layer> <x_tile> <y_tile>
00334         // Param count is validated higher up
00335         std::vector<String> vec = val.split();
00336         ushort layer = (ushort)StringConverter::parseUnsignedInt(vec[0]);
00337         Real x_tile = StringConverter::parseReal(vec[1]);
00338         Real y_tile = StringConverter::parseReal(vec[2]);
00339 
00340         static_cast<PanelGuiElement*>(target)->setTiling(x_tile, y_tile, layer);
00341     }
00342     //-----------------------------------------------------------------------
00343     String PanelGuiElement::CmdTransparent::doGet(const void* target) const
00344     {
00345         return StringConverter::toString(
00346             static_cast<const PanelGuiElement*>(target)->isTransparent() );
00347     }
00348     void PanelGuiElement::CmdTransparent::doSet(void* target, const String& val)
00349     {
00350         static_cast<PanelGuiElement*>(target)->setTransparent(
00351             StringConverter::parseBool(val));
00352     }
00353 
00354 
00355 }
00356 
00357 
00358 

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:20 2004