← index
emx/editor/main_window.cpp
Source: emx/editor/main_window.cpp
#include"main_window.hpp"
#include<QPainter>
#include<QMenuBar>
#include<QAction>
#include<QDir>
#include<QApplication>
#include<QMouseEvent>
#include<QKeyEvent>
#include<QFileDialog>
#include<QMessageBox>
#include<QProcess>
#include<QThread>
#include "gfx_file.hpp"

// constructor - (window init)
MainWindow::MainWindow() {
    file_name = "Untitled.lvl";
    map_init = false;
    pos_x = pos_y = 0;
    setGeometry(230, 90, 1280, 720+offset_y);
    setFixedSize(1280, 720+offset_y);
    setWindowIcon(QIcon(":/images/col1.bmp"));
    setWindowTitle(tr("Editor [Please Create/Open a Map]"));

    en.push_back(QImage(":/images/char.png"));

    tool_window = new ToolWindow(this);
    tool_window->setGeometry(10, 90, 150, 480);
    tool_window->show(); 

    connect(tool_window->camera_x, SIGNAL(valueChanged(int)), this, SLOT(cameraChanged(int)));
    connect(tool_window->camera_y, SIGNAL(valueChanged(int)), this, SLOT(cameraChanged(int)));    

    new_window = new NewWindow(&level, this);
    new_window->setMainWindow(this);
    new_window->hide();

    run_window = new RunWindow(this);
    run_window->setMainWindow(this);
    run_window->hide();

    debug_window = new DebugWindow(this);
    debug_window->setGeometry(230, 840+offset_y, 640, 320);
    debug_window->show();

    gfx_window = new GfxWindow(this);
    gfx_window->setMainWindow(this);
    gfx_window->setGeometry(450, 175, 800, 600);
    gfx_window->hide();

    open_window = new OpenWindow(this);
    open_window->setMainWindow(this);
    open_window->hide();

    about_window = new AboutWindow(this);
    about_window->hide();

    pref_window = new PrefWindow(this);
    pref_window->setMainWindow(this);
    pref_window->hide();

    export_window = new ExportWindow(this);
    export_window->setLevel(&level);
    export_window->setMainWindow(this);
    export_window->hide();

    file_menu = menuBar()->addMenu(tr("&File"));
    file_new = new QAction(tr("New Map"), this);
    file_new->setShortcut(tr("Ctrl+N"));
    connect(file_new, SIGNAL(triggered()), this, SLOT(openNewMenu()));
    file_menu->addAction(file_new);
    file_menu->addSeparator();
    //setMouseTracking(true);
    file_load = new QAction(tr("Open Map"), this);
    file_load->setShortcut(tr("Ctrl+O"));
    connect(file_load, SIGNAL(triggered()), this, SLOT(loadFile()));
    file_menu->addAction(file_load);
    file_save = new QAction(tr("Save Map"), this);
    file_save->setShortcut(tr("Ctrl+S"));
    connect(file_save, SIGNAL(triggered()), this, SLOT(saveFile()));
    file_menu->addAction(file_save);
    file_save_as = new QAction(tr("Save Map As"), this);
    file_save_as->setShortcut(tr("Ctrl+A"));
    connect(file_save_as, SIGNAL(triggered()), this, SLOT(saveFileAs()));
    file_menu->addAction(file_save_as);

    export_file = new QAction(tr("E&xport"), this);
    export_file->setShortcut(tr("Ctrl+E"));
    connect(export_file, SIGNAL(triggered()), this, SLOT(exportFile()));

    file_menu->addAction(export_file);
    
    file_menu->addSeparator();
    
    
    file_pref = new QAction(tr("Preferences"), this);

    connect(file_pref, SIGNAL(triggered()), this, SLOT(openPref()));

    file_menu->addAction(file_pref);
    file_menu->addSeparator();

    file_exit = new QAction(tr("E&xit"), this);
    connect(file_exit, SIGNAL(triggered()), this, SLOT(shutdownProgram()));
    file_menu->addAction(file_exit);

    level_menu = menuBar()->addMenu(tr("&Level"));
    level_left = new QAction(tr("Scroll Left"));
    level_left->setShortcut(tr("Ctrl+Left"));
    connect(level_left, SIGNAL(triggered()), this, SLOT(levelLeft()));
    level_menu->addAction(level_left);

    level_right = new QAction(tr("Scroll Right"));
    level_right->setShortcut(tr("Ctrl+Right"));
    connect(level_right, SIGNAL(triggered()), this, SLOT(levelRight()));
    level_menu->addAction(level_right);

    level_up = new QAction(tr("Scroll Up"));
    level_up->setShortcut(tr("Ctrl+Up"));
    connect(level_up, SIGNAL(triggered()), this, SLOT(levelUp()));
    level_menu->addAction(level_up);

    level_down = new QAction(tr("Scroll Down"));
    level_down->setShortcut(tr("Ctrl+Down"));
    connect(level_down, SIGNAL(triggered()), this, SLOT(levelDown()));
    level_menu->addAction(level_down);
    connect(tool_window->hover_object, SIGNAL(stateChanged(int)), this, SLOT(updateMap(int)));

    level_menu->addSeparator();

    level_gfx = new QAction(tr("Level Graphics"));
    connect(level_gfx, SIGNAL(triggered()), this, SLOT(levelGraphicsOpen()));
    level_gfx->setShortcut(tr("Ctrl+G"));
    level_menu->addAction(level_gfx);

    run_menu = menuBar()->addMenu(tr("&Run"));
    run_settings = new QAction(tr("Run &Settings"));
    run_settings->setShortcut(tr("Ctrl+E"));
    connect(run_settings, SIGNAL(triggered()), this, SLOT(runSettings()));
    run_menu->addAction(run_settings);
    run_menu->addSeparator();
    run_exec = new QAction(tr("&Run"));
    run_exec->setShortcut(tr("Ctrl+R"));
    connect(run_exec, SIGNAL(triggered()), this, SLOT(runExec()));
    run_menu->addAction(run_exec);

    view_menu = menuBar()->addMenu(tr("&View"));
    view_show_tool = new QAction(tr("Show ToolBox"));
    view_show_tool->setShortcut(tr("Ctrl+T"));
    connect(view_show_tool, SIGNAL(triggered()), this, SLOT(showTool()));

    view_menu->addAction(view_show_tool);

    help_menu = menuBar()->addMenu(tr("&Help"));
    help_about = new QAction(tr("&About"));
    connect(help_about, SIGNAL(triggered()), this, SLOT(showAbout()));
    help_menu->addAction(help_about);    

    setMouseTracking(true);
    debug_window->clear();
    debug_window->Log("editor: successfully initalized..\n");
    cursor_visible = false;
}
// close event
void MainWindow::closeEvent(QCloseEvent *) {
    if(proc_run == true) {
        proc->terminate();
        proc->waitForFinished();
        proc_run = false;
        delete proc;
        proc = nullptr;
    } else if(modified == true && map_init == true) {
        askSave();
   }
}
// shutdown the program
void MainWindow::shutdownProgram() {
    if(proc_run == true) {
        proc->terminate();
        proc->waitForFinished();
        proc_run = false;
        delete proc;
        proc = nullptr;
    } else if(modified == true && map_init == true) {
        askSave();
    }
    QApplication::exit(0);
}
// ask to save
void MainWindow::askSave() {
    QMessageBox msgbox;
    msgbox.setWindowTitle("Do you wish to save?");
    msgbox.setText("Do you wish to save?");
    msgbox.setIcon(QMessageBox::Icon::Question);
    msgbox.setStandardButtons(QMessageBox::Yes);
    msgbox.addButton(QMessageBox::No);
    msgbox.setDefaultButton(QMessageBox::Yes);
    if(msgbox.exec() == QMessageBox::Yes) {
        saveFile();
        modified = false;
    }
}
// read from standard output on QProcess
void MainWindow::readStdout() {
    if(proc_run) {
        QString data = proc->readAll();
        std::cout << data.toStdString() << "\n";
        debug_window->Log(data);
    }
}

// paint the window to screen
void MainWindow::paintEvent(QPaintEvent *) {

    QPainter paint(this);
    paint.fillRect(QRect(0, 0, 1280, 720), QColor(255,255,255));

    for(int i = 0; i < MAP_WIDTH; ++i) {
        for(int z = 0; z < MAP_HEIGHT; ++z) {
            int x = (i*16)+offset_x;
            int y = (z*16)+offset_y;
            game::Tile *tile = level.at(pos_x+i, pos_y+z);
            if(map_init == false) {
                paint.fillRect(QRect(x, y, 15, 15), QColor(0, 0, 0));
            } else {
                if(images.size()>0 && tile->img < images.size())
                   paint.drawImage((i*16)+offset_x, (z*16)+offset_y, images[tile->img], 0, 0, 16, 16);
            }
        }
    }
    drawLayer1(paint);
    drawLayer2(paint);
    drawLayer3(paint);

    if(cursor_visible == true) {
        
        if(images.size()>0) {
            QImage &img = (tool_window->hover_object->isChecked()) ? col[tool_window->tile_objects->currentIndex()] : images[tool_window->tiles->currentIndex()];
            int cx = draw_pos.x(), cy = draw_pos.y();
            int zx = 0, zy = 0;
            if(game::atPoint(cx, cy-offset_y, 16, 16, zx, zy)) {
                cx = (zx*16)+offset_x, cy = (zy*16)+offset_y;
                paint.drawImage(cx, cy, img);
                int im_width = img.width();
                int im_height = img.height();

                if(tool_window->hover_object->isChecked() == false) {
                    im_width = pen_x * 16;
                    im_height = pen_y * 16;
                }
                paint.fillRect(QRect(cx, cy-1, im_width, 1), QColor(qRgb(255, 255, 255)));
                paint.fillRect(QRect(cx, cy+im_height, im_width, 1), QColor(qRgb(255, 255, 255)));
                paint.fillRect(QRect(cx, cy-1, 1, im_height), QColor(qRgb(255,255,255)));
                paint.fillRect(QRect(cx+im_width, cy-1, 1, im_height), QColor(qRgb(255,255,255)));
            }
        }
    }
}

// update the map
void MainWindow::updateMap(int) {        
    update();
}

// draw layer 1
void MainWindow::drawLayer1(QPainter & paint) {
    for(int i = 0; i < MAP_WIDTH; ++i) {
        for(int z = 0; z < MAP_HEIGHT; ++z) {
            int x = (i*16)+offset_x;
            int y = (z*16)+offset_y;
            game::Tile *tile = level.at(pos_x+i, pos_y+z);
            if(tile != nullptr) {
                if(tile->layers[2] > 0) {
                    paint.drawImage(x, y, en[tile->layers[2]-1]);
                } else if(tile->layers[0] > 0 && tile->layers[0] <= col.size()) {
                    paint.drawImage(x, y, col[tile->layers[0]-1]);
                }
            }
        }
    }
}
 
void MainWindow::drawLayer2(QPainter & /*paint*/) {

}
 
void MainWindow::drawLayer3(QPainter & /*paint*/) {

}

// mouse move event
void MainWindow::mouseMoveEvent(QMouseEvent *e) {
    if(map_init == true) { 
            cursor_visible = true;
            draw_pos = e->pos();
    } 
    if(e->buttons() & Qt::MouseButton::LeftButton) {
        setTile(e->pos());
    } else if(e->buttons() & Qt::MouseButton::RightButton) {
        setObject(e->pos());
    } 
    update();
    
}

// mouse press event
void MainWindow::mousePressEvent(QMouseEvent *e) {
    if(e->button() == Qt::MouseButton::LeftButton) {
        setTile(e->pos());
        update();
    } else if(e->button() == Qt::MouseButton::RightButton) {
        setObject(e->pos());
        update();
    }
}

// mouse leave event
void MainWindow::leaveEvent(QEvent *) {
   cursor_visible = false;
   update();
}

// key press event
void MainWindow::keyPressEvent(QKeyEvent *e) {
    switch(e->key()) {
        case Qt::Key::Key_Left:
        if(pos_x > 0) pos_x--;
        break;
        case Qt::Key::Key_Right:
        if(pos_x < level.width - (1280/16))
        pos_x++;
        break;
        case Qt::Key::Key_Up:
        if(pos_y > 0) pos_y--;
        break;
        case Qt::Key::Key_Down:
        if(pos_y < level.height - (720/16))
        pos_y++;
        break;
    }
    tool_window->camera_x->setSliderPosition(pos_x);
    tool_window->camera_y->setSliderPosition(pos_y);
    updateLabelText();
    update();
}

// set the tile from mouse event
void MainWindow::setTile(const QPoint &pos) {
    if(map_init == true) {
        modified = true;
        int x,y;
        if(game::atPoint(pos.x(), pos.y()-offset_y,16,16,x, y)) {
            game::Tile *tile = level.at(pos_x+x, pos_y+y);
            if(tile != nullptr) {
                //tile->img = 2;
                switch(tool_window->tool->currentIndex()) {
                    case 0: {
                        int pos_start_x = pos_x+x;
                        int pos_start_y = pos_y+y;
                        for(int i = pos_start_x; i < pos_start_x+pen_x; ++i) {
                            for(int z = pos_start_y; z < pos_start_y+pen_y; ++z) {
                                game::Tile *tile = level.at(i, z);
                                if(tile != nullptr) {
                                    tile->setTile(tiles[tool_window->tiles->currentIndex()]);
                                }
                            }
                        }
                    }
                        break;
                    case 1: {
                        int pos_start_x = pos_x+x;
                        int pos_start_y = pos_y+y;
                        for(int i = pos_start_x; i < pos_start_x+pen_x; ++i) {
                            for(int z = pos_start_y; z < pos_start_y+pen_y; ++z) {
                                game::Tile *tile = level.at(i, z);
                                if(tile != nullptr) {
                                    tile->setTile(tiles[0]);
                                }
                            }
                        }
                    }
                        break;
                    case 2:
                       for(int i = pos_x; i < pos_x+(1280/16) && i < level.width; ++i) {
                            for(int z = pos_y; z < pos_y+(720/16) && z < level.height; ++z) {
                                game::Tile *tile = level.at(i, z);
                                if(tile != nullptr) {
                                    *tile = tiles[tool_window->tiles->currentIndex()];
                                }
                            }
                        }
                        break;
                    case 3: {
                        game::Tile *tile = level.at(pos_x+x, pos_y+y);
                        if(tile != nullptr) {
                            tile->layers[2] = 1+tool_window->char_objects->currentIndex();
                        }
                    }
                        break;
                }
            } 
        }
    }
}

// set object triggered by mouse event
void MainWindow::setObject(const QPoint &pos) {
    if(map_init == true) {
        modified = true;
        if(tool_window->tool->currentIndex() == 1) {
            int width = col[tool_window->tile_objects->currentIndex()].width();
            int height = col[tool_window->tile_objects->currentIndex()].height();
            int px = pos.x();
            int py = pos.y()-offset_y;
            for(int i = 0; i < MAP_WIDTH; ++i) {
                for(int z = 0; z < MAP_HEIGHT; ++z) {
                    game::Tile *tile = level.at(pos_x+i, pos_y+z);
                    if(tile != nullptr) {
                        int x = (i*16-16);
                        int y = (z*16-16);
                        if(tile->layers[0] > 0) {
                            if(px >= x && px <= x+width && py >= y && py <= y+height) {
                                tile->layers[0] = 0;
                                return;
                            }
                        }
                    }
                }
            }
            return;
        }
        int x,y;
        if(game::atPoint(pos.x(), pos.y()-offset_y, 16,16, x, y)) {
            game::Tile *tile = level.at(pos_x+x, pos_y+y);
            if(tile != nullptr) {
                switch(tool_window->tool->currentIndex()) {
                    case 0:
                        tile->layers[0] = tool_window->tile_objects->currentIndex()+1;
                    break;
                }
            } 
        }
    }   
}

void MainWindow::exportFile() {
    if(map_init == true)
        export_window->show();
    else {
        // print out message
        QMessageBox msgbox;
        msgbox.setText("Must create/open map to export");
        msgbox.setWindowTitle("Error exporting map");
        msgbox.setIcon(QMessageBox::Icon::Warning);
        msgbox.setWindowIcon(QIcon(":/images/col1.bmp"));
        msgbox.exec();
    }
}


// created a new map
void MainWindow::createdNewMap() { 
    updateTitle();
    tool_window->camera_x->setMinimum(0);
    tool_window->camera_x->setMaximum(level.width-(1280/16));
    tool_window->camera_y->setMinimum(0);
    tool_window->camera_y->setMaximum(level.height-(720/16));
    tool_window->camera_x->setSliderPosition(0);
    tool_window->camera_y->setSliderPosition(0);
    map_init = true;
    update();
    QString txt;
    QTextStream stream(&txt);
    stream << tr("editor: Created new map: [") << level.width << "x" << level.height << "]\n";
    debug_window->Log(txt);
    modified = false;
}

// update title
void MainWindow::updateTitle() {
    QString title;
    QTextStream stream(&title);
    stream << file_name << " - Map [" << level.width << "x" << level.height << "] - " << level.getLevelName().c_str();
    setWindowTitle(title);
    pref_window->setMaxSize(level.width, level.height);

}

// camera scroll bar changed
void MainWindow::cameraChanged(int) {
    pos_x = tool_window->camera_x->sliderPosition();
    pos_y = tool_window->camera_y->sliderPosition();
    updateLabelText();
    update();
}

// update labels
void MainWindow::updateLabelText() {
    QString lbl;
    QTextStream stream(&lbl);
    stream << "Camera X: " << pos_x;
    tool_window->lbl_x->setText(lbl);
    lbl = "";
    stream << "Camera Y: " << pos_y;
    tool_window->lbl_y->setText(lbl);
}

// open new menu
void MainWindow::openNewMenu() {
     if(modified == true) {
        askSave();
    }
    new_window->show();
}
// save file to disk
void MainWindow::saveFile() {

    if(file_name == "Untitled.lvl")
        saveFileAs();
    else {
        if(!level.saveLevel(file_name.toStdString())) {
                QMessageBox msgbox;
                msgbox.setText("Error on load of map");
                msgbox.setWindowTitle("Error loading map");
                msgbox.setIcon(QMessageBox::Icon::Warning);
                msgbox.setWindowIcon(QIcon(":/images/col1.bmp"));
                msgbox.exec();
            } else {
                updateTitle();
                debug_window->Log(tr("editor: Saved level.\n"));
                modified = false;
            }
    }
}
// save file as
void MainWindow::saveFileAs() {
    if(map_init == true) {
        QString filename = QFileDialog::getSaveFileName(nullptr, tr("Save File"), "", tr("LVL (*.lvl)"));
        if(filename != "") {
            if(!level.saveLevel(filename.toStdString())) {
                QMessageBox msgbox;
                msgbox.setText("Error on load of map");
                msgbox.setWindowTitle("Error loading map");
                msgbox.setIcon(QMessageBox::Icon::Warning);
                msgbox.setWindowIcon(QIcon(":/images/col1.bmp"));
                msgbox.exec();
            } else {
                file_name = filename;
                debug_window->Log(tr("editor: Saved level as: ") + file_name + "\n");
                updateTitle();
                modified = false;
            }
        }
    }
}

// TODO: Replace with Open Dialog window
void MainWindow::loadFile() {
    debug_window->Log("editor: Select Level File, Graphics File, Extraction location, and background bitmap\n");
    open_window->show();
}

// load level file from disk
bool MainWindow::loadLevelFile(const QString &filename, const QString &gfx_file, const QString &background, const QString &dir) {
    if(!loadGfx(gfx_file, dir, background)) {
        return false;
    }
    if(level.loadLevelByName(filename.toStdString())) {
        createdNewMap();
        file_name = filename;
        updateTitle();
        update();
    } else {
        QMessageBox msgbox;
        msgbox.setText("Could not load map");
        msgbox.setWindowTitle("Error on load");
        msgbox.setIcon(QMessageBox::Icon::Warning);
        msgbox.setWindowIcon(QIcon(":/images/col1.bmp"));
        msgbox.exec();
        return false;
    }
    modified = false;
    return true;
}

// scroll level  - up
void MainWindow::levelUp() {
   if(pos_y > 0) pos_y--;
    tool_window->camera_y->setSliderPosition(pos_y);
    updateLabelText();
    update();
}
// scroll level  - down 
void MainWindow::levelDown() {
    if(pos_y < level.height - (720/16))
        pos_y++;

    tool_window->camera_y->setSliderPosition(pos_y);
    updateLabelText();
    update();
}
// scroll level  - left
void MainWindow::levelLeft() {
    if(pos_x > 0)
        pos_x--;

    tool_window->camera_x->setSliderPosition(pos_x);
    updateLabelText();
    update();
}
// scroll level  - right
void MainWindow::levelRight() {
    if(pos_x < level.width - (1280/16))
        pos_x++;
    tool_window->camera_x->setSliderPosition(pos_x);
    updateLabelText();
    update();
}
// show level graphics window
void MainWindow::levelGraphicsOpen() {
    gfx_window->show();
}

// show run settings
void MainWindow::runSettings() {
    run_window->show();
}

// process stopped
void MainWindow::procStopped(int, QProcess::ExitStatus) {
    std::cout << proc->readAllStandardOutput().toStdString();
    run_exec->setText(tr("&Run"));
    debug_window->Log("editor: Map successfully exited.\n");
    proc_run = false;
}
// run test executable with map
void MainWindow::runExec() {
    saveFile();
    if(file_name != "Untitled.lvl") {
        QString path = run_window->exec_path->text();
        if(proc_run == false) {
            proc = new QProcess(this);
            QStringList args;
            args << "-p" << (QDir::currentPath() + "/assets") << "-l" << file_name << "-g" << graphics_file << "-b" << run_window->exec_bg->text();
            QStringList argsx;
            QString coord_str;
            QTextStream stream(&coord_str);
            switch(run_window->exec_res->currentIndex()) {
                case 0:
                    argsx << "640" << "360";
                break;
                case 1:
                    argsx << "1280" << "720";
                break;
                case 2:
                    argsx << "1920" << "1080";
                break;
                case 3:
                    argsx << "3840" << "2160";
                    break;
            } 


           QString command_string;
           QTextStream command(&command_string);
            
            command << path+"/scroller";
            args << "-r" << argsx.at(0) + "x" + argsx.at(1);
            for(int i = 0; i < args.length(); ++i) {
                std::cout << args.at(i).toStdString() << " ";
            }
            connect(proc, SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(procStopped(int, QProcess::ExitStatus)));
            connect(proc, SIGNAL(readyReadStandardOutput()), this, SLOT(readStdout()));
            proc->setWorkingDirectory(path+"/");
            proc->start(path+"/scroller", args);
            if(proc->waitForStarted()) {
                run_exec->setText(tr("&Stop"));
                debug_window->clear();
                debug_window->Log(tr("editor: Command: ") + command_string + "\n");
                debug_window->Log("editor: Started Level: " + file_name + "\n");
                proc_run = true;
            }
            else {
                run_exec->setText(tr("&Run"));
                delete proc;
                proc = nullptr;
                QMessageBox msgbox;
                msgbox.setText("Error on execution of map executable");
                msgbox.setWindowTitle("Error loading map");
                msgbox.setIcon(QMessageBox::Icon::Warning);
                msgbox.setWindowIcon(QIcon(":/images/col1.bmp"));
                msgbox.exec();
                debug_window->Log("editor: Could not open map executable file: " + path+"/test-game\n");
            }
        } else {
            proc->terminate();
            proc->waitForFinished();
            proc_run = false;
            delete proc;
            proc = nullptr;
            run_exec->setText(tr("&Run"));
        }
    } else {
        QMessageBox msgbox;
        msgbox.setText("You must create a map");
        msgbox.setWindowTitle("Error loading map");
        msgbox.setIcon(QMessageBox::Icon::Warning);
        msgbox.setWindowIcon(QIcon(":/images/col1.bmp"));
        msgbox.exec();
    }
}

// show gfx window
void MainWindow::showGfx() {
    gfx_window->show();
}

// load graphics file
bool MainWindow::loadGfx(const QString &filename, const QString &dir, const QString &background) {

    background_file = background;
    run_window->exec_bg->setText(background_file);
    game::GfxTable table;
    game::GfxExtract extract;

    if(extract.open(filename.toStdString())) {
        if(extract.extract(table, dir.toStdString())) {
            debug_window->Log("editor: Extracted to dir: " + dir + "\n");
            // load graphics
            if(!images.empty())
                images.erase(images.begin(), images.end());

            if(!col.empty()) 
                col.erase(col.begin(), col.end());

            if(!tiles.empty())
                tiles.erase(tiles.begin(), tiles.end());

            tool_window->tiles->clear();
            tool_window->tile_objects->clear();

            int index[2] = {0};

            for(std::vector<game::GfxItem>::size_type i = 0; i < table.table.size(); ++i) {
                QString text;
                QTextStream stream(&text);
                stream << dir << "/" << table.table[i].filename.c_str();
                uint8_t s = table.table[i].solid;
                switch(table.table[i].obj) {
                    case 0: {
                        QImage img(text);
                        images.push_back(img);
                        QString output;
                        QTextStream out(&output);
                        out << "editor: Loaded: " << text << " size: " << img.width() << "x" << img.height() << "\n";
                        tiles.push_back(game::Tile{0, s, static_cast<uint8_t>(i)});
                        tool_window->tiles->addItem(table.table[i].filename.c_str());
                        QPixmap pix(text);
                        QPixmap img_s = pix.scaled(16,16,Qt::IgnoreAspectRatio);
                        tool_window->tiles->setItemData(index[0]++, img_s, Qt::DecorationRole);
    
                        debug_window->Log(output);
                    }
                    break;
                    case 1: {
                        QImage img(text);
                        QImage img_t = img.convertToFormat(QImage::Format_ARGB32);
                        for(int i = 0; i < img.width(); ++i) {
                            for(int z = 0; z < img.height(); ++z) {
                                if(img_t.pixel(i, z) == qRgb(255, 255, 255)) {
                                    img_t.setPixel(i, z, qRgba(0, 0, 0, 0));
                                }
                            }
                        }
                        col.push_back(img_t);
                        QString output;
                        QTextStream out(&output);
                        out << "editor: Loaded: " << text << " size: " << img.width() << "x" << img.height() << "\n";
                        debug_window->Log(output);
                        QPixmap pix(text);
                        QPixmap img_s = pix.scaled(16,16,Qt::IgnoreAspectRatio);
                        tool_window->tile_objects->addItem(table.table[i].filename.c_str());
                        tool_window->tile_objects->setItemData(index[1]++, img_s, Qt::DecorationRole);
                    }
                    break;
                }
            }

            QString txt;
            QTextStream st(&txt);
            st << "editor: Loaded: " << images.size() << " tiles\neditor: Loaded: " << col.size() << " objects\n";
            debug_window->Log(txt);
            graphics_file = filename;            
            update();
        }
        else {
            QMessageBox msgbox;
            msgbox.setText("Error opening resource file");
            msgbox.setWindowTitle("Error opening file");
            msgbox.setIcon(QMessageBox::Icon::Warning);
            msgbox.exec();
            debug_window->Log("editor: Failed to extract resource file: " + filename + "\n");
            return false;
        }
    } else {
        QMessageBox msgbox;
        msgbox.setText("Error opening resource file");
        msgbox.setWindowTitle("Error opening file");
        msgbox.setIcon(QMessageBox::Icon::Warning);
        msgbox.exec();
        debug_window->Log("editor: Failed to open resource file: " + filename + "\n");
        return false;
    }

    return true;
    
}

// set a new gfx window
void MainWindow::setNewGfx(const QString &filename) {
    new_window->gfx_box->addItem(filename);
    new_window->gfx_box->setCurrentIndex(new_window->gfx_box->count()-1);
}

// show about window
void MainWindow::showAbout() {
    debug_window->Log("editor: written by Jared Bruni.\n");
    about_window->show();
}

// open preferences
void MainWindow::openPref() {
    pref_window->show();
}

// set cursor pen size in 16x16 tiles
void MainWindow::setPenSize(int px, int py) {
    pen_x = px;
    pen_y = py;
    QString text;
    QTextStream stream(&text);
    stream << tr("editor: Set Pencil Size: ") << pen_x << ", " << pen_y << "\n";
    debug_window->Log(text);
}

// show tool window
void MainWindow::showTool() {
    tool_window->show();
}