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

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:37 2004