[1] | 1 | /* |
---|
| 2 | ----------------------------------------------------------------------------- |
---|
| 3 | This source file is part of OGRE |
---|
| 4 | (Object-oriented Graphics Rendering Engine) |
---|
| 5 | For the latest info, see http://www.ogre3d.org/ |
---|
| 6 | |
---|
| 7 | Copyright (c) 2000-2006 Torus Knot Software Ltd |
---|
| 8 | Also see acknowledgements in Readme.html |
---|
| 9 | |
---|
| 10 | This program is free software; you can redistribute it and/or modify it under |
---|
| 11 | the terms of the GNU Lesser General Public License as published by the Free Software |
---|
| 12 | Foundation; either version 2 of the License, or (at your option) any later |
---|
| 13 | version. |
---|
| 14 | |
---|
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT |
---|
| 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
---|
| 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
---|
| 18 | |
---|
| 19 | You should have received a copy of the GNU Lesser General Public License along with |
---|
| 20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
---|
| 21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to |
---|
| 22 | http://www.gnu.org/copyleft/lesser.txt. |
---|
| 23 | |
---|
| 24 | You may alternatively use this source under the terms of a specific version of |
---|
| 25 | the OGRE Unrestricted License provided you have obtained such a license from |
---|
| 26 | Torus Knot Software Ltd. |
---|
| 27 | ----------------------------------------------------------------------------- |
---|
| 28 | */ |
---|
| 29 | #include "OgreStableHeaders.h" |
---|
| 30 | #include "OgreRibbonTrail.h" |
---|
| 31 | #include "OgreMath.h" |
---|
| 32 | #include "OgreException.h" |
---|
| 33 | #include "OgreSceneNode.h" |
---|
| 34 | #include "OgreStringConverter.h" |
---|
| 35 | |
---|
| 36 | namespace Ogre |
---|
| 37 | { |
---|
| 38 | namespace |
---|
| 39 | { |
---|
| 40 | /** Controller value for pass frame time to RibbonTrail |
---|
| 41 | */ |
---|
| 42 | class _OgrePrivate TimeControllerValue : public ControllerValue<Real> |
---|
| 43 | { |
---|
| 44 | protected: |
---|
| 45 | RibbonTrail* mTrail; |
---|
| 46 | public: |
---|
| 47 | TimeControllerValue(RibbonTrail* r) { mTrail = r; } |
---|
| 48 | |
---|
| 49 | Real getValue(void) const { return 0; }// not a source |
---|
| 50 | void setValue(Real value) { mTrail->_timeUpdate(value); } |
---|
| 51 | }; |
---|
| 52 | } |
---|
| 53 | //----------------------------------------------------------------------- |
---|
| 54 | //----------------------------------------------------------------------- |
---|
| 55 | RibbonTrail::RibbonTrail(const String& name, size_t maxElements, |
---|
| 56 | size_t numberOfChains, bool useTextureCoords, bool useColours) |
---|
| 57 | :BillboardChain(name, maxElements, 0, useTextureCoords, useColours, true), |
---|
| 58 | mFadeController(0) |
---|
| 59 | { |
---|
| 60 | setTrailLength(100); |
---|
| 61 | setNumberOfChains(numberOfChains); |
---|
| 62 | mTimeControllerValue = ControllerValueRealPtr(new TimeControllerValue(this)); |
---|
| 63 | |
---|
| 64 | // use V as varying texture coord, so we can use 1D textures to 'smear' |
---|
| 65 | setTextureCoordDirection(TCD_V); |
---|
| 66 | |
---|
| 67 | |
---|
| 68 | } |
---|
| 69 | //----------------------------------------------------------------------- |
---|
| 70 | RibbonTrail::~RibbonTrail() |
---|
| 71 | { |
---|
| 72 | // Detach listeners |
---|
| 73 | for (NodeList::iterator i = mNodeList.begin(); i != mNodeList.end(); ++i) |
---|
| 74 | { |
---|
| 75 | (*i)->setListener(0); |
---|
| 76 | } |
---|
| 77 | |
---|
| 78 | if (mFadeController) |
---|
| 79 | { |
---|
| 80 | // destroy controller |
---|
| 81 | ControllerManager::getSingleton().destroyController(mFadeController); |
---|
| 82 | } |
---|
| 83 | |
---|
| 84 | } |
---|
| 85 | //----------------------------------------------------------------------- |
---|
| 86 | void RibbonTrail::addNode(Node* n) |
---|
| 87 | { |
---|
| 88 | if (mNodeList.size() == mChainCount) |
---|
| 89 | { |
---|
| 90 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 91 | mName + " cannot monitor any more nodes, chain count exceeded", |
---|
| 92 | "RibbonTrail::addNode"); |
---|
| 93 | } |
---|
| 94 | if (n->getListener()) |
---|
| 95 | { |
---|
| 96 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 97 | mName + " cannot monitor node " + n->getName() + " since it already has a listener.", |
---|
| 98 | "RibbonTrail::addNode"); |
---|
| 99 | } |
---|
| 100 | |
---|
| 101 | // initialise the chain |
---|
| 102 | resetTrail(mNodeList.size(), n); |
---|
| 103 | |
---|
| 104 | mNodeList.push_back(n); |
---|
| 105 | n->setListener(this); |
---|
| 106 | |
---|
| 107 | } |
---|
| 108 | //----------------------------------------------------------------------- |
---|
| 109 | void RibbonTrail::removeNode(Node* n) |
---|
| 110 | { |
---|
| 111 | NodeList::iterator i = std::find(mNodeList.begin(), mNodeList.end(), n); |
---|
| 112 | if (i != mNodeList.end()) |
---|
| 113 | { |
---|
| 114 | n->setListener(0); |
---|
| 115 | mNodeList.erase(i); |
---|
| 116 | } |
---|
| 117 | } |
---|
| 118 | //----------------------------------------------------------------------- |
---|
| 119 | RibbonTrail::NodeIterator |
---|
| 120 | RibbonTrail::getNodeIterator(void) const |
---|
| 121 | { |
---|
| 122 | return NodeIterator(mNodeList.begin(), mNodeList.end()); |
---|
| 123 | } |
---|
| 124 | //----------------------------------------------------------------------- |
---|
| 125 | void RibbonTrail::setTrailLength(Real len) |
---|
| 126 | { |
---|
| 127 | mTrailLength = len; |
---|
| 128 | mElemLength = mTrailLength / mMaxElementsPerChain; |
---|
| 129 | mSquaredElemLength = mElemLength * mElemLength; |
---|
| 130 | } |
---|
| 131 | //----------------------------------------------------------------------- |
---|
| 132 | void RibbonTrail::setMaxChainElements(size_t maxElements) |
---|
| 133 | { |
---|
| 134 | BillboardChain::setMaxChainElements(maxElements); |
---|
| 135 | mElemLength = mTrailLength / mMaxElementsPerChain; |
---|
| 136 | mSquaredElemLength = mElemLength * mElemLength; |
---|
| 137 | |
---|
| 138 | resetAllTrails(); |
---|
| 139 | } |
---|
| 140 | //----------------------------------------------------------------------- |
---|
| 141 | void RibbonTrail::setNumberOfChains(size_t numChains) |
---|
| 142 | { |
---|
| 143 | if (numChains < mNodeList.size()) |
---|
| 144 | { |
---|
| 145 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 146 | "Can't shrink the number of chains less than number of tracking nodes", |
---|
| 147 | "RibbonTrail::setNumberOfChains"); |
---|
| 148 | } |
---|
| 149 | |
---|
| 150 | BillboardChain::setNumberOfChains(numChains); |
---|
| 151 | |
---|
| 152 | mInitialColour.resize(numChains, ColourValue::White); |
---|
| 153 | mDeltaColour.resize(numChains, ColourValue::ZERO); |
---|
| 154 | mInitialWidth.resize(numChains, 10); |
---|
| 155 | mDeltaWidth.resize(numChains, 0); |
---|
| 156 | |
---|
| 157 | resetAllTrails(); |
---|
| 158 | } |
---|
| 159 | //----------------------------------------------------------------------- |
---|
| 160 | void RibbonTrail::clearChain(size_t chainIndex) |
---|
| 161 | { |
---|
| 162 | BillboardChain::clearChain(chainIndex); |
---|
| 163 | |
---|
| 164 | // Reset if we are tracking for this chain |
---|
| 165 | if (chainIndex < mNodeList.size()) |
---|
| 166 | { |
---|
| 167 | resetTrail(chainIndex, mNodeList[chainIndex]); |
---|
| 168 | } |
---|
| 169 | } |
---|
| 170 | //----------------------------------------------------------------------- |
---|
| 171 | void RibbonTrail::setInitialColour(size_t chainIndex, const ColourValue& col) |
---|
| 172 | { |
---|
| 173 | setInitialColour(chainIndex, col.r, col.g, col.b, col.a); |
---|
| 174 | } |
---|
| 175 | //----------------------------------------------------------------------- |
---|
| 176 | void RibbonTrail::setInitialColour(size_t chainIndex, Real r, Real g, Real b, Real a) |
---|
| 177 | { |
---|
| 178 | if (chainIndex >= mChainCount) |
---|
| 179 | { |
---|
| 180 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 181 | "chainIndex out of bounds", "RibbonTrail::setInitialColour"); |
---|
| 182 | } |
---|
| 183 | mInitialColour[chainIndex].r = r; |
---|
| 184 | mInitialColour[chainIndex].g = g; |
---|
| 185 | mInitialColour[chainIndex].b = b; |
---|
| 186 | mInitialColour[chainIndex].a = a; |
---|
| 187 | } |
---|
| 188 | //----------------------------------------------------------------------- |
---|
| 189 | const ColourValue& RibbonTrail::getInitialColour(size_t chainIndex) const |
---|
| 190 | { |
---|
| 191 | if (chainIndex >= mChainCount) |
---|
| 192 | { |
---|
| 193 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 194 | "chainIndex out of bounds", "RibbonTrail::getInitialColour"); |
---|
| 195 | } |
---|
| 196 | return mInitialColour[chainIndex]; |
---|
| 197 | } |
---|
| 198 | //----------------------------------------------------------------------- |
---|
| 199 | void RibbonTrail::setInitialWidth(size_t chainIndex, Real width) |
---|
| 200 | { |
---|
| 201 | if (chainIndex >= mChainCount) |
---|
| 202 | { |
---|
| 203 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 204 | "chainIndex out of bounds", "RibbonTrail::setInitialWidth"); |
---|
| 205 | } |
---|
| 206 | mInitialWidth[chainIndex] = width; |
---|
| 207 | } |
---|
| 208 | //----------------------------------------------------------------------- |
---|
| 209 | Real RibbonTrail::getInitialWidth(size_t chainIndex) const |
---|
| 210 | { |
---|
| 211 | if (chainIndex >= mChainCount) |
---|
| 212 | { |
---|
| 213 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 214 | "chainIndex out of bounds", "RibbonTrail::getInitialWidth"); |
---|
| 215 | } |
---|
| 216 | return mInitialWidth[chainIndex]; |
---|
| 217 | } |
---|
| 218 | //----------------------------------------------------------------------- |
---|
| 219 | void RibbonTrail::setColourChange(size_t chainIndex, const ColourValue& valuePerSecond) |
---|
| 220 | { |
---|
| 221 | setColourChange(chainIndex, |
---|
| 222 | valuePerSecond.r, valuePerSecond.g, valuePerSecond.b, valuePerSecond.a); |
---|
| 223 | } |
---|
| 224 | //----------------------------------------------------------------------- |
---|
| 225 | void RibbonTrail::setColourChange(size_t chainIndex, Real r, Real g, Real b, Real a) |
---|
| 226 | { |
---|
| 227 | if (chainIndex >= mChainCount) |
---|
| 228 | { |
---|
| 229 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 230 | "chainIndex out of bounds", "RibbonTrail::setColourChange"); |
---|
| 231 | } |
---|
| 232 | mDeltaColour[chainIndex].r = r; |
---|
| 233 | mDeltaColour[chainIndex].g = g; |
---|
| 234 | mDeltaColour[chainIndex].b = b; |
---|
| 235 | mDeltaColour[chainIndex].a = a; |
---|
| 236 | |
---|
| 237 | manageController(); |
---|
| 238 | |
---|
| 239 | } |
---|
| 240 | //----------------------------------------------------------------------- |
---|
| 241 | const ColourValue& RibbonTrail::getColourChange(size_t chainIndex) const |
---|
| 242 | { |
---|
| 243 | if (chainIndex >= mChainCount) |
---|
| 244 | { |
---|
| 245 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 246 | "chainIndex out of bounds", "RibbonTrail::getColourChange"); |
---|
| 247 | } |
---|
| 248 | return mDeltaColour[chainIndex]; |
---|
| 249 | } |
---|
| 250 | //----------------------------------------------------------------------- |
---|
| 251 | void RibbonTrail::setWidthChange(size_t chainIndex, Real widthDeltaPerSecond) |
---|
| 252 | { |
---|
| 253 | if (chainIndex >= mChainCount) |
---|
| 254 | { |
---|
| 255 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 256 | "chainIndex out of bounds", "RibbonTrail::setWidthChange"); |
---|
| 257 | } |
---|
| 258 | mDeltaWidth[chainIndex] = widthDeltaPerSecond; |
---|
| 259 | manageController(); |
---|
| 260 | } |
---|
| 261 | //----------------------------------------------------------------------- |
---|
| 262 | Real RibbonTrail::getWidthChange(size_t chainIndex) const |
---|
| 263 | { |
---|
| 264 | if (chainIndex >= mChainCount) |
---|
| 265 | { |
---|
| 266 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 267 | "chainIndex out of bounds", "RibbonTrail::getWidthChange"); |
---|
| 268 | } |
---|
| 269 | return mDeltaWidth[chainIndex]; |
---|
| 270 | |
---|
| 271 | } |
---|
| 272 | //----------------------------------------------------------------------- |
---|
| 273 | void RibbonTrail::manageController(void) |
---|
| 274 | { |
---|
| 275 | bool needController = false; |
---|
| 276 | for (size_t i = 0; i < mChainCount; ++i) |
---|
| 277 | { |
---|
| 278 | if (mDeltaWidth[i] != 0 || mDeltaColour[i] != ColourValue::ZERO) |
---|
| 279 | { |
---|
| 280 | needController = true; |
---|
| 281 | break; |
---|
| 282 | } |
---|
| 283 | } |
---|
| 284 | if (!mFadeController && needController) |
---|
| 285 | { |
---|
| 286 | // Set up fading via frame time controller |
---|
| 287 | ControllerManager& mgr = ControllerManager::getSingleton(); |
---|
| 288 | mFadeController = mgr.createFrameTimePassthroughController(mTimeControllerValue); |
---|
| 289 | } |
---|
| 290 | else if (mFadeController && !needController) |
---|
| 291 | { |
---|
| 292 | // destroy controller |
---|
| 293 | ControllerManager::getSingleton().destroyController(mFadeController); |
---|
| 294 | mFadeController = 0; |
---|
| 295 | } |
---|
| 296 | |
---|
| 297 | } |
---|
| 298 | //----------------------------------------------------------------------- |
---|
| 299 | void RibbonTrail::nodeUpdated(const Node* node) |
---|
| 300 | { |
---|
| 301 | |
---|
| 302 | for (size_t idx = 0; idx < mNodeList.size(); ++idx) |
---|
| 303 | { |
---|
| 304 | if (mNodeList[idx] == node) |
---|
| 305 | { |
---|
| 306 | updateTrail(idx, node); |
---|
| 307 | break; |
---|
| 308 | } |
---|
| 309 | } |
---|
| 310 | } |
---|
| 311 | //----------------------------------------------------------------------- |
---|
| 312 | void RibbonTrail::nodeDestroyed(const Node* node) |
---|
| 313 | { |
---|
| 314 | removeNode(const_cast<Node*>(node)); |
---|
| 315 | |
---|
| 316 | } |
---|
| 317 | //----------------------------------------------------------------------- |
---|
| 318 | void RibbonTrail::updateTrail(size_t index, const Node* node) |
---|
| 319 | { |
---|
| 320 | // Repeat this entire process if chain is stretched beyond its natural length |
---|
| 321 | bool done = false; |
---|
| 322 | while (!done) |
---|
| 323 | { |
---|
| 324 | // Node has changed somehow, we're only interested in the derived position |
---|
| 325 | ChainSegment& seg = mChainSegmentList[index]; |
---|
| 326 | Element& headElem = mChainElementList[seg.start + seg.head]; |
---|
| 327 | size_t nextElemIdx = seg.head + 1; |
---|
| 328 | // wrap |
---|
| 329 | if (nextElemIdx == mMaxElementsPerChain) |
---|
| 330 | nextElemIdx = 0; |
---|
| 331 | Element& nextElem = mChainElementList[seg.start + nextElemIdx]; |
---|
| 332 | |
---|
| 333 | // Vary the head elem, but bake new version if that exceeds element len |
---|
| 334 | Vector3 newPos = node->_getDerivedPosition(); |
---|
| 335 | if (mParentNode) |
---|
| 336 | { |
---|
| 337 | // Transform position to ourself space |
---|
| 338 | newPos = mParentNode->_getDerivedOrientation().UnitInverse() * |
---|
| 339 | (newPos - mParentNode->_getDerivedPosition()) / mParentNode->_getDerivedScale(); |
---|
| 340 | } |
---|
| 341 | Vector3 diff = newPos - nextElem.position; |
---|
| 342 | Real sqlen = diff.squaredLength(); |
---|
| 343 | if (sqlen >= mSquaredElemLength) |
---|
| 344 | { |
---|
| 345 | // Move existing head to mElemLength |
---|
| 346 | Vector3 scaledDiff = diff * (mElemLength / Math::Sqrt(sqlen)); |
---|
| 347 | headElem.position = nextElem.position + scaledDiff; |
---|
| 348 | // Add a new element to be the new head |
---|
| 349 | Element newElem(newPos, mInitialWidth[index], 0.0f, mInitialColour[index]); |
---|
| 350 | addChainElement(index, newElem); |
---|
| 351 | // alter diff to represent new head size |
---|
| 352 | diff = newPos - headElem.position; |
---|
| 353 | // check whether another step is needed or not |
---|
| 354 | if (diff.squaredLength() <= mSquaredElemLength) |
---|
| 355 | done = true; |
---|
| 356 | |
---|
| 357 | } |
---|
| 358 | else |
---|
| 359 | { |
---|
| 360 | // Extend existing head |
---|
| 361 | headElem.position = newPos; |
---|
| 362 | done = true; |
---|
| 363 | } |
---|
| 364 | |
---|
| 365 | // Is this segment full? |
---|
| 366 | if ((seg.tail + 1) % mMaxElementsPerChain == seg.head) |
---|
| 367 | { |
---|
| 368 | // If so, shrink tail gradually to match head extension |
---|
| 369 | Element& tailElem = mChainElementList[seg.start + seg.tail]; |
---|
| 370 | size_t preTailIdx; |
---|
| 371 | if (seg.tail == 0) |
---|
| 372 | preTailIdx = mMaxElementsPerChain - 1; |
---|
| 373 | else |
---|
| 374 | preTailIdx = seg.tail - 1; |
---|
| 375 | Element& preTailElem = mChainElementList[seg.start + preTailIdx]; |
---|
| 376 | |
---|
| 377 | // Measure tail diff from pretail to tail |
---|
| 378 | Vector3 taildiff = tailElem.position - preTailElem.position; |
---|
| 379 | Real taillen = taildiff.length(); |
---|
| 380 | if (taillen > 1e-06) |
---|
| 381 | { |
---|
| 382 | Real tailsize = mElemLength - diff.length(); |
---|
| 383 | taildiff *= tailsize / taillen; |
---|
| 384 | tailElem.position = preTailElem.position + taildiff; |
---|
| 385 | } |
---|
| 386 | |
---|
| 387 | } |
---|
| 388 | } // end while |
---|
| 389 | |
---|
| 390 | |
---|
| 391 | mBoundsDirty = true; |
---|
| 392 | // Need to dirty the parent node, but can't do it using needUpdate() here |
---|
| 393 | // since we're in the middle of the scene graph update (node listener), |
---|
| 394 | // so re-entrant calls don't work. Queue. |
---|
| 395 | if (mParentNode) |
---|
| 396 | { |
---|
| 397 | Node::queueNeedUpdate(getParentSceneNode()); |
---|
| 398 | } |
---|
| 399 | |
---|
| 400 | } |
---|
| 401 | //----------------------------------------------------------------------- |
---|
| 402 | void RibbonTrail::_timeUpdate(Real time) |
---|
| 403 | { |
---|
| 404 | // Apply all segment effects |
---|
| 405 | for (size_t s = 0; s < mChainSegmentList.size(); ++s) |
---|
| 406 | { |
---|
| 407 | ChainSegment& seg = mChainSegmentList[s]; |
---|
| 408 | if (seg.head != SEGMENT_EMPTY && seg.head != seg.tail) |
---|
| 409 | { |
---|
| 410 | |
---|
| 411 | for(size_t e = seg.head + 1;; ++e) // until break |
---|
| 412 | { |
---|
| 413 | e = e % mMaxElementsPerChain; |
---|
| 414 | |
---|
| 415 | Element& elem = mChainElementList[seg.start + e]; |
---|
| 416 | elem.width = elem.width - (time * mDeltaWidth[s]); |
---|
| 417 | elem.width = std::max(Real(0.0f), elem.width); |
---|
| 418 | elem.colour = elem.colour - (mDeltaColour[s] * time); |
---|
| 419 | elem.colour.saturate(); |
---|
| 420 | |
---|
| 421 | if (e == seg.tail) |
---|
| 422 | break; |
---|
| 423 | |
---|
| 424 | } |
---|
| 425 | } |
---|
| 426 | |
---|
| 427 | } |
---|
| 428 | |
---|
| 429 | } |
---|
| 430 | //----------------------------------------------------------------------- |
---|
| 431 | void RibbonTrail::resetTrail(size_t index, const Node* node) |
---|
| 432 | { |
---|
| 433 | assert(index < mChainCount); |
---|
| 434 | |
---|
| 435 | ChainSegment& seg = mChainSegmentList[index]; |
---|
| 436 | // set up this segment |
---|
| 437 | seg.head = seg.tail = SEGMENT_EMPTY; |
---|
| 438 | // Create new element, v coord is always 0.0f |
---|
| 439 | Element e(node->_getDerivedPosition(), |
---|
| 440 | mInitialWidth[index], 0.0f, mInitialColour[index]); |
---|
| 441 | // Add the start position |
---|
| 442 | addChainElement(index, e); |
---|
| 443 | // Add another on the same spot, this will extend |
---|
| 444 | addChainElement(index, e); |
---|
| 445 | } |
---|
| 446 | //----------------------------------------------------------------------- |
---|
| 447 | void RibbonTrail::resetAllTrails(void) |
---|
| 448 | { |
---|
| 449 | for (size_t i = 0; i < mNodeList.size(); ++i) |
---|
| 450 | { |
---|
| 451 | resetTrail(i, mNodeList[i]); |
---|
| 452 | } |
---|
| 453 | } |
---|
| 454 | //----------------------------------------------------------------------- |
---|
| 455 | const String& RibbonTrail::getMovableType(void) const |
---|
| 456 | { |
---|
| 457 | return RibbonTrailFactory::FACTORY_TYPE_NAME; |
---|
| 458 | } |
---|
| 459 | //----------------------------------------------------------------------- |
---|
| 460 | //----------------------------------------------------------------------- |
---|
| 461 | String RibbonTrailFactory::FACTORY_TYPE_NAME = "RibbonTrail"; |
---|
| 462 | //----------------------------------------------------------------------- |
---|
| 463 | const String& RibbonTrailFactory::getType(void) const |
---|
| 464 | { |
---|
| 465 | return FACTORY_TYPE_NAME; |
---|
| 466 | } |
---|
| 467 | //----------------------------------------------------------------------- |
---|
| 468 | MovableObject* RibbonTrailFactory::createInstanceImpl( const String& name, |
---|
| 469 | const NameValuePairList* params) |
---|
| 470 | { |
---|
| 471 | size_t maxElements = 20; |
---|
| 472 | size_t numberOfChains = 1; |
---|
| 473 | bool useTex = true; |
---|
| 474 | bool useCol = true; |
---|
| 475 | // optional params |
---|
| 476 | if (params != 0) |
---|
| 477 | { |
---|
| 478 | NameValuePairList::const_iterator ni = params->find("maxElements"); |
---|
| 479 | if (ni != params->end()) |
---|
| 480 | { |
---|
| 481 | maxElements = StringConverter::parseUnsignedLong(ni->second); |
---|
| 482 | } |
---|
| 483 | ni = params->find("numberOfChains"); |
---|
| 484 | if (ni != params->end()) |
---|
| 485 | { |
---|
| 486 | numberOfChains = StringConverter::parseUnsignedLong(ni->second); |
---|
| 487 | } |
---|
| 488 | ni = params->find("useTextureCoords"); |
---|
| 489 | if (ni != params->end()) |
---|
| 490 | { |
---|
| 491 | useTex = StringConverter::parseBool(ni->second); |
---|
| 492 | } |
---|
| 493 | ni = params->find("useVertexColours"); |
---|
| 494 | if (ni != params->end()) |
---|
| 495 | { |
---|
| 496 | useCol = StringConverter::parseBool(ni->second); |
---|
| 497 | } |
---|
| 498 | |
---|
| 499 | } |
---|
| 500 | |
---|
| 501 | return new RibbonTrail(name, maxElements, numberOfChains, useTex, useCol); |
---|
| 502 | |
---|
| 503 | } |
---|
| 504 | //----------------------------------------------------------------------- |
---|
| 505 | void RibbonTrailFactory::destroyInstance( MovableObject* obj) |
---|
| 506 | { |
---|
| 507 | delete obj; |
---|
| 508 | } |
---|
| 509 | |
---|
| 510 | |
---|
| 511 | |
---|
| 512 | |
---|
| 513 | } |
---|
| 514 | |
---|