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 Fri May 14 23:22:30 2004