Screen.cpp 15 KB

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