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