W3DInGameUI.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  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. // FILE: W3DInGameUI.cpp //////////////////////////////////////////////////////////////////////////
  24. // Author: Colin Day, April 2001
  25. // Desct: In game user interface implementation for W3D
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #include <stdlib.h>
  28. #include "Common/GlobalData.h"
  29. #include "Common/ThingTemplate.h"
  30. #include "Common/ThingFactory.h"
  31. #include "GameLogic/TerrainLogic.h"
  32. #include "GameLogic/GameLogic.h"
  33. #include "GameLogic/Object.h"
  34. #include "GameClient/Drawable.h"
  35. #include "GameClient/GadgetListBox.h"
  36. #include "GameClient/GameClient.h"
  37. #include "GameClient/GameWindowManager.h"
  38. #include "GameClient/GadgetSlider.h"
  39. #include "GameClient/ControlBar.h"
  40. #include "W3DDevice/GameClient/W3DAssetManager.h"
  41. #include "W3DDevice/GameClient/W3DGUICallbacks.h"
  42. #include "W3DDevice/GameClient/W3DInGameUI.h"
  43. #include "W3DDevice/GameClient/W3DDisplay.h"
  44. #include "W3DDevice/GameClient/W3DScene.h"
  45. #include "W3DDevice/Common/W3DConvert.h"
  46. #include "WW3D2/WW3D.h"
  47. #include "WW3D2/HAnim.h"
  48. #include "Common/UnitTimings.h" //Contains the DO_UNIT_TIMINGS define jba.
  49. #ifdef _INTERNAL
  50. // for occasional debugging...
  51. //#pragma optimize("", off)
  52. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  53. #endif
  54. #ifdef _DEBUG
  55. #include "W3DDevice/GameClient/HeightMap.h"
  56. #include "WW3D2/DX8IndexBuffer.h"
  57. #include "WW3D2/DX8VertexBuffer.h"
  58. #include "WW3D2/VertMaterial.h"
  59. class DebugHintObject : public RenderObjClass
  60. {
  61. public:
  62. DebugHintObject(void);
  63. DebugHintObject(const DebugHintObject & src);
  64. DebugHintObject & operator = (const DebugHintObject &);
  65. ~DebugHintObject(void);
  66. virtual RenderObjClass * Clone(void) const;
  67. virtual int Class_ID(void) const;
  68. virtual void Render(RenderInfoClass & rinfo);
  69. virtual Bool Cast_Ray(RayCollisionTestClass & raytest);
  70. virtual void Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const;
  71. virtual void Get_Obj_Space_Bounding_Box(AABoxClass & aabox) const;
  72. int updateBlock(void);
  73. void freeMapResources(void);
  74. void setLocAndColorAndSize(const Coord3D *loc, Int argb, Int size);
  75. protected:
  76. Coord3D m_myLoc;
  77. Int m_myColor; // argb
  78. Int m_mySize;
  79. DX8IndexBufferClass *m_indexBuffer;
  80. ShaderClass m_shaderClass; //shader or rendering state for heightmap
  81. VertexMaterialClass *m_vertexMaterialClass;
  82. DX8VertexBufferClass *m_vertexBufferTile; //First vertex buffer.
  83. void initData(void);
  84. };
  85. // Texturing, no zbuffer, disabled zbuffer write, primary gradient, alpha blending
  86. #define SC_ALPHA ( SHADE_CNST(ShaderClass::PASS_ALWAYS, ShaderClass::DEPTH_WRITE_DISABLE, ShaderClass::COLOR_WRITE_ENABLE, ShaderClass::SRCBLEND_SRC_ALPHA, \
  87. ShaderClass::DSTBLEND_ONE_MINUS_SRC_ALPHA, ShaderClass::FOG_DISABLE, ShaderClass::GRADIENT_MODULATE, ShaderClass::SECONDARY_GRADIENT_DISABLE, ShaderClass::TEXTURING_ENABLE, \
  88. ShaderClass::ALPHATEST_DISABLE, ShaderClass::CULL_MODE_ENABLE, \
  89. ShaderClass::DETAILCOLOR_DISABLE, ShaderClass::DETAILALPHA_DISABLE) )
  90. DebugHintObject::~DebugHintObject(void)
  91. {
  92. freeMapResources();
  93. }
  94. DebugHintObject::DebugHintObject(void) :
  95. m_indexBuffer(NULL),
  96. m_vertexMaterialClass(NULL),
  97. m_vertexBufferTile(NULL),
  98. m_myColor(0),
  99. m_mySize(0)
  100. {
  101. initData();
  102. }
  103. Bool DebugHintObject::Cast_Ray(RayCollisionTestClass & raytest)
  104. {
  105. return false;
  106. }
  107. DebugHintObject::DebugHintObject(const DebugHintObject & src)
  108. {
  109. *this = src;
  110. }
  111. DebugHintObject & DebugHintObject::operator = (const DebugHintObject & that)
  112. {
  113. DEBUG_CRASH(("oops"));
  114. return *this;
  115. }
  116. void DebugHintObject::Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const
  117. {
  118. Vector3 ObjSpaceCenter((float)1000*0.5f,(float)1000*0.5f,(float)0);
  119. float length = ObjSpaceCenter.Length();
  120. sphere.Init(ObjSpaceCenter, length);
  121. }
  122. void DebugHintObject::Get_Obj_Space_Bounding_Box(AABoxClass & box) const
  123. {
  124. Vector3 minPt(0,0,0);
  125. Vector3 maxPt((float)1000,(float)1000,(float)1000);
  126. box.Init(minPt,maxPt);
  127. }
  128. Int DebugHintObject::Class_ID(void) const
  129. {
  130. return RenderObjClass::CLASSID_UNKNOWN;
  131. }
  132. RenderObjClass * DebugHintObject::Clone(void) const
  133. {
  134. DEBUG_CRASH(("oops"));
  135. return NEW DebugHintObject(*this);
  136. }
  137. void DebugHintObject::freeMapResources(void)
  138. {
  139. REF_PTR_RELEASE(m_indexBuffer);
  140. REF_PTR_RELEASE(m_vertexBufferTile);
  141. REF_PTR_RELEASE(m_vertexMaterialClass);
  142. }
  143. //Allocate a heightmap of x by y vertices.
  144. //data must be an array matching this size.
  145. void DebugHintObject::initData(void)
  146. {
  147. freeMapResources(); //free old data and ib/vb
  148. m_indexBuffer = NEW_REF(DX8IndexBufferClass,(3));
  149. // Fill up the IB
  150. {
  151. DX8IndexBufferClass::WriteLockClass lockIdxBuffer(m_indexBuffer);
  152. UnsignedShort *ib=lockIdxBuffer.Get_Index_Array();
  153. ib[0]=0;
  154. ib[1]=1;
  155. ib[2]=2;
  156. }
  157. m_vertexBufferTile = NEW_REF(DX8VertexBufferClass,(DX8_FVF_XYZDUV1,3,DX8VertexBufferClass::USAGE_DEFAULT));
  158. //go with a preset material for now.
  159. m_vertexMaterialClass = VertexMaterialClass::Get_Preset(VertexMaterialClass::PRELIT_DIFFUSE);
  160. //use a multi-texture shader: (text1*diffuse)*text2.
  161. m_shaderClass = ShaderClass::ShaderClass(SC_ALPHA);
  162. }
  163. void DebugHintObject::setLocAndColorAndSize(const Coord3D *loc, Int argb, Int size)
  164. {
  165. m_myLoc = *loc;
  166. m_myColor = argb;
  167. m_mySize = size;
  168. if (m_myLoc.z < 0 && TheTerrainRenderObject)
  169. {
  170. m_myLoc.z = TheTerrainRenderObject->getHeightMapHeight(m_myLoc.x, m_myLoc.y, NULL);
  171. }
  172. if (m_vertexBufferTile)
  173. {
  174. DX8VertexBufferClass::WriteLockClass lockVtxBuffer(m_vertexBufferTile);
  175. VertexFormatXYZDUV1 *vb = (VertexFormatXYZDUV1*)lockVtxBuffer.Get_Vertex_Array();
  176. Real x1 = m_mySize * 0.866; // cos(30)
  177. Real y1 = m_mySize * 0.5; // sin(30)
  178. // note, pts must go in a counterclockwise order!
  179. vb[0].x = 0;
  180. vb[0].y = m_mySize;
  181. vb[0].z = 0;
  182. vb[0].diffuse = m_myColor;
  183. vb[0].u1 = 0;
  184. vb[0].v1 = 0;
  185. vb[1].x = -x1;
  186. vb[1].y = -y1;
  187. vb[1].z = 0;
  188. vb[1].diffuse = m_myColor;
  189. vb[1].u1 = 0;
  190. vb[1].v1 = 0;
  191. vb[2].x = x1;
  192. vb[2].y = -y1;
  193. vb[2].z = 0;
  194. vb[2].diffuse = m_myColor;
  195. vb[2].u1 = 0;
  196. vb[2].v1 = 0;
  197. }
  198. }
  199. void DebugHintObject::Render(RenderInfoClass & rinfo)
  200. {
  201. SphereClass bounds(Vector3(m_myLoc.x, m_myLoc.y, m_myLoc.z), m_mySize);
  202. if (!rinfo.Camera.Cull_Sphere(bounds))
  203. {
  204. DX8Wrapper::Set_Material(m_vertexMaterialClass);
  205. DX8Wrapper::Set_Shader(m_shaderClass);
  206. DX8Wrapper::Set_Texture(0, NULL);
  207. DX8Wrapper::Set_Index_Buffer(m_indexBuffer,0);
  208. DX8Wrapper::Set_Vertex_Buffer(m_vertexBufferTile);
  209. Matrix3D tm(Transform);
  210. Vector3 vec(m_myLoc.x, m_myLoc.y, m_myLoc.z);
  211. tm.Set_Translation(vec);
  212. DX8Wrapper::Set_Transform(D3DTS_WORLD, tm);
  213. DX8Wrapper::Draw_Triangles( 0, 1, 0, 3);
  214. }
  215. }
  216. #endif // _DEBUG
  217. ///////////////////////////////////////////////////////////////////////////////////////////////////
  218. // DEFINITIONS
  219. ///////////////////////////////////////////////////////////////////////////////////////////////////
  220. //-------------------------------------------------------------------------------------------------
  221. //-------------------------------------------------------------------------------------------------
  222. W3DInGameUI::W3DInGameUI()
  223. {
  224. Int i;
  225. for( i = 0; i < MAX_MOVE_HINTS; i++ )
  226. {
  227. m_moveHintRenderObj[ i ] = NULL;
  228. m_moveHintAnim[ i ] = NULL;
  229. } // end for i
  230. m_buildingPlacementAnchor = NULL;
  231. m_buildingPlacementArrow = NULL;
  232. } // end W3DInGameUI
  233. //-------------------------------------------------------------------------------------------------
  234. //-------------------------------------------------------------------------------------------------
  235. W3DInGameUI::~W3DInGameUI()
  236. {
  237. Int i;
  238. // remove render objects for hints
  239. for( i = 0; i < MAX_MOVE_HINTS; i++ )
  240. {
  241. REF_PTR_RELEASE( m_moveHintRenderObj[ i ] );
  242. REF_PTR_RELEASE( m_moveHintAnim[ i ] );
  243. } // end for i
  244. REF_PTR_RELEASE( m_buildingPlacementAnchor );
  245. REF_PTR_RELEASE( m_buildingPlacementArrow );
  246. } // end ~W3DInGameUI
  247. // loadText ===================================================================
  248. /** Load text from the file */
  249. //=============================================================================
  250. static void loadText( char *filename, GameWindow *listboxText )
  251. {
  252. if (!listboxText)
  253. return;
  254. GadgetListBoxReset(listboxText);
  255. FILE *fp;
  256. // open the file
  257. fp = fopen( filename, "r" );
  258. if( fp == NULL )
  259. return;
  260. char buffer[ 1024 ];
  261. UnicodeString line;
  262. Color color = GameMakeColor(255, 255, 255, 255);
  263. while( fgets( buffer, 1024, fp ) != NULL )
  264. {
  265. line.translate(buffer);
  266. line.trim();
  267. if (line.isEmpty())
  268. line = UnicodeString(L" ");
  269. GadgetListBoxAddEntryText(listboxText, line, color, -1, -1);
  270. } // end while
  271. // close the file
  272. fclose( fp );
  273. } // end loadText
  274. //-------------------------------------------------------------------------------------------------
  275. //-------------------------------------------------------------------------------------------------
  276. void W3DInGameUI::init( void )
  277. {
  278. // extending functionality
  279. InGameUI::init();
  280. // for the beta, they didn't want the help menu showing up, but I left this as a bock
  281. // comment because we'll probably want to add this back in.
  282. /*
  283. // create the MOTD
  284. GameWindow *motd = TheWindowManager->winCreateFromScript( AsciiString("MOTD.wnd") );
  285. if( motd )
  286. {
  287. NameKeyType listboxTextID = TheNameKeyGenerator->nameToKey( "MOTD.wnd:ListboxMOTD" );
  288. GameWindow *listboxText = TheWindowManager->winGetWindowFromId(motd, listboxTextID);
  289. loadText( "HelpScreen.txt", listboxText );
  290. // hide it for now
  291. motd->winHide( TRUE );
  292. } // end if*/
  293. } // end init
  294. //-------------------------------------------------------------------------------------------------
  295. /** Update in game UI */
  296. //-------------------------------------------------------------------------------------------------
  297. void W3DInGameUI::update( void )
  298. {
  299. // call base
  300. InGameUI::update();
  301. } // end update
  302. //-------------------------------------------------------------------------------------------------
  303. /** Reset the in game ui */
  304. //-------------------------------------------------------------------------------------------------
  305. void W3DInGameUI::reset( void )
  306. {
  307. // call base
  308. InGameUI::reset();
  309. } // end reset
  310. //-------------------------------------------------------------------------------------------------
  311. /** Draw member for the W3D implemenation of the game user interface */
  312. //-------------------------------------------------------------------------------------------------
  313. void W3DInGameUI::draw( void )
  314. {
  315. preDraw();
  316. // draw selection region if drag selecting
  317. if( m_isDragSelecting )
  318. drawSelectionRegion();
  319. // for each view draw hints
  320. /// @todo should the UI be iterating through views like this?
  321. if( TheDisplay )
  322. {
  323. View *view;
  324. for( view = TheDisplay->getFirstView();
  325. view;
  326. view = TheDisplay->getNextView( view ) )
  327. {
  328. // draw move hints
  329. drawMoveHints( view );
  330. // draw attack hints
  331. drawAttackHints( view );
  332. // draw placement angle selection if needed
  333. drawPlaceAngle( view );
  334. } // end for view
  335. } // end if
  336. // repaint all our windows
  337. #ifdef EXTENDED_STATS
  338. if (!DX8Wrapper::stats.m_disableConsole) {
  339. #endif
  340. #ifdef DO_UNIT_TIMINGS
  341. #pragma MESSAGE("*** WARNING *** DOING DO_UNIT_TIMINGS!!!!")
  342. extern Bool g_UT_startTiming;
  343. if (!g_UT_startTiming)
  344. #endif
  345. postDraw();
  346. TheWindowManager->winRepaint();
  347. #ifdef EXTENDED_STATS
  348. }
  349. #endif
  350. } // end draw
  351. //-------------------------------------------------------------------------------------------------
  352. /** draw 2d selection region on screen */
  353. //-------------------------------------------------------------------------------------------------
  354. void W3DInGameUI::drawSelectionRegion( void )
  355. {
  356. Real width = 2.0f;
  357. UnsignedInt color = 0x9933FF33; //0xAARRGGBB
  358. TheDisplay->drawOpenRect( m_dragSelectRegion.lo.x,
  359. m_dragSelectRegion.lo.y,
  360. m_dragSelectRegion.hi.x - m_dragSelectRegion.lo.x,
  361. m_dragSelectRegion.hi.y - m_dragSelectRegion.lo.y,
  362. width,
  363. color );
  364. } // end drawSelectionRegion
  365. //-------------------------------------------------------------------------------------------------
  366. /** Draw the visual feedback for clicking in the world and telling units
  367. * to move there */
  368. //-------------------------------------------------------------------------------------------------
  369. void W3DInGameUI::drawMoveHints( View *view )
  370. {
  371. Int i;
  372. // Real width = 1.0f;
  373. // UnsignedInt color = 0x9933FF33; //0xAARRGGBB
  374. for( i = 0; i < MAX_MOVE_HINTS; i++ )
  375. {
  376. Int elapsed = TheGameClient->getFrame() - m_moveHint[i].frame;
  377. if( elapsed <= 40 )
  378. {
  379. RectClass rect;
  380. // if this hint is not in this view ignore it
  381. /// @todo write this to check if point is visible in view
  382. // if( view->pointInView( &m_moveHint[ i ].pos == FALSE )
  383. // continue;
  384. // create render object and add to scene of needed
  385. if( m_moveHintRenderObj[ i ] == NULL )
  386. {
  387. RenderObjClass *hint;
  388. HAnimClass *anim;
  389. // create hint object
  390. hint = W3DDisplay::m_assetManager->Create_Render_Obj(TheGlobalData->m_moveHintName.str());
  391. AsciiString animName;
  392. animName.format("%s.%s", TheGlobalData->m_moveHintName.str(), TheGlobalData->m_moveHintName.str());
  393. anim = W3DDisplay::m_assetManager->Get_HAnim(animName.str());
  394. // sanity
  395. if( hint == NULL )
  396. {
  397. DEBUG_CRASH(("unable to create hint"));
  398. return;
  399. } // end if
  400. // asign render objects to GUI data
  401. m_moveHintRenderObj[ i ] = hint;
  402. // note that 'anim' is returned from Get_HAnim with an AddRef, so we don't need to addref it again.
  403. // however, we do need to release the contents of moveHintAnim (if any)
  404. REF_PTR_RELEASE(m_moveHintAnim[i]);
  405. m_moveHintAnim[i] = anim;
  406. } // end if, create render objects
  407. // show the render object if hidden
  408. if( m_moveHintRenderObj[ i ]->Is_Hidden() == 1 ) {
  409. m_moveHintRenderObj[ i ]->Set_Hidden( 0 );
  410. // add to scene
  411. W3DDisplay::m_3DScene->Add_Render_Object( m_moveHintRenderObj[ i ] );
  412. if (m_moveHintAnim[i])
  413. m_moveHintRenderObj[i]->Set_Animation(m_moveHintAnim[i], 0, RenderObjClass::ANIM_MODE_ONCE);
  414. }
  415. // move this hint render object to the position and align with terrain
  416. Matrix3D transform;
  417. PathfindLayerEnum layer = TheTerrainLogic->alignOnTerrain( 0, m_moveHint[ i ].pos, true, transform );
  418. Real waterZ;
  419. if (layer == LAYER_GROUND && TheTerrainLogic->isUnderwater(m_moveHint[ i ].pos.x, m_moveHint[ i ].pos.y, &waterZ))
  420. {
  421. Coord3D tmp = m_moveHint[ i ].pos;
  422. tmp.z = waterZ;
  423. Coord3D normal;
  424. normal.x = 0;
  425. normal.y = 0;
  426. normal.z = 1;
  427. makeAlignToNormalMatrix(0, tmp, normal, transform);
  428. }
  429. m_moveHintRenderObj[ i ]->Set_Transform( transform );
  430. #if 0
  431. // if there is a source then draw line from source to destination
  432. Object *obj = TheGameLogic->getObject( m_moveHint[ i ].sourceID );
  433. if( obj )
  434. {
  435. Drawable *source = obj->getDrawable();
  436. if( source )
  437. {
  438. Coord3D pos;
  439. ICoord2D start, end;
  440. // project start and end point to screen point
  441. source->getPosition( &pos );
  442. view->worldToScreen( &pos, &start );
  443. view->worldToScreen( &hintPos, &end );
  444. // draw the line
  445. TheDisplay->drawLine( start.x, start.y, end.x, end.y, width, color );
  446. } // end if
  447. } // end if
  448. #endif
  449. }
  450. else
  451. {
  452. // hide hint marker
  453. if( m_moveHintRenderObj[ i ] )
  454. if( m_moveHintRenderObj[ i ]->Is_Hidden() == 0 ) {
  455. m_moveHintRenderObj[ i ]->Set_Hidden( 1 );
  456. W3DDisplay::m_3DScene->Remove_Render_Object( m_moveHintRenderObj[ i ] );
  457. }
  458. } // end else
  459. } // end for i
  460. } // end drawMoveHints
  461. //-------------------------------------------------------------------------------------------------
  462. /** Draw visual back for clicking to attack a unit in the world */
  463. //-------------------------------------------------------------------------------------------------
  464. void W3DInGameUI::drawAttackHints( View *view )
  465. {
  466. } // end drawAttackHints
  467. //-------------------------------------------------------------------------------------------------
  468. /** Draw the angle selection for placing building if needed */
  469. //-------------------------------------------------------------------------------------------------
  470. void W3DInGameUI::drawPlaceAngle( View *view )
  471. {
  472. // Coord2D v, p, o;
  473. //Real size = 15.0f;
  474. //Create the anchor & arrow if not already created!
  475. if( !m_buildingPlacementAnchor )
  476. {
  477. m_buildingPlacementAnchor = W3DDisplay::m_assetManager->Create_Render_Obj( "Locater01" );
  478. // sanity
  479. if( !m_buildingPlacementAnchor )
  480. {
  481. DEBUG_CRASH( ("Unable to create BuildingPlacementAnchor (Locator01.w3d) -- cursor for placing buildings") );
  482. return;
  483. }
  484. }
  485. if( !m_buildingPlacementArrow )
  486. {
  487. m_buildingPlacementArrow = W3DDisplay::m_assetManager->Create_Render_Obj( "Locater02" );
  488. // sanity
  489. if( !m_buildingPlacementArrow )
  490. {
  491. DEBUG_CRASH( ("Unable to create BuildingPlacementArrow (Locator02.w3d) -- cursor for placing buildings") );
  492. return;
  493. }
  494. }
  495. Bool anchorInScene = m_buildingPlacementAnchor->Peek_Scene() != NULL;
  496. Bool arrowInScene = m_buildingPlacementArrow->Peek_Scene() != NULL;
  497. // get out of here if this display isn't up anyway
  498. if( isPlacementAnchored() == FALSE )
  499. {
  500. if( anchorInScene )
  501. {
  502. //If our anchor is in the scene, remove it from the scene but don't delete it.
  503. W3DDisplay::m_3DScene->Remove_Render_Object( m_buildingPlacementAnchor );
  504. }
  505. if( arrowInScene )
  506. {
  507. //If our arrow is in the scene, remove it from the scene but don't delete it.
  508. W3DDisplay::m_3DScene->Remove_Render_Object( m_buildingPlacementArrow );
  509. }
  510. return;
  511. }
  512. // get the anchor points
  513. ICoord2D start, end;
  514. getPlacementPoints( &start, &end );
  515. Coord3D vector;
  516. vector.x = end.x - start.x;
  517. vector.y = end.y - start.y;
  518. vector.z = 0.0f;
  519. Real length = vector.length();
  520. Bool showArrow = length >= 5.0f;
  521. if( showArrow )
  522. {
  523. if( anchorInScene )
  524. {
  525. //We're switching to the arrow!
  526. W3DDisplay::m_3DScene->Remove_Render_Object( m_buildingPlacementAnchor );
  527. }
  528. if( !arrowInScene )
  529. {
  530. W3DDisplay::m_3DScene->Add_Render_Object( m_buildingPlacementArrow );
  531. arrowInScene = TRUE;
  532. }
  533. }
  534. else
  535. {
  536. if( arrowInScene )
  537. {
  538. //We're switching to the anchor!
  539. W3DDisplay::m_3DScene->Remove_Render_Object( m_buildingPlacementArrow );
  540. }
  541. if( !anchorInScene )
  542. {
  543. W3DDisplay::m_3DScene->Add_Render_Object( m_buildingPlacementAnchor );
  544. anchorInScene = TRUE;
  545. }
  546. }
  547. //The proper way to orient the placement arrow is to copy the matrix from the m_placeIcon[0]!
  548. if( anchorInScene )
  549. {
  550. if ( m_placeIcon[ 0 ] )
  551. m_buildingPlacementAnchor->Set_Transform( *m_placeIcon[ 0 ]->getTransformMatrix() );
  552. }
  553. else if( arrowInScene )
  554. {
  555. if ( m_placeIcon[ 0 ] )
  556. m_buildingPlacementArrow->Set_Transform( *m_placeIcon[ 0 ]->getTransformMatrix() );
  557. }
  558. //m_buildingPlacementArrow->Set_Transform(
  559. // draw a little box at the start to show the "anchor" point
  560. //Real rectSize = 4.0f;
  561. //TheDisplay->drawFillRect( start.x - rectSize / 2, start.y - rectSize / 2,
  562. // rectSize, rectSize, color );
  563. // compute vector for line
  564. //v.x = end.x - start.x;
  565. //v.y = end.y - start.y;
  566. //v.normalize();
  567. // compute opposite vector
  568. //o.x = -v.x;
  569. //o.y = -v.y;
  570. // compute perpendicular vector one way
  571. //p.x = -v.y;
  572. //p.y = v.x;
  573. // draw the line
  574. //start.x = o.x * size + p.x * (size/2.0f) + end.x;
  575. //start.y = o.y * size + p.y * (size/2.0f) + end.y;
  576. //TheDisplay->drawLine( start.x, start.y, end.x, end.y, width, color );
  577. // compute perpendicular vector other way
  578. //p.x = v.y;
  579. //p.y = -v.x;
  580. // draw the line
  581. //start.x = o.x * size + p.x * (size/2.0f) + end.x;
  582. //start.y = o.y * size + p.y * (size/2.0f) + end.y;
  583. //TheDisplay->drawLine( start.x, start.y, end.x, end.y, width, color );
  584. } // end drawPlaceAngle