PageRenderTime 124ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/Code/Angel/Actors/Actor.cpp

http://angel-engine.googlecode.com/
C++ | 707 lines | 545 code | 99 blank | 63 comment | 82 complexity | c0ddd2ab99d0eb975b84ab7a6c0c7e90 MD5 | raw file
Possible License(s): 0BSD, BSD-3-Clause, LGPL-2.1, GPL-2.0, LGPL-2.0, LGPL-3.0, GPL-3.0
  1. //////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 2008-2012, Shane Liesegang
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are met:
  7. //
  8. // * Redistributions of source code must retain the above copyright
  9. // notice, this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above copyright
  11. // notice, this list of conditions and the following disclaimer in the
  12. // documentation and/or other materials provided with the distribution.
  13. // * Neither the name of the copyright holder nor the names of any
  14. // contributors may be used to endorse or promote products derived from
  15. // this software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  18. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  21. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  24. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  25. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  26. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  27. // POSSIBILITY OF SUCH DAMAGE.
  28. //////////////////////////////////////////////////////////////////////////////
  29. #include "stdafx.h"
  30. #include "../Actors/Actor.h"
  31. #include "../Infrastructure/TagCollection.h"
  32. #include "../Infrastructure/Textures.h"
  33. #include "../Infrastructure/TextRendering.h"
  34. #include "../Infrastructure/Log.h"
  35. #include "../Util/StringUtil.h"
  36. #include "../Util/MathUtil.h"
  37. #include "../Messaging/Switchboard.h"
  38. #include "../Infrastructure/World.h"
  39. #include <sstream>
  40. const float Actor::_squareVertices[] = {
  41. -0.5f, 0.5f,
  42. -0.5f, -0.5f,
  43. 0.5f, 0.5f,
  44. 0.5f, -0.5f,
  45. };
  46. float Actor::_circleVertices[(CIRCLE_DRAW_SECTIONS+2)*2];
  47. float Actor::_circleTextureCoords[(CIRCLE_DRAW_SECTIONS+2)*2];
  48. Actor* Actor::_scriptCreatedActor = NULL;
  49. bool __inittedActorCirclePoints = false;
  50. std::map<String, Actor*> Actor::_nameList;
  51. Actor::Actor()
  52. {
  53. if (!__inittedActorCirclePoints)
  54. {
  55. Actor::_circleVertices[0] = 0.0f;
  56. Actor::_circleVertices[1] = 0.0f;
  57. Actor::_circleTextureCoords[0] = 0.5f;
  58. Actor::_circleTextureCoords[1] = 0.5f;
  59. for (int i=1; i < CIRCLE_DRAW_SECTIONS+2; i++)
  60. {
  61. Actor::_circleVertices[i*2] = 0.5f * cos((float) MathUtil::TwoPi * i / CIRCLE_DRAW_SECTIONS);
  62. Actor::_circleVertices[(i*2)+1] = 0.5f * sin((float) MathUtil::TwoPi * i / CIRCLE_DRAW_SECTIONS);
  63. Actor::_circleTextureCoords[i*2] = Actor::_circleVertices[i*2] + 0.5f;
  64. Actor::_circleTextureCoords[(i*2)+1] = Actor::_circleVertices[(i*2)+1] + 0.5f;
  65. }
  66. __inittedActorCirclePoints = true;
  67. }
  68. SetColor(1.0f, 1.0f, 1.0f);
  69. SetAlpha(1.0f);
  70. SetSize(1.0f);
  71. SetRotation(0.0f);
  72. SetPosition(0.0f, 0.0f);
  73. SetUVs(Vector2(0.f, 0.f), Vector2(1.f, 1.f));
  74. _name = "";
  75. _spriteNumFrames = 0;
  76. _spriteCurrentFrame = 0;
  77. _spriteTextureReferences[0] = -1;
  78. _spriteFrameDelay = 0.0f;
  79. _displayListIndex = -1;
  80. _layer = 0;
  81. _drawShape = ADS_Square;
  82. }
  83. Actor::~Actor()
  84. {
  85. StringSet::iterator it = _tags.begin();
  86. while (it != _tags.end())
  87. {
  88. String tag = *it;
  89. it++;
  90. Untag(tag);
  91. }
  92. Actor::_nameList.erase(_name);
  93. }
  94. void Actor::Update(float dt)
  95. {
  96. UpdateSpriteAnimation(dt);
  97. if (_positionInterval.ShouldStep())
  98. {
  99. SetPosition(_positionInterval.Step(dt));
  100. if (!_positionInterval.ShouldStep())
  101. {
  102. if (_positionIntervalMessage != "")
  103. {
  104. theSwitchboard.Broadcast(new Message(_positionIntervalMessage, this));
  105. }
  106. }
  107. }
  108. if (_rotationInterval.ShouldStep())
  109. {
  110. SetRotation(_rotationInterval.Step(dt));
  111. if (!_rotationInterval.ShouldStep())
  112. {
  113. if (_rotationIntervalMessage != "")
  114. {
  115. theSwitchboard.Broadcast(new Message(_rotationIntervalMessage, this));
  116. }
  117. }
  118. }
  119. if (_colorInterval.ShouldStep())
  120. {
  121. SetColor(_colorInterval.Step(dt));
  122. if (!_colorInterval.ShouldStep())
  123. {
  124. if (_colorIntervalMessage != "")
  125. {
  126. theSwitchboard.Broadcast(new Message(_colorIntervalMessage, this));
  127. }
  128. }
  129. }
  130. if (_sizeInterval.ShouldStep())
  131. {
  132. Vector2 newSize = _sizeInterval.Step(dt);
  133. SetSize(newSize.X, newSize.Y);
  134. if (!_sizeInterval.ShouldStep())
  135. {
  136. if (_sizeIntervalMessage != "")
  137. {
  138. theSwitchboard.Broadcast(new Message(_sizeIntervalMessage, this));
  139. }
  140. }
  141. }
  142. }
  143. void Actor::UpdateSpriteAnimation(float dt)
  144. {
  145. if (_spriteFrameDelay > 0.0f)
  146. {
  147. _spriteCurrentFrameDelay -= dt;
  148. if (_spriteCurrentFrameDelay < 0.0f)
  149. {
  150. while (_spriteCurrentFrameDelay < 0.0f)
  151. {
  152. if (_spriteAnimType == SAT_Loop)
  153. {
  154. if (_spriteCurrentFrame == _spriteAnimEndFrame)
  155. _spriteCurrentFrame = _spriteAnimStartFrame;
  156. else
  157. ++_spriteCurrentFrame;
  158. }
  159. else if (_spriteAnimType == SAT_PingPong)
  160. {
  161. if (_spriteAnimDirection == 1)
  162. {
  163. if (_spriteCurrentFrame == _spriteAnimEndFrame)
  164. {
  165. _spriteAnimDirection = -1;
  166. _spriteCurrentFrame = _spriteAnimEndFrame - 1;
  167. }
  168. else
  169. ++_spriteCurrentFrame;
  170. }
  171. else
  172. {
  173. if (_spriteCurrentFrame == _spriteAnimStartFrame)
  174. {
  175. _spriteAnimDirection = 1;
  176. _spriteCurrentFrame = _spriteAnimStartFrame + 1;
  177. }
  178. else
  179. {
  180. --_spriteCurrentFrame;
  181. }
  182. }
  183. }
  184. else if (_spriteAnimType == SAT_OneShot)
  185. {
  186. // If we're done with our one shot and they set an animName, let them know it's done.
  187. if (_spriteCurrentFrame == _spriteAnimEndFrame)
  188. {
  189. // Needs to get called before callback, in case they start a new animation.
  190. _spriteAnimType = SAT_None;
  191. if (_currentAnimName.length() > 0)
  192. {
  193. AnimCallback(_currentAnimName);
  194. }
  195. }
  196. else
  197. {
  198. _spriteCurrentFrame += _spriteAnimDirection;
  199. }
  200. }
  201. _spriteCurrentFrameDelay += _spriteFrameDelay;
  202. }
  203. }
  204. }
  205. }
  206. void Actor::SetDrawShape( actorDrawShape drawShape )
  207. {
  208. _drawShape = drawShape;
  209. }
  210. const actorDrawShape& Actor::GetDrawShape() const
  211. {
  212. return _drawShape;
  213. }
  214. void Actor::MoveTo(const Vector2& newPosition, float duration, bool smooth, String onCompletionMessage)
  215. {
  216. _positionInterval = Interval<Vector2>(_position, newPosition, duration, smooth);
  217. _positionIntervalMessage = onCompletionMessage;
  218. }
  219. void Actor::RotateTo(float newRotation, float duration, bool smooth, String onCompletionMessage)
  220. {
  221. _rotationInterval = Interval<float>(_rotation, newRotation, duration, smooth);
  222. _rotationIntervalMessage = onCompletionMessage;
  223. }
  224. void Actor::ChangeColorTo(const Color& newColor, float duration, bool smooth, String onCompletionMessage)
  225. {
  226. _colorInterval = Interval<Color>(_color, newColor, duration, smooth);
  227. _colorIntervalMessage = onCompletionMessage;
  228. }
  229. void Actor::ChangeSizeTo(const Vector2& newSize, float duration, bool smooth, String onCompletionMessage)
  230. {
  231. _sizeInterval = Interval<Vector2>(_size, newSize, duration, smooth);
  232. _sizeIntervalMessage = onCompletionMessage;
  233. }
  234. void Actor::ChangeSizeTo(float newSize, float duration, bool smooth, String onCompletionMessage)
  235. {
  236. ChangeSizeTo(Vector2(newSize, newSize), duration, smooth, onCompletionMessage);
  237. }
  238. void Actor::Render()
  239. {
  240. glPushMatrix();
  241. glTranslatef(_position.X, _position.Y, 0.0f);
  242. glRotatef(_rotation, 0, 0, 1);
  243. glScalef(_size.X, _size.Y, 1.0f);
  244. glColor4f(_color.R, _color.G, _color.B, _color.A);
  245. int textureReference = _spriteTextureReferences[_spriteCurrentFrame];
  246. if (textureReference >= 0)
  247. {
  248. glEnable(GL_TEXTURE_2D);
  249. glBindTexture(GL_TEXTURE_2D, textureReference);
  250. }
  251. switch( _drawShape )
  252. {
  253. default:
  254. case ADS_Square:
  255. glEnableClientState(GL_VERTEX_ARRAY);
  256. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  257. glVertexPointer(2, GL_FLOAT, 0, _squareVertices);
  258. glTexCoordPointer(2, GL_FLOAT, 0, _UV);
  259. glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  260. break;
  261. case ADS_Circle:
  262. glEnableClientState(GL_VERTEX_ARRAY);
  263. glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  264. glVertexPointer(2, GL_FLOAT, 0, _circleVertices);
  265. glTexCoordPointer(2, GL_FLOAT, 0, _circleTextureCoords);
  266. glDrawArrays(GL_TRIANGLE_FAN, 0, CIRCLE_DRAW_SECTIONS+2);
  267. break;
  268. case ADS_CustomList:
  269. #if ANGEL_MOBILE
  270. sysLog.Printf("glCallList is unsupported in OpenGL|ES.");
  271. #else
  272. if (_displayListIndex < 0)
  273. {
  274. sysLog.Printf("Invalid display list index: %i.", _displayListIndex);
  275. }
  276. else
  277. {
  278. glCallList(_displayListIndex);
  279. }
  280. #endif
  281. break;
  282. }
  283. if (textureReference >= 0)
  284. {
  285. glDisable(GL_TEXTURE_2D);
  286. }
  287. glPopMatrix();
  288. }
  289. void Actor::SetSize(float x, float y)
  290. {
  291. float sizeX, sizeY;
  292. if (x < 0.0f)
  293. sizeX = 0.0f;
  294. else
  295. sizeX = x;
  296. if (y <= 0.f)
  297. sizeY = x;
  298. else
  299. sizeY = y;
  300. _size = Vector2(sizeX, sizeY);
  301. }
  302. void Actor::SetSize(const Vector2& newSize)
  303. {
  304. _size = newSize;
  305. if (_size.X < 0.0f)
  306. {
  307. _size.X = 0.0f;
  308. }
  309. if (_size.Y < 0.0f)
  310. {
  311. _size.Y = 0.0f;
  312. }
  313. }
  314. const Vector2& Actor::GetSize() const
  315. {
  316. return _size;
  317. }
  318. const BoundingBox Actor::GetBoundingBox() const
  319. {
  320. BoundingBox forReturn;
  321. forReturn.Min = _position - (_size / 2.0f);
  322. forReturn.Max = _position + (_size / 2.0f);
  323. return forReturn;
  324. }
  325. void Actor::SetPosition(float x, float y)
  326. {
  327. _position.X = x;
  328. _position.Y = y;
  329. }
  330. void Actor::SetPosition(const Vector2& pos)
  331. {
  332. _position = pos;
  333. }
  334. const Vector2& Actor::GetPosition() const
  335. {
  336. return _position;
  337. }
  338. void Actor::SetRotation(float rotation)
  339. {
  340. _rotation = rotation;
  341. }
  342. const float Actor::GetRotation() const
  343. {
  344. return _rotation;
  345. }
  346. const Color& Actor::GetColor() const
  347. {
  348. return _color;
  349. }
  350. void Actor::SetColor(float r, float g, float b, float a)
  351. {
  352. _color = Color(r, g, b, a);
  353. }
  354. void Actor::SetColor(const Color& color)
  355. {
  356. _color = color;
  357. }
  358. void Actor::SetAlpha(float newAlpha)
  359. {
  360. _color.A = newAlpha;
  361. }
  362. const float Actor::GetAlpha() const
  363. {
  364. return _color.A;
  365. }
  366. void Actor::SetSpriteTexture(int texRef, int frame)
  367. {
  368. frame = MathUtil::Clamp(frame, 0, MAX_SPRITE_FRAMES - 1);
  369. // Make sure to bump the number of frames if this frame surpasses it.
  370. if (frame >= _spriteNumFrames)
  371. {
  372. _spriteNumFrames = frame + 1;
  373. }
  374. _spriteTextureReferences[frame] = texRef;
  375. }
  376. int Actor::GetSpriteTexture(int frame) const
  377. {
  378. frame = MathUtil::Clamp(frame, 0, _spriteNumFrames - 1);
  379. return _spriteTextureReferences[frame];
  380. }
  381. // Will load the sprite if it doesn't find it in the texture cache.
  382. // The texture cache caches textures by filename.
  383. bool Actor::SetSprite(const String& filename, int frame, GLint clampmode, GLint filtermode, bool optional)
  384. {
  385. int textureReference = GetTextureReference(filename, clampmode, filtermode, optional);
  386. if (textureReference == -1)
  387. return false;
  388. SetSpriteTexture(textureReference, frame);
  389. return true;
  390. }
  391. void Actor::ClearSpriteInfo()
  392. {
  393. for (int i=0; i<_spriteNumFrames; ++i)
  394. {
  395. _spriteTextureReferences[i] = -1;
  396. }
  397. _spriteAnimType = SAT_None;
  398. _spriteFrameDelay = 0.0f;
  399. _spriteCurrentFrame = 0;
  400. }
  401. void Actor::SetSpriteFrame(int frame)
  402. {
  403. frame = MathUtil::Clamp(frame, 0, _spriteNumFrames - 1);
  404. if (_spriteTextureReferences[frame] == -1)
  405. {
  406. sysLog.Log("setSpriteFrame() - Warning: frame(" + IntToString(frame) + ") has an invalid texture reference.");
  407. }
  408. _spriteCurrentFrame = frame;
  409. }
  410. void Actor::PlaySpriteAnimation(float delay, spriteAnimationType animType, int startFrame, int endFrame, const char* _animName)
  411. {
  412. startFrame = MathUtil::Clamp(startFrame, 0, _spriteNumFrames-1);
  413. endFrame = MathUtil::Clamp(endFrame, 0, _spriteNumFrames-1);
  414. _spriteAnimDirection = startFrame > endFrame ? -1 : 1;
  415. _spriteCurrentFrameDelay = _spriteFrameDelay = delay;
  416. _spriteAnimType= animType;
  417. _spriteAnimStartFrame = _spriteCurrentFrame = startFrame;
  418. _spriteAnimEndFrame = endFrame;
  419. if (_animName)
  420. _currentAnimName = _animName;
  421. }
  422. void Actor::LoadSpriteFrames(const String& firstFilename, GLint clampmode, GLint filtermode)
  423. {
  424. int extensionLocation = firstFilename.rfind(".");
  425. int numberSeparator = firstFilename.rfind("_");
  426. int numDigits = extensionLocation - numberSeparator - 1;
  427. // Clear out the number of frames we think we have.
  428. _spriteNumFrames = 0;
  429. bool bValidNumber = true;
  430. // So you're saying I've got a chance?
  431. if (numberSeparator > 0 && numDigits > 0)
  432. {
  433. // Now see if all of the digits between _ and . are numbers (i.e. test_001.jpg).
  434. for (int i=1; i<=numDigits; ++i)
  435. {
  436. char digit = firstFilename[numberSeparator+i];
  437. if (digit < '0' || digit > '9')
  438. {
  439. bValidNumber = false;
  440. break;
  441. }
  442. }
  443. }
  444. // If these aren't valid, the format is incorrect.
  445. if (numberSeparator == (int)String::npos || numDigits <= 0 || !bValidNumber)
  446. {
  447. sysLog.Log("LoadSpriteFrames() - Bad Format - Expecting somename_###.ext");
  448. sysLog.Log("Attempting to load single texture: " + firstFilename);
  449. if (!SetSprite(firstFilename, 0, clampmode, filtermode))
  450. return;
  451. }
  452. // If we got this far, the filename format is correct.
  453. String numberString;
  454. // The number string is just the digits between the '_' and the file extension (i.e. 001).
  455. numberString.append(firstFilename.c_str(), numberSeparator+1, numDigits);
  456. // Get our starting numberical value.
  457. int number = atoi(numberString.c_str());
  458. String baseFilename;
  459. // The base name is everything up to the '_' before the number (i.e. somefile_).
  460. baseFilename.append( firstFilename.c_str(), numberSeparator+1);
  461. String extension;
  462. // The extension is everything after the number (i.e. .jpg).
  463. extension.append(firstFilename.c_str(), extensionLocation, firstFilename.length() - extensionLocation);
  464. // Keep loading until we stop finding images in the sequence.
  465. while (true)
  466. {
  467. // Build up the filename of the current image in the sequence.
  468. String newFilename = baseFilename + numberString + extension;
  469. // Were we able to load the file for this sprite?
  470. if (!SetSprite(newFilename, _spriteNumFrames, clampmode, filtermode, true /*optional*/))
  471. {
  472. break;
  473. }
  474. // Verify we don't go out of range on our hard-coded frame limit per sprite.
  475. if (_spriteNumFrames >= MAX_SPRITE_FRAMES)
  476. {
  477. sysLog.Log("Maximum number of frames reached (" + IntToString(MAX_SPRITE_FRAMES) + "). Bailing out...");
  478. sysLog.Log("Increment MAX_SPRITE_FRAMES if you need more.");
  479. break;
  480. }
  481. // Bump the number to the next value in the sequence.
  482. ++number;
  483. // Serialize the numerical value to it so we can retrieve the string equivalent.
  484. std::stringstream sstr;
  485. sstr << number;
  486. String newNumberString = sstr.str();
  487. // We assume that all the files have as many numerical digits as the first one (or greater) (i.e. 01..999).
  488. // See if we need to pad with leading zeros.
  489. int numLeadingZeros = numDigits - (int)newNumberString.length();
  490. // Do the leading zero padding.
  491. for (int i=0; i<numLeadingZeros; ++i)
  492. {
  493. newNumberString = '0' + newNumberString;
  494. }
  495. // Save off the newly formulated number string for the next image in the sequence.
  496. numberString = newNumberString;
  497. }
  498. }
  499. void Actor::SetUVs(const Vector2& lowleft, const Vector2& upright)
  500. {
  501. _UV[0] = lowleft.X;
  502. _UV[1] = upright.Y;
  503. _UV[2] = lowleft.X;
  504. _UV[3] = lowleft.Y;
  505. _UV[4] = upright.X;
  506. _UV[5] = upright.Y;
  507. _UV[6] = upright.X;
  508. _UV[7] = lowleft.Y;
  509. }
  510. void Actor::GetUVs(Vector2 &lowleft, Vector2 &upright) const
  511. {
  512. lowleft.X = _UV[2];
  513. lowleft.Y = _UV[3];
  514. upright.X = _UV[4];
  515. upright.Y = _UV[5];
  516. }
  517. const bool Actor::IsTagged(const String& tag)
  518. {
  519. StringSet::iterator it = _tags.find(tag);
  520. if (it != _tags.end())
  521. {
  522. return true;
  523. }
  524. else
  525. {
  526. return false;
  527. }
  528. }
  529. void Actor::Tag(const String& newTag)
  530. {
  531. StringList tags = SplitString(newTag, ", ");
  532. for(unsigned int i=0; i < tags.size(); i++)
  533. {
  534. tags[i] = ToLower(tags[i]);
  535. _tags.insert(tags[i]);
  536. theTagList.AddObjToTagList(this, tags[i]);
  537. }
  538. }
  539. void Actor::Untag(const String& oldTag)
  540. {
  541. _tags.erase(oldTag);
  542. theTagList.RemoveObjFromTagList(this, oldTag);
  543. }
  544. const StringSet& Actor::GetTags() const
  545. {
  546. return _tags;
  547. }
  548. const String& Actor::SetName(String newName)
  549. {
  550. //overkill for sure, but who knows how many unique actors we'll need
  551. static unsigned long long nameIndex = 0;
  552. if(newName.length() == 0)
  553. {
  554. newName = GetClassName();
  555. }
  556. newName[0] = toupper(newName[0]);
  557. const Actor* preNamed = Actor::GetNamed(newName);
  558. if ((preNamed == NULL) || (preNamed == this))
  559. {
  560. _name = newName;
  561. }
  562. else
  563. {
  564. _name = newName + ULLIntToString(++nameIndex);
  565. }
  566. Actor::_nameList[_name] = this;
  567. return _name;
  568. }
  569. const String& Actor::GetName() const
  570. {
  571. return _name;
  572. }
  573. Actor* const Actor::GetNamed(const String& nameLookup)
  574. {
  575. std::map<String,Actor*>::iterator it = _nameList.find(nameLookup);
  576. if (it == _nameList.end())
  577. {
  578. return NULL;
  579. }
  580. else
  581. {
  582. return it->second;
  583. }
  584. }
  585. Actor* Actor::Create(const String& archetype)
  586. {
  587. // Yes it might be faster to directly find the function in the Lua state
  588. // and call it with the C API, but this is much more readable. You're welcome.
  589. String toExec = "Actor_CreateAndRegister('" + archetype + "')\n";
  590. theWorld.ScriptExec(toExec);
  591. return _scriptCreatedActor;
  592. // For those curious, it would look like this:
  593. /*
  594. lua_State* L = LuaScriptingModule::GetLuaState();
  595. lua_getglobal(L, "Actor_CreateAndRegister");
  596. lua_pushstring(L, archetype.c_str());
  597. lua_call(L, 1, 0);
  598. return _scriptCreatedActor;
  599. */
  600. }
  601. void Actor::SetLayer(int layerIndex)
  602. {
  603. theWorld.UpdateLayer(this, layerIndex);
  604. }
  605. void Actor::SetLayer(const String& layerName)
  606. {
  607. theWorld.UpdateLayer(this, layerName);
  608. }