#include "Screen.h" #include #include "Image.h" #include "File.h" #include "Window.h" #include "Globals.h" #include "GraphicsApi.h" #include "Logging.h" #include "Mat3.h" #include "MouseEvent.h" #include "Model3D.h" #include "Text.h" #include "ToolTip.h" #include "Drawing.h" #include "Time.h" #ifdef WIN32 # include # include # include # include # include "comdef.h" # include "Camera3D.h" #endif using namespace Framework; // Content of the Screen class from Screen.h // Constructor Screen::Screen(NativeWindow* f) : ReferenceCounter(), api(0), fenster(f), members(new RCArray()), fillColor(0xFF000000), deckColor(0), onTop(0), renderOnTop(0), renderDrawables(1), rendering(0), renderTime(new Timer()), tips(new RCArray()), testRend(1), fill(1), rend(0), handleUserInputsOnTick(0) {} // Destructor Screen::~Screen() { lock(); #ifdef WIN32 if (fenster) fenster->release(); #endif members->release(); tips->release(); renderTime->release(); if (onTop) onTop->release(); if (api) api->release(); unlock(); } void Screen::postAction(std::function action) { cs.lock(); actions.push(action); cs.unlock(); } void Screen::setHandleUserInputsOnTick(bool handleOnTick) { handleUserInputsOnTick = handleOnTick; } // non-constant void Screen::lock() { cs.lock(); } void Screen::unlock() { cs.unlock(); } void Screen::setFill(bool f) { fill = f; } // Updates the objects that manage the graphics card void Screen::update() { lock(); api->update(); unlock(); } void Screen::setTestRend( bool tr) // specifies whether to check for updates before rendering { testRend = tr; } void Screen::setRenderDrawables( bool rO) // specifies whether drawings are rendered { lock(); renderDrawables = rO; rend = 1; unlock(); } void Screen::setOnTop( bool onTop) // specifies whether the onTop drawing is rendered { renderOnTop = onTop; rend = 1; } void Screen::setOnTopDrawable(Drawable* obj) // sets the onTop drawing { lock(); if (onTop) onTop->release(); onTop = obj; rend = 1; unlock(); } void Screen::setdeckColor(int f) // sets the overlay color { deckColor = f; rend = 1; } void Screen::addMember(Drawable* obj) // Adds a drawing { lock(); members->add(obj); rend = 1; unlock(); } void Screen::removeMember(Drawable* zObj) // Removes a drawing { lock(); for (int i = 0; i < members->getEntryCount(); i++) { if (members->z(i) == zObj) members->remove(i); } rend = 1; unlock(); } // Draws an image and presents it on the screen void Screen::render() { lock(); api->update(); rend = 1; unlock(); } void Screen::setFillColor(int f) // sets the fill color { fillColor = f; rend = 1; } void Screen::setFullscreen(bool vollbild) // sets fullscreen { lock(); api->setFullScreen(vollbild); unlock(); } void Screen::tick(double tickval) { lock(); while (!actions.empty()) { actions.front()(); actions.pop(); } if (!renderOnTop) { for (ArrayIterator i = tips->begin(); i; i++) { i->tick(tickval); if (i->getReferenceCount() == 1) i.remove(); } for (Drawable* i : *members) rend |= i->tick(tickval); } else if (onTop) { rend |= onTop->tick(tickval); for (ArrayIterator i = tips->begin(); i; i++) { i->tick(tickval); if (i->getReferenceCount() == 1) i.remove(); } } unlock(); } void Screen::setBackBufferSize( int Width, int height) // sets the size of the back buffer { lock(); api->setBackBufferSize(Vec2(Width, height)); unlock(); } void Screen::setBackBufferSize(Point& size) { lock(); api->setBackBufferSize(size); unlock(); } void Screen::doMouseEvent(MouseEvent& me) // sends mouse event { int fBr = api->getBackBufferSize().x; int fHi = api->getBackBufferSize().y; #ifdef WIN32 if (fenster) { fBr = fenster->getBodyWidth(); fHi = fenster->getBodyHeight(); } #endif me.mx = (int)(me.mx * api->getBackBufferSize().x / (double)fBr + 0.5); me.my = (int)(me.my * api->getBackBufferSize().y / (double)fHi + 0.5); lock(); if (!renderOnTop) { for (ArrayIterator i = tips->begin(); i; i++) { i->doPublicMouseEvent(me); if (i->getReferenceCount() == 1) i.remove(); } for (int i = members->getEntryCount() - 1; i >= 0; i--) members->z(i)->doPublicMouseEvent(me); } else if (onTop) { onTop->doPublicMouseEvent(me); for (ArrayIterator i = tips->begin(); i; i++) { i->doPublicMouseEvent(me); if (i->getReferenceCount() == 1) i.remove(); } } unlock(); } void Screen::doKeyboardEvent( KeyboardEvent& te) // sends keyboard event { lock(); if (!renderOnTop) { for (int i = members->getEntryCount() - 1; i >= 0; i--) members->z(i)->doKeyboardEvent(te); } for (ArrayIterator i = tips->begin(); i; i++) { i->doKeyboardEvent(te); if (i->getReferenceCount() == 1) i.remove(); } unlock(); } void Screen::addToolTip(ToolTip* tip) // adds a ToolTip { lock(); tips->add(tip); rend = 1; unlock(); } // constant Image* Screen::getRenderImage() const { return dynamic_cast(api->zUIRenderImage()->getThis()); } Image* Screen::zRenderImage() const { return api->zUIRenderImage(); } ArrayIterator Screen::getMembers() const // returns the drawings { return members->begin(); } int Screen::getFillColor() const // returns the fill color { return fillColor; } bool Screen::isFullscreen() const // returns whether fullscreen is on { return api->isFullScreen(); } const Point Screen::getBackBufferSize() const // returns the size of the back buffer { return api->getBackBufferSize(); } void Screen::waitForRendering() const // waits for the render function { while (rendering) { if (!rendering) return; } } double Screen::getRenderZeit() const // returns how many seconds rendering takes { return renderTime->getSekunden(); } // Returns the graphics API (without increased reference counter) GraphicsApi* Screen::zGraphicsApi() const { return api; } // Returns the graphics API GraphicsApi* Screen::getGraphicsApi() const { return api ? dynamic_cast(api->getThis()) : 0; } #ifdef WIN32 int MonitorEnum(HMONITOR m, HDC dc, LPRECT r, LPARAM p) { MONITORINFOEXA info; ZeroMemory(&info, sizeof(info)); info.cbSize = sizeof(info); GetMonitorInfo(m, &info); Monitor* mon = new Monitor(); mon->exists = 1; mon->x = r->left; mon->y = r->top; mon->Width = r->right - r->left; mon->height = r->bottom - r->top; mon->name = info.szDevice; if (mon->x == 0 && mon->y == 0) { ((Array*)p)->add(mon, 0); } else { ((Array*)p)->add(mon); } return 1; } Monitor Framework::getMonitor(int id) { if (id < 0) { Monitor m; m.exists = 0; return m; } Array* monitore = new Array(); DISPLAY_DEVICE dispDev; ZeroMemory(&dispDev, sizeof(dispDev)); dispDev.cb = sizeof(dispDev); EnumDisplayDevices(NULL, id, &dispDev, 0); EnumDisplayMonitors(0, 0, (MONITORENUMPROC)MonitorEnum, (LPARAM)monitore); int anz = monitore->getEntryCount(); Monitor result; result.exists = 0; result = *monitore->get(id); for (Monitor* m : *monitore) { delete m; } monitore->release(); return result; } // Screen2D // Constructor Screen2D::Screen2D(NativeWindow* fenster) : Screen(fenster) { api = new DirectX9(); api->initialize(dynamic_cast(fenster->getThis()), fenster->getBodySize(), 0); } // Destructor Screen2D::~Screen2D() {} void Screen2D::render() // Draws the image { if (!rend && testRend) return; rendering = 1; Image* ui = api->zUIRenderImage(); if (ui) { lock(); renderTime->measureStart(); api->beginFrame(fill && (rend || !testRend), 0, fillColor); if (renderDrawables) { if (renderOnTop && deckColor && (deckColor & (fillColor | 0xFF000000)) == deckColor) { ui->setAlpha(255 - (unsigned char)(deckColor >> 24)); for (Drawable* z : *members) z->render(*ui); // draw to intermediate buffer ui->releaseAlpha(); } else { for (Drawable* z : *members) z->render(*ui); // draw to intermediate buffer if (renderOnTop && deckColor) ui->alphaRegion( 0, 0, ui->getWidth(), ui->getHeight(), deckColor); } for (ArrayIterator i = tips->begin(); i; i++) { i->render(*ui); if (i->getReferenceCount() == 1) i.remove(); } } if (renderOnTop && onTop) onTop->render(*ui); api->presentFrame(); renderTime->measureEnd(); unlock(); } rendering = 0; rend = 0; } // Screen3D // Constructor Screen3D::Screen3D(NativeWindow* fenster) : Screen(fenster), kameras(new RCArray()), rend3D(0) { if (DirectX12::isAvailable()) api = new DirectX12(); else if (DirectX11::isAvailable()) api = new DirectX11(); else api = new DirectX9(); api->initialize(dynamic_cast(fenster->getThis()), fenster->getBodySize(), 0); } Screen3D::Screen3D(NativeWindow* fenster, GraphicApiType apiTyp) : Screen(fenster), kameras(new RCArray()), rend3D(0) { if (apiTyp == DIRECTX9) api = new DirectX9(); if (apiTyp == DIRECTX11) api = new DirectX11(); if (apiTyp == DIRECTX12) api = new DirectX12(); api->initialize(dynamic_cast(fenster->getThis()), fenster->getBodySize(), 0); } Screen3D::Screen3D(NativeWindow* fenster, GraphicsApi* api) : Screen(fenster), kameras(new RCArray()), rend3D(0) { this->api = api; api->initialize(dynamic_cast(fenster->getThis()), fenster->getBodySize(), 0); } // Destructor Screen3D::~Screen3D() { kameras->release(); } // non-constant void Screen3D::addKamera(Cam3D* obj) // Adds a camera { lock(); kameras->add(obj); rend3D = 1; unlock(); } void Screen3D::removeKamera(Cam3D* zObj) // Removes a camera { lock(); for (int i = 0; kameras->z(i); i++) { if (kameras->z(i) == zObj) { kameras->remove(i); break; } } rend3D = 1; unlock(); } void Screen3D::tick(double tickval) { lock(); __super::tick(tickval); for (Cam3D* k : *kameras) rend3D |= k->tick(tickval); unlock(); if (handleUserInputsOnTick) { queueCs.lock(); while (meQueue.getEntryCount() > 0) { MouseEvent me = meQueue.get(0); __super::doMouseEvent(me); for (int i = kameras->getEntryCount() - 1; i >= 0; i--) kameras->z(i)->doMouseEvent(me); meQueue.remove(0); } while (teQueue.getEntryCount() > 0) { KeyboardEvent te = teQueue.get(0); __super::doKeyboardEvent(te); for (int i = kameras->getEntryCount() - 1; i >= 0; i--) kameras->z(i)->doKeyboardEvent(te); teQueue.remove(0); } queueCs.unlock(); } } void Screen3D::doMouseEvent(MouseEvent& me) // sends mouse event { if (handleUserInputsOnTick) { queueCs.lock(); meQueue.add(me); queueCs.unlock(); } else { lock(); __super::doMouseEvent(me); for (int i = kameras->getEntryCount() - 1; i >= 0; i--) kameras->z(i)->doMouseEvent(me); unlock(); } } void Screen3D::doKeyboardEvent( KeyboardEvent& te) // sends keyboard event { if (handleUserInputsOnTick) { queueCs.lock(); teQueue.add(te); queueCs.unlock(); } else { lock(); __super::doKeyboardEvent(te); for (int i = kameras->getEntryCount() - 1; i >= 0; i--) kameras->z(i)->doKeyboardEvent(te); unlock(); } } void Screen3D::render() // Draws the image { rendering = 1; lock(); renderTime->measureStart(); // Clear the back buffer. api->beginFrame(fill && (rend || !testRend), fill && (rend3D || !testRend || rend), fillColor); if (rend3D || !testRend || rend) { // Render 3d Objects for (Cam3D* k : *kameras) api->renderKamera(k); rend3D = 0; } // render User Interface Image* ui = api->zUIRenderImage(); if ((rend || !testRend) && ui) { if (renderDrawables) { if (renderOnTop && deckColor && (deckColor & (fillColor | 0xFF000000)) == deckColor) { ui->setAlpha(255 - (unsigned char)(deckColor >> 24)); for (Drawable* z : *members) z->render(*ui); // draw to intermediate buffer ui->releaseAlpha(); } else { for (Drawable* z : *members) z->render(*ui); // draw to intermediate buffer if (renderOnTop && deckColor) ui->alphaRegion( 0, 0, ui->getWidth(), ui->getHeight(), deckColor); } for (ArrayIterator i = tips->begin(); i; i++) { i->render(*ui); if (i->getReferenceCount() == 1) i.remove(); } } if (renderOnTop && onTop) onTop->render(*ui); } api->presentFrame(); unlock(); renderTime->measureEnd(); # ifdef _DEBUG // Logging::trace() << renderTime->getSekunden() << "\n"; # endif rendering = 0; rend = 0; } #endif