RadiusDecal.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // RadiusDecal.cpp ///////////////////////////////////////////////////////////////////////////////////
  24. ///////////////////////////////////////////////////////////////////////////////////////////////////
  25. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  26. #define DEFINE_SHADOW_NAMES
  27. #include "Common/Player.h"
  28. #include "Common/PlayerList.h"
  29. #include "Common/Xfer.h"
  30. #include "GameClient/RadiusDecal.h"
  31. #include "GameClient/Shadow.h"
  32. #include "GameLogic/GameLogic.h"
  33. #ifdef _INTERNAL
  34. // for occasional debugging...
  35. //#pragma optimize("", off)
  36. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  37. #endif
  38. // ------------------------------------------------------------------------------------------------
  39. RadiusDecalTemplate::RadiusDecalTemplate() :
  40. m_shadowType(SHADOW_ALPHA_DECAL),
  41. m_minOpacity(1.0f),
  42. m_maxOpacity(1.0f),
  43. m_opacityThrobTime(LOGICFRAMES_PER_SECOND),
  44. m_color(0),
  45. m_onlyVisibleToOwningPlayer(true),
  46. m_name(AsciiString::TheEmptyString) // Added By Sadullah Nader for Init purposes
  47. {
  48. }
  49. // ------------------------------------------------------------------------------------------------
  50. void RadiusDecalTemplate::createRadiusDecal(const Coord3D& pos, Real radius, const Player* owningPlayer, RadiusDecal& result) const
  51. {
  52. result.clear();
  53. if (owningPlayer == NULL)
  54. {
  55. DEBUG_CRASH(("You MUST specify a non-NULL owningPlayer to createRadiusDecal. (srj)\n"));
  56. return;
  57. }
  58. if (m_name.isEmpty() || radius <= 0.0f)
  59. return;
  60. // it is now considered nonEmpty, regardless of the state of m_decal, etc
  61. result.m_empty = false;
  62. if (!m_onlyVisibleToOwningPlayer ||
  63. owningPlayer->getPlayerIndex() == ThePlayerList->getLocalPlayer()->getPlayerIndex())
  64. {
  65. Shadow::ShadowTypeInfo decalInfo;
  66. decalInfo.allowUpdates = FALSE; // shadow texture will never update
  67. decalInfo.allowWorldAlign = TRUE; // shadow image will wrap around world objects
  68. decalInfo.m_type = m_shadowType;
  69. strcpy(decalInfo.m_ShadowName, m_name.str()); // name of your texture
  70. decalInfo.m_sizeX = radius*2; // world space dimensions
  71. decalInfo.m_sizeY = radius*2; // world space dimensions
  72. result.m_decal = TheProjectedShadowManager->addDecal(&decalInfo);
  73. if (result.m_decal)
  74. {
  75. result.m_decal->setAngle(0.0f);
  76. result.m_decal->setColor(m_color == 0 ? owningPlayer->getPlayerColor() : m_color);
  77. result.m_decal->setPosition(pos.x, pos.y, pos.z);
  78. result.m_template = this;
  79. }
  80. else
  81. {
  82. DEBUG_CRASH(("Unable to add decal %s\n",decalInfo.m_ShadowName));
  83. }
  84. }
  85. }
  86. // ------------------------------------------------------------------------------------------------
  87. void RadiusDecalTemplate::xferRadiusDecalTemplate( Xfer *xfer )
  88. {
  89. // version
  90. XferVersion currentVersion = 1;
  91. XferVersion version = currentVersion;
  92. xfer->xferVersion( &version, currentVersion );
  93. xfer->xferAsciiString(&m_name);
  94. xfer->xferUser(&m_shadowType, sizeof(m_shadowType));
  95. xfer->xferReal(&m_minOpacity);
  96. xfer->xferReal(&m_maxOpacity);
  97. xfer->xferUnsignedInt(&m_opacityThrobTime);
  98. xfer->xferColor(&m_color);
  99. xfer->xferBool(&m_onlyVisibleToOwningPlayer);
  100. }
  101. // ------------------------------------------------------------------------------------------------
  102. /*static*/ void RadiusDecalTemplate::parseRadiusDecalTemplate(INI* ini, void *instance, void * store, const void* /*userData*/)
  103. {
  104. static const FieldParse dataFieldParse[] =
  105. {
  106. { "Texture", INI::parseAsciiString, NULL, offsetof( RadiusDecalTemplate, m_name ) },
  107. { "Style", INI::parseBitString32, TheShadowNames, offsetof( RadiusDecalTemplate, m_shadowType ) },
  108. { "OpacityMin", INI::parsePercentToReal, NULL, offsetof( RadiusDecalTemplate, m_minOpacity ) },
  109. { "OpacityMax", INI::parsePercentToReal, NULL, offsetof( RadiusDecalTemplate, m_maxOpacity) },
  110. { "OpacityThrobTime", INI::parseDurationUnsignedInt,NULL, offsetof( RadiusDecalTemplate, m_opacityThrobTime ) },
  111. { "Color", INI::parseColorInt, NULL, offsetof( RadiusDecalTemplate, m_color ) },
  112. { "OnlyVisibleToOwningPlayer", INI::parseBool, NULL, offsetof( RadiusDecalTemplate, m_onlyVisibleToOwningPlayer ) },
  113. { 0, 0, 0, 0 }
  114. };
  115. ini->initFromINI(store, dataFieldParse);
  116. }
  117. // ------------------------------------------------------------------------------------------------
  118. RadiusDecal::RadiusDecal() :
  119. m_template(NULL),
  120. m_decal(NULL),
  121. m_empty(true)
  122. {
  123. }
  124. // ------------------------------------------------------------------------------------------------
  125. RadiusDecal::RadiusDecal(const RadiusDecal& that) :
  126. m_template(NULL),
  127. m_decal(NULL),
  128. m_empty(true)
  129. {
  130. DEBUG_CRASH(("not fully implemented"));
  131. }
  132. // ------------------------------------------------------------------------------------------------
  133. RadiusDecal& RadiusDecal::operator=(const RadiusDecal& that)
  134. {
  135. if (this != &that)
  136. {
  137. m_template = NULL;
  138. if (m_decal)
  139. m_decal->release();
  140. m_decal = NULL;
  141. m_empty = true;
  142. DEBUG_CRASH(("not fully implemented"));
  143. }
  144. return *this;
  145. }
  146. // ------------------------------------------------------------------------------------------------
  147. void RadiusDecal::xferRadiusDecal( Xfer *xfer )
  148. {
  149. /// @todo implement me
  150. if (xfer->getXferMode() == XFER_LOAD)
  151. {
  152. clear();
  153. }
  154. }
  155. // ------------------------------------------------------------------------------------------------
  156. void RadiusDecal::clear()
  157. {
  158. m_template = NULL;
  159. if (m_decal)
  160. {
  161. m_decal->release();
  162. }
  163. m_decal = NULL;
  164. m_empty = true;
  165. }
  166. // ------------------------------------------------------------------------------------------------
  167. RadiusDecal::~RadiusDecal()
  168. {
  169. clear();
  170. }
  171. // ------------------------------------------------------------------------------------------------
  172. void RadiusDecal::update()
  173. {
  174. if (m_decal && m_template)
  175. {
  176. UnsignedInt now = TheGameLogic->getFrame();
  177. Real theta = (2*PI) * (Real)(now % m_template->m_opacityThrobTime) / (Real)m_template->m_opacityThrobTime;
  178. Real percent = 0.5f * (Sin(theta) + 1.0f);
  179. Int opac;
  180. if( TheGameLogic->getDrawIconUI() )
  181. {
  182. opac = REAL_TO_INT((m_template->m_minOpacity + percent * (m_template->m_maxOpacity - m_template->m_minOpacity)) * 255.0f);
  183. }
  184. else
  185. {
  186. //Scripts turned this off, so don't show them!
  187. opac = 0;
  188. }
  189. m_decal->setOpacity(opac);
  190. }
  191. }
  192. void RadiusDecal::setOpacity( Real o )
  193. {
  194. if (m_decal)
  195. {
  196. m_decal->setOpacity(REAL_TO_INT(255.0f * o));
  197. }
  198. }
  199. // ------------------------------------------------------------------------------------------------
  200. void RadiusDecal::setPosition(const Coord3D& pos)
  201. {
  202. if (m_decal)
  203. {
  204. m_decal->setPosition(pos.x, pos.y, pos.z); //world space position of center of decal
  205. }
  206. }