Screen.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. #include "Screen.h"
  2. #include <iostream>
  3. #include "Drawing.h"
  4. #include "File.h"
  5. #include "Globals.h"
  6. #include "GraphicsApi.h"
  7. #include "Image.h"
  8. #include "Logging.h"
  9. #include "Mat3.h"
  10. #include "Model3D.h"
  11. #include "MouseEvent.h"
  12. #include "Text.h"
  13. #include "Timer.h"
  14. #include "ToolTip.h"
  15. #include "Window.h"
  16. #ifdef WIN32
  17. # include <d3d11.h>
  18. # include <d3d9.h>
  19. # include <D3Dcompiler.h>
  20. # include <DirectXMath.h>
  21. # include "Camera3D.h"
  22. # include "comdef.h"
  23. #endif
  24. using namespace Framework;
  25. // Content of the Screen class from Screen.h
  26. // Constructor
  27. Screen::Screen(NativeWindow* f)
  28. : ReferenceCounter(),
  29. api(0),
  30. fenster(f),
  31. members(new RCArray<Drawable>()),
  32. fillColor(0xFF000000),
  33. deckColor(0),
  34. onTop(0),
  35. renderOnTop(0),
  36. renderDrawables(1),
  37. rendering(0),
  38. renderTime(new Timer()),
  39. tips(new RCArray<ToolTip>()),
  40. testRend(1),
  41. fill(1),
  42. rend(0),
  43. handleUserInputsOnTick(0)
  44. {}
  45. // Destructor
  46. Screen::~Screen()
  47. {
  48. rwLock.lockWrite();
  49. #ifdef WIN32
  50. if (fenster) fenster->release();
  51. #endif
  52. members->release();
  53. tips->release();
  54. renderTime->release();
  55. if (onTop) onTop->release();
  56. if (api) api->release();
  57. rwLock.unlockWrite();
  58. }
  59. void Screen::postAction(std::function<void()> action)
  60. {
  61. actionsLock.lockWrite();
  62. actions.push(action);
  63. actionsLock.unlockWrite();
  64. }
  65. void Screen::setHandleUserInputsOnTick(bool handleOnTick)
  66. {
  67. handleUserInputsOnTick = handleOnTick;
  68. }
  69. void Screen::setFill(bool f)
  70. {
  71. fill = f;
  72. }
  73. // Updates the objects that manage the graphics card
  74. void Screen::update()
  75. {
  76. rwLock.lockRead();
  77. api->update();
  78. rwLock.unlockRead();
  79. }
  80. void Screen::setTestRend(
  81. bool tr) // specifies whether to check for updates before rendering
  82. {
  83. testRend = tr;
  84. }
  85. void Screen::setRenderDrawables(
  86. bool rO) // specifies whether drawings are rendered
  87. {
  88. rwLock.lockWrite();
  89. renderDrawables = rO;
  90. rend = 1;
  91. rwLock.unlockWrite();
  92. }
  93. void Screen::setOnTop(
  94. bool onTop) // specifies whether the onTop drawing is rendered
  95. {
  96. renderOnTop = onTop;
  97. rend = 1;
  98. }
  99. void Screen::setOnTopDrawable(Drawable* obj) // sets the onTop drawing
  100. {
  101. rwLock.lockWrite();
  102. if (onTop) onTop->release();
  103. onTop = obj;
  104. rend = 1;
  105. rwLock.unlockWrite();
  106. }
  107. void Screen::setdeckColor(int f) // sets the overlay color
  108. {
  109. deckColor = f;
  110. rend = 1;
  111. }
  112. void Screen::addMember(Drawable* obj) // Adds a drawing
  113. {
  114. rwLock.lockWrite();
  115. members->add(obj);
  116. rend = 1;
  117. rwLock.unlockWrite();
  118. }
  119. void Screen::removeMember(Drawable* zObj) // Removes a drawing
  120. {
  121. rwLock.lockWrite();
  122. for (int i = 0; i < members->getEntryCount(); i++)
  123. {
  124. if (members->z(i) == zObj) members->remove(i);
  125. }
  126. rend = 1;
  127. rwLock.unlockWrite();
  128. }
  129. void Screen::setFillColor(int f) // sets the fill color
  130. {
  131. fillColor = f;
  132. rend = 1;
  133. }
  134. void Screen::setFullscreen(bool vollbild) // sets fullscreen
  135. {
  136. rwLock.lockRead();
  137. api->setFullScreen(vollbild);
  138. rwLock.unlockRead();
  139. }
  140. void Screen::tick(double tickval)
  141. {
  142. actionsLock.lockRead();
  143. while (!actions.empty())
  144. {
  145. actions.front()();
  146. actionsLock.lockWrite();
  147. actions.pop();
  148. actionsLock.unlockWrite();
  149. }
  150. actionsLock.unlockRead();
  151. rwLock.lockRead();
  152. if (!renderOnTop)
  153. {
  154. for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
  155. {
  156. i->tick(tickval);
  157. if (i->getReferenceCount() == 1)
  158. {
  159. rwLock.lockWrite();
  160. i.remove();
  161. rwLock.unlockWrite();
  162. }
  163. }
  164. for (Drawable* i : *members)
  165. rend |= i->tick(tickval);
  166. }
  167. else if (onTop)
  168. {
  169. rend |= onTop->tick(tickval);
  170. for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
  171. {
  172. i->tick(tickval);
  173. if (i->getReferenceCount() == 1)
  174. {
  175. rwLock.lockWrite();
  176. i.remove();
  177. rwLock.unlockWrite();
  178. }
  179. }
  180. }
  181. rwLock.unlockRead();
  182. }
  183. void Screen::setBackBufferSize(
  184. int Width, int height) // sets the size of the back buffer
  185. {
  186. rwLock.lockRead();
  187. api->setBackBufferSize(Vec2<int>(Width, height));
  188. rwLock.unlockRead();
  189. }
  190. void Screen::setBackBufferSize(Point& size)
  191. {
  192. rwLock.lockRead();
  193. api->setBackBufferSize(size);
  194. rwLock.unlockRead();
  195. }
  196. void Screen::doMouseEvent(MouseEvent& me) // sends mouse event
  197. {
  198. int fBr = api->getBackBufferSize().x;
  199. int fHi = api->getBackBufferSize().y;
  200. #ifdef WIN32
  201. if (fenster)
  202. {
  203. fBr = fenster->getBodyWidth();
  204. fHi = fenster->getBodyHeight();
  205. }
  206. #endif
  207. me.mx = (int)(me.mx * api->getBackBufferSize().x / (double)fBr + 0.5);
  208. me.my = (int)(me.my * api->getBackBufferSize().y / (double)fHi + 0.5);
  209. rwLock.lockRead();
  210. if (!renderOnTop)
  211. {
  212. for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
  213. {
  214. i->doPublicMouseEvent(me);
  215. }
  216. for (int i = members->getEntryCount() - 1; i >= 0; i--)
  217. members->z(i)->doPublicMouseEvent(me);
  218. }
  219. else if (onTop)
  220. {
  221. onTop->doPublicMouseEvent(me);
  222. for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
  223. {
  224. i->doPublicMouseEvent(me);
  225. }
  226. }
  227. rwLock.unlockRead();
  228. }
  229. void Screen::doKeyboardEvent(KeyboardEvent& te) // sends keyboard event
  230. {
  231. rwLock.lockRead();
  232. if (!renderOnTop)
  233. {
  234. for (int i = members->getEntryCount() - 1; i >= 0; i--)
  235. members->z(i)->doKeyboardEvent(te);
  236. }
  237. for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
  238. {
  239. i->doKeyboardEvent(te);
  240. }
  241. rwLock.unlockRead();
  242. }
  243. void Screen::addToolTip(ToolTip* tip) // adds a ToolTip
  244. {
  245. rwLock.lockWrite();
  246. tips->add(tip);
  247. rend = 1;
  248. rwLock.unlockWrite();
  249. }
  250. // constant
  251. Image* Screen::getRenderImage() const
  252. {
  253. return dynamic_cast<Image*>(api->zUIRenderImage()->getThis());
  254. }
  255. Image* Screen::zRenderImage() const
  256. {
  257. return api->zUIRenderImage();
  258. }
  259. ArrayIterator<Drawable*> Screen::getMembers() const // returns the drawings
  260. {
  261. return members->begin();
  262. }
  263. int Screen::getFillColor() const // returns the fill color
  264. {
  265. return fillColor;
  266. }
  267. bool Screen::isFullscreen() const // returns whether fullscreen is on
  268. {
  269. return api->isFullScreen();
  270. }
  271. const Point
  272. Screen::getBackBufferSize() const // returns the size of the back buffer
  273. {
  274. return api->getBackBufferSize();
  275. }
  276. void Screen::waitForRendering() const // waits for the render function
  277. {
  278. while (rendering)
  279. {
  280. if (!rendering) return;
  281. }
  282. }
  283. double Screen::getRenderZeit() const // returns how many seconds rendering takes
  284. {
  285. return renderTime->getSekunden();
  286. }
  287. // Returns the graphics API (without increased reference counter)
  288. GraphicsApi* Screen::zGraphicsApi() const
  289. {
  290. return api;
  291. }
  292. // Returns the graphics API
  293. GraphicsApi* Screen::getGraphicsApi() const
  294. {
  295. return api ? dynamic_cast<GraphicsApi*>(api->getThis()) : 0;
  296. }
  297. #ifdef WIN32
  298. int MonitorEnum(HMONITOR m, HDC dc, LPRECT r, LPARAM p)
  299. {
  300. MONITORINFOEXA info;
  301. ZeroMemory(&info, sizeof(info));
  302. info.cbSize = sizeof(info);
  303. GetMonitorInfo(m, &info);
  304. Monitor* mon = new Monitor();
  305. mon->exists = 1;
  306. mon->x = r->left;
  307. mon->y = r->top;
  308. mon->width = r->right - r->left;
  309. mon->height = r->bottom - r->top;
  310. mon->name = info.szDevice;
  311. if (mon->x == 0 && mon->y == 0)
  312. {
  313. ((Array<Monitor*>*)p)->add(mon, 0);
  314. }
  315. else
  316. {
  317. ((Array<Monitor*>*)p)->add(mon);
  318. }
  319. return 1;
  320. }
  321. Monitor Framework::getMonitor(int id)
  322. {
  323. if (id < 0)
  324. {
  325. Monitor m;
  326. m.exists = 0;
  327. return m;
  328. }
  329. Array<Monitor*>* monitore = new Array<Monitor*>();
  330. DISPLAY_DEVICE dispDev;
  331. ZeroMemory(&dispDev, sizeof(dispDev));
  332. dispDev.cb = sizeof(dispDev);
  333. EnumDisplayDevices(NULL, id, &dispDev, 0);
  334. EnumDisplayMonitors(0, 0, (MONITORENUMPROC)MonitorEnum, (LPARAM)monitore);
  335. int anz = monitore->getEntryCount();
  336. Monitor result;
  337. result.exists = 0;
  338. result = *monitore->get(id);
  339. for (Monitor* m : *monitore)
  340. {
  341. delete m;
  342. }
  343. monitore->release();
  344. return result;
  345. }
  346. // Screen2D
  347. // Constructor
  348. Screen2D::Screen2D(NativeWindow* fenster)
  349. : Screen(fenster)
  350. {
  351. api = new DirectX9();
  352. api->initialize(dynamic_cast<NativeWindow*>(fenster->getThis()),
  353. fenster->getBodySize(),
  354. 0);
  355. }
  356. // Destructor
  357. Screen2D::~Screen2D() {}
  358. void Screen2D::render() // Draws the image
  359. {
  360. if (!rend && testRend) return;
  361. rendering = 1;
  362. Image* ui = api->zUIRenderImage();
  363. if (ui)
  364. {
  365. rwLock.lockRead();
  366. renderTime->measureStart();
  367. api->beginFrame(fill && (rend || !testRend), 0, fillColor);
  368. if (renderDrawables)
  369. {
  370. if (renderOnTop && deckColor
  371. && (deckColor & (fillColor | 0xFF000000)) == deckColor)
  372. {
  373. ui->setAlpha(255 - (unsigned char)(deckColor >> 24));
  374. for (Drawable* z : *members)
  375. z->render(*ui); // draw to intermediate buffer
  376. ui->releaseAlpha();
  377. }
  378. else
  379. {
  380. for (Drawable* z : *members)
  381. z->render(*ui); // draw to intermediate buffer
  382. if (renderOnTop && deckColor)
  383. ui->alphaRegion(
  384. 0, 0, ui->getWidth(), ui->getHeight(), deckColor);
  385. }
  386. for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
  387. {
  388. i->render(*ui);
  389. if (i->getReferenceCount() == 1) i.remove();
  390. }
  391. }
  392. if (renderOnTop && onTop) onTop->render(*ui);
  393. api->presentFrame();
  394. renderTime->measureEnd();
  395. rwLock.unlockRead();
  396. }
  397. rendering = 0;
  398. rend = 0;
  399. }
  400. // Screen3D
  401. // Constructor
  402. Screen3D::Screen3D(NativeWindow* fenster)
  403. : Screen(fenster),
  404. kameras(new RCArray<Cam3D>()),
  405. rend3D(0)
  406. {
  407. if (DirectX12::isAvailable())
  408. api = new DirectX12();
  409. else if (DirectX11::isAvailable())
  410. api = new DirectX11();
  411. else
  412. api = new DirectX9();
  413. api->initialize(dynamic_cast<NativeWindow*>(fenster->getThis()),
  414. fenster->getBodySize(),
  415. 0);
  416. }
  417. Screen3D::Screen3D(NativeWindow* fenster, GraphicApiType apiTyp)
  418. : Screen(fenster),
  419. kameras(new RCArray<Cam3D>()),
  420. rend3D(0)
  421. {
  422. if (apiTyp == DIRECTX9) api = new DirectX9();
  423. if (apiTyp == DIRECTX11) api = new DirectX11();
  424. if (apiTyp == DIRECTX12) api = new DirectX12();
  425. api->initialize(dynamic_cast<NativeWindow*>(fenster->getThis()),
  426. fenster->getBodySize(),
  427. 0);
  428. }
  429. Screen3D::Screen3D(NativeWindow* fenster, GraphicsApi* api)
  430. : Screen(fenster),
  431. kameras(new RCArray<Cam3D>()),
  432. rend3D(0)
  433. {
  434. this->api = api;
  435. api->initialize(dynamic_cast<NativeWindow*>(fenster->getThis()),
  436. fenster->getBodySize(),
  437. 0);
  438. }
  439. // Destructor
  440. Screen3D::~Screen3D()
  441. {
  442. kameras->release();
  443. }
  444. // non-constant
  445. void Screen3D::addKamera(Cam3D* obj) // Adds a camera
  446. {
  447. rwLock.lockWrite();
  448. kameras->add(obj);
  449. rend3D = 1;
  450. rwLock.unlockWrite();
  451. }
  452. void Screen3D::removeKamera(Cam3D* zObj) // Removes a camera
  453. {
  454. rwLock.lockWrite();
  455. for (int i = 0; kameras->z(i); i++)
  456. {
  457. if (kameras->z(i) == zObj)
  458. {
  459. kameras->remove(i);
  460. break;
  461. }
  462. }
  463. rend3D = 1;
  464. rwLock.unlockWrite();
  465. }
  466. void Screen3D::tick(double tickval)
  467. {
  468. rwLock.lockRead();
  469. __super::tick(tickval);
  470. for (Cam3D* k : *kameras)
  471. rend3D |= k->tick(tickval);
  472. rwLock.unlockRead();
  473. if (handleUserInputsOnTick)
  474. {
  475. queueCs.lock();
  476. while (meQueue.getEntryCount() > 0)
  477. {
  478. MouseEvent me = meQueue.get(0);
  479. __super::doMouseEvent(me);
  480. for (int i = kameras->getEntryCount() - 1; i >= 0; i--)
  481. kameras->z(i)->doMouseEvent(me);
  482. meQueue.remove(0);
  483. }
  484. while (teQueue.getEntryCount() > 0)
  485. {
  486. KeyboardEvent te = teQueue.get(0);
  487. __super::doKeyboardEvent(te);
  488. for (int i = kameras->getEntryCount() - 1; i >= 0; i--)
  489. kameras->z(i)->doKeyboardEvent(te);
  490. teQueue.remove(0);
  491. }
  492. queueCs.unlock();
  493. }
  494. }
  495. void Screen3D::doMouseEvent(MouseEvent& me) // sends mouse event
  496. {
  497. if (handleUserInputsOnTick)
  498. {
  499. queueCs.lock();
  500. meQueue.add(me);
  501. queueCs.unlock();
  502. }
  503. else
  504. {
  505. __super::doMouseEvent(me);
  506. rwLock.lockRead();
  507. for (int i = kameras->getEntryCount() - 1; i >= 0; i--)
  508. kameras->z(i)->doMouseEvent(me);
  509. rwLock.unlockRead();
  510. }
  511. }
  512. void Screen3D::doKeyboardEvent(KeyboardEvent& te) // sends keyboard event
  513. {
  514. if (handleUserInputsOnTick)
  515. {
  516. queueCs.lock();
  517. teQueue.add(te);
  518. queueCs.unlock();
  519. }
  520. else
  521. {
  522. __super::doKeyboardEvent(te);
  523. rwLock.lockRead();
  524. for (int i = kameras->getEntryCount() - 1; i >= 0; i--)
  525. kameras->z(i)->doKeyboardEvent(te);
  526. rwLock.unlockRead();
  527. }
  528. }
  529. void Screen3D::render() // Draws the image
  530. {
  531. rendering = 1;
  532. rwLock.lockRead();
  533. renderTime->measureStart();
  534. // Clear the back buffer.
  535. api->beginFrame(fill && (rend || !testRend),
  536. fill && (rend3D || !testRend || rend),
  537. fillColor);
  538. if (rend3D || !testRend || rend)
  539. {
  540. // Render 3d Objects
  541. for (Cam3D* k : *kameras)
  542. api->renderKamera(k);
  543. rend3D = 0;
  544. }
  545. // render User Interface
  546. Image* ui = api->zUIRenderImage();
  547. if ((rend || !testRend) && ui)
  548. {
  549. if (renderDrawables)
  550. {
  551. if (renderOnTop && deckColor
  552. && (deckColor & (fillColor | 0xFF000000)) == deckColor)
  553. {
  554. ui->setAlpha(255 - (unsigned char)(deckColor >> 24));
  555. for (Drawable* z : *members)
  556. z->render(*ui); // draw to intermediate buffer
  557. ui->releaseAlpha();
  558. }
  559. else
  560. {
  561. for (Drawable* z : *members)
  562. z->render(*ui); // draw to intermediate buffer
  563. if (renderOnTop && deckColor)
  564. ui->alphaRegion(
  565. 0, 0, ui->getWidth(), ui->getHeight(), deckColor);
  566. }
  567. for (ArrayIterator<ToolTip*> i = tips->begin(); i; i++)
  568. {
  569. i->render(*ui);
  570. }
  571. }
  572. if (renderOnTop && onTop) onTop->render(*ui);
  573. }
  574. api->presentFrame();
  575. rwLock.unlockRead();
  576. renderTime->measureEnd();
  577. # ifdef _DEBUG
  578. // Logging::trace() << renderTime->getSekunden() << "\n";
  579. # endif
  580. rendering = 0;
  581. rend = 0;
  582. }
  583. #endif