#include "Bildschirm.h" #include #include "Bild.h" #include "Datei.h" #include "Fenster.h" #include "Globals.h" #include "GraphicsApi.h" #include "Logging.h" #include "Mat3.h" #include "MausEreignis.h" #include "Model3D.h" #include "Text.h" #include "ToolTip.h" #include "Zeichnung.h" #include "Zeit.h" #ifdef WIN32 # include # include # include # include # include "comdef.h" # include "Kam3D.h" #endif using namespace Framework; // Inhalt der Bildschirmklass aus Bildschirm.h // Konstruktor Bildschirm::Bildschirm(WFenster* f) : ReferenceCounter(), api(0), fenster(f), members(new RCArray()), fillColor(0xFF000000), deckFarbe(0), onTop(0), renderOnTop(0), renderZeichnungen(1), rendering(0), renderZeit(new ZeitMesser()), tips(new RCArray()), testRend(1), fill(1), rend(0), handleUserInputsOnTick(0) {} // Destruktor Bildschirm::~Bildschirm() { lock(); #ifdef WIN32 if (fenster) fenster->release(); #endif members->release(); tips->release(); renderZeit->release(); if (onTop) onTop->release(); if (api) api->release(); unlock(); } void Bildschirm::postAction(std::function action) { cs.lock(); actions.push(action); cs.unlock(); } void Bildschirm::setHandleUserInputsOnTick(bool handleOnTick) { handleUserInputsOnTick = handleOnTick; } // nicht konstant void Bildschirm::lock() { cs.lock(); } void Bildschirm::unlock() { cs.unlock(); } void Bildschirm::setFill(bool f) { fill = f; } // Aktualisiert die Objekte, mit der die Grafikkarte verwaltet wird void Bildschirm::update() { lock(); api->update(); unlock(); } void Bildschirm::setTestRend( bool tr) // legt fest, ob vo rendern auf updates geprüft werden soll { testRend = tr; } void Bildschirm::setRenderZeichnungen( bool rO) // legt fest, ob die Zeichnunge gerendert werden { lock(); renderZeichnungen = rO; rend = 1; unlock(); } void Bildschirm::setOnTop( bool onTop) // legt fest, ob das onTop Zeichnung gerendert wid { renderOnTop = onTop; rend = 1; } void Bildschirm::setOnTopZeichnung(Zeichnung* obj) // setzt das OnTop Zeichnung { lock(); if (onTop) onTop->release(); onTop = obj; rend = 1; unlock(); } void Bildschirm::setdeckFarbe(int f) // setzt die deckFarbe { deckFarbe = f; rend = 1; } void Bildschirm::addMember(Zeichnung* obj) // Fügt ein Zeichnung hinzu { lock(); members->add(obj); rend = 1; unlock(); } void Bildschirm::removeMember(Zeichnung* zObj) // Entfernt ein Zeichnung { lock(); for (int i = 0; i < members->getEintragAnzahl(); i++) { if (members->z(i) == zObj) members->remove(i); } rend = 1; unlock(); } // Zeichnet ein Bild und präsentiert es auf dem Bildschirm void Bildschirm::render() { lock(); api->update(); rend = 1; unlock(); } void Bildschirm::setFillFarbe(int f) // setzt die Fill Farbe { fillColor = f; rend = 1; } void Bildschirm::setVollbild(bool vollbild) // setzt vollbild { lock(); api->setFullScreen(vollbild); unlock(); } void Bildschirm::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 (Zeichnung* 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 Bildschirm::setBackBufferSize( int breite, int height) // setzt die Größe des Backbuffers { lock(); api->setBackBufferSize(Vec2(breite, height)); unlock(); } void Bildschirm::setBackBufferSize(Punkt& size) { lock(); api->setBackBufferSize(size); unlock(); } void Bildschirm::doMausEreignis(MausEreignis& me) // sendet maus Ereignis { int fBr = api->getBackBufferSize().x; int fHi = api->getBackBufferSize().y; #ifdef WIN32 if (fenster) { fBr = fenster->getKörperBreite(); fHi = fenster->getKörperHöhe(); } #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->doPublicMausEreignis(me); if (i->getReferenceCount() == 1) i.remove(); } for (int i = members->getEintragAnzahl() - 1; i >= 0; i--) members->z(i)->doPublicMausEreignis(me); } else if (onTop) { onTop->doPublicMausEreignis(me); for (ArrayIterator i = tips->begin(); i; i++) { i->doPublicMausEreignis(me); if (i->getReferenceCount() == 1) i.remove(); } } unlock(); } void Bildschirm::doTastaturEreignis( TastaturEreignis& te) // sendet tastatur Ereignis { lock(); if (!renderOnTop) { for (int i = members->getEintragAnzahl() - 1; i >= 0; i--) members->z(i)->doTastaturEreignis(te); } for (ArrayIterator i = tips->begin(); i; i++) { i->doTastaturEreignis(te); if (i->getReferenceCount() == 1) i.remove(); } unlock(); } void Bildschirm::addToolTip(ToolTip* tip) // fügt ToolTip hinzu { lock(); tips->add(tip); rend = 1; unlock(); } // constant Bild* Bildschirm::getRenderBild() const { return dynamic_cast(api->zUIRenderBild()->getThis()); } Bild* Bildschirm::zRenderBild() const { return api->zUIRenderBild(); } ArrayIterator Bildschirm::getMembers() const // gibt die Zeichnunge zurück { return members->begin(); } int Bildschirm::getFillFarbe() const // gibt die Füll Farbe zurück { return fillColor; } bool Bildschirm::istVolbild() const // gibt zurück, ob vollbild an ist { return api->isFullScreen(); } const Punkt Bildschirm::getBackBufferSize() const // gibt die Größe des Backbuffers zurück { return api->getBackBufferSize(); } void Bildschirm::warteAufRendern() const // wartet auf die render Funktion { while (rendering) { if (!rendering) return; } } double Bildschirm::getRenderZeit() const // gibt zurück wie viele Sekunden das Rendern dauert { return renderZeit->getSekunden(); } // Gibt die Grafik API zurück (ohne erhöhten Reference Counter) GraphicsApi* Bildschirm::zGraphicsApi() const { return api; } // Gibt die Grafik API zurück GraphicsApi* Bildschirm::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->existiert = 1; mon->x = r->left; mon->y = r->top; mon->breite = 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.existiert = 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->getEintragAnzahl(); Monitor result; result.existiert = 0; result = *monitore->get(id); for (Monitor* m : *monitore) { delete m; } monitore->release(); return result; } // Bildschirm2D // Konstruktor Bildschirm2D::Bildschirm2D(WFenster* fenster) : Bildschirm(fenster) { api = new DirectX9(); api->initialize(dynamic_cast(fenster->getThis()), fenster->getKörperGröße(), 0); } // Destruktor Bildschirm2D::~Bildschirm2D() {} void Bildschirm2D::render() // Zeichnet das Bild { if (!rend && testRend) return; rendering = 1; Bild* ui = api->zUIRenderBild(); if (ui) { lock(); renderZeit->messungStart(); api->beginFrame(fill && (rend || !testRend), 0, fillColor); if (renderZeichnungen) { if (renderOnTop && deckFarbe && (deckFarbe & (fillColor | 0xFF000000)) == deckFarbe) { ui->setAlpha(255 - (unsigned char)(deckFarbe >> 24)); for (Zeichnung* z : *members) z->render(*ui); // zeichnen nach zwischenbuffer ui->releaseAlpha(); } else { for (Zeichnung* z : *members) z->render(*ui); // zeichnen nach zwischenbuffer if (renderOnTop && deckFarbe) ui->alphaRegion( 0, 0, ui->getBreite(), ui->getHeight(), deckFarbe); } for (ArrayIterator i = tips->begin(); i; i++) { i->render(*ui); if (i->getReferenceCount() == 1) i.remove(); } } if (renderOnTop && onTop) onTop->render(*ui); api->presentFrame(); renderZeit->messungEnde(); unlock(); } rendering = 0; rend = 0; } // Bildschirm3D // Konstruktor Bildschirm3D::Bildschirm3D(WFenster* fenster) : Bildschirm(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->getKörperGröße(), 0); } Bildschirm3D::Bildschirm3D(WFenster* fenster, GraphicApiType apiTyp) : Bildschirm(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->getKörperGröße(), 0); } Bildschirm3D::Bildschirm3D(WFenster* fenster, GraphicsApi* api) : Bildschirm(fenster), kameras(new RCArray()), rend3D(0) { this->api = api; api->initialize(dynamic_cast(fenster->getThis()), fenster->getKörperGröße(), 0); } // Destruktor Bildschirm3D::~Bildschirm3D() { kameras->release(); } // nicht constant void Bildschirm3D::addKamera(Kam3D* obj) // Fügt ein Zeichnung hinzu { lock(); kameras->add(obj); rend3D = 1; unlock(); } void Bildschirm3D::removeKamera(Kam3D* zObj) // Entfernt ein Zeichnung { lock(); for (int i = 0; kameras->z(i); i++) { if (kameras->z(i) == zObj) { kameras->remove(i); break; } } rend3D = 1; unlock(); } void Bildschirm3D::tick(double tickval) { lock(); __super::tick(tickval); for (Kam3D* k : *kameras) rend3D |= k->tick(tickval); unlock(); if (handleUserInputsOnTick) { queueCs.lock(); while (meQueue.getEintragAnzahl() > 0) { MausEreignis me = meQueue.get(0); __super::doMausEreignis(me); for (int i = kameras->getEintragAnzahl() - 1; i >= 0; i--) kameras->z(i)->doMausEreignis(me); meQueue.remove(0); } while (teQueue.getEintragAnzahl() > 0) { TastaturEreignis te = teQueue.get(0); __super::doTastaturEreignis(te); for (int i = kameras->getEintragAnzahl() - 1; i >= 0; i--) kameras->z(i)->doTastaturEreignis(te); teQueue.remove(0); } queueCs.unlock(); } } void Bildschirm3D::doMausEreignis(MausEreignis& me) // sendet maus Ereignis { if (handleUserInputsOnTick) { queueCs.lock(); meQueue.add(me); queueCs.unlock(); } else { lock(); __super::doMausEreignis(me); for (int i = kameras->getEintragAnzahl() - 1; i >= 0; i--) kameras->z(i)->doMausEreignis(me); unlock(); } } void Bildschirm3D::doTastaturEreignis( TastaturEreignis& te) // sendet tastatur Ereignis { if (handleUserInputsOnTick) { queueCs.lock(); teQueue.add(te); queueCs.unlock(); } else { lock(); __super::doTastaturEreignis(te); for (int i = kameras->getEintragAnzahl() - 1; i >= 0; i--) kameras->z(i)->doTastaturEreignis(te); unlock(); } } void Bildschirm3D::render() // Zeichnet das Bild { rendering = 1; lock(); renderZeit->messungStart(); // Clear the back buffer. api->beginFrame(fill && (rend || !testRend), fill && (rend3D || !testRend || rend), fillColor); if (rend3D || !testRend || rend) { // Render 3d Objects for (Kam3D* k : *kameras) api->renderKamera(k); rend3D = 0; } // render User Interface Bild* ui = api->zUIRenderBild(); if ((rend || !testRend) && ui) { if (renderZeichnungen) { if (renderOnTop && deckFarbe && (deckFarbe & (fillColor | 0xFF000000)) == deckFarbe) { ui->setAlpha(255 - (unsigned char)(deckFarbe >> 24)); for (Zeichnung* z : *members) z->render(*ui); // zeichnen nach zwischenbuffer ui->releaseAlpha(); } else { for (Zeichnung* z : *members) z->render(*ui); // zeichnen nach zwischenbuffer if (renderOnTop && deckFarbe) ui->alphaRegion( 0, 0, ui->getBreite(), ui->getHeight(), deckFarbe); } 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(); renderZeit->messungEnde(); # ifdef _DEBUG // Logging::trace() << renderZeit->getSekunden() << "\n"; # endif rendering = 0; rend = 0; } #endif