From 67f7fca399b5ba8f57b4e03afd1353b91ceb6d54 Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 11 Sep 2018 20:37:36 -0400 Subject: [PATCH 01/16] add HealLocation fly spots --- editor.h | 1 + event.cpp | 28 +++++++ event.h | 4 + heallocation.cpp | 19 +++++ heallocation.h | 23 ++++++ mainwindow.cpp | 13 +++- map.h | 1 + neweventtoolbutton.cpp | 13 ++++ neweventtoolbutton.h | 2 + parseutil.cpp | 18 +++++ parseutil.h | 3 + pretmap.pro | 106 ++++++++++++------------- project.cpp | 117 ++++++++++++++++++++++++++++ project.h | 3 + resources/images/Entities_16x16.png | Bin 274 -> 490 bytes 15 files changed, 295 insertions(+), 56 deletions(-) create mode 100644 heallocation.cpp create mode 100644 heallocation.h diff --git a/editor.h b/editor.h index 863b096f..29b832dc 100755 --- a/editor.h +++ b/editor.h @@ -130,6 +130,7 @@ private: void updateMirroredConnection(Connection*, QString, QString, bool isDelete = false); Event* createNewObjectEvent(); Event* createNewWarpEvent(); + Event* createNewHealLocationEvent(); Event* createNewCoordScriptEvent(); Event* createNewCoordWeatherEvent(); Event* createNewSignEvent(); diff --git a/event.cpp b/event.cpp index e26b4540..c92b9a26 100755 --- a/event.cpp +++ b/event.cpp @@ -1,4 +1,5 @@ #include "event.h" +#include "map.h" QString EventType::Object = "event_object"; QString EventType::Warp = "event_warp"; @@ -7,6 +8,7 @@ QString EventType::CoordWeather = "event_trap_weather"; QString EventType::Sign = "event_sign"; QString EventType::HiddenItem = "event_hidden_item"; QString EventType::SecretBase = "event_secret_base"; +QString EventType::HealLocation = "event_heal_location"; Event::Event() { @@ -19,6 +21,8 @@ Event* Event::createNewEvent(QString event_type, QString map_name) event = createNewObjectEvent(); } else if (event_type == EventType::Warp) { event = createNewWarpEvent(map_name); + } else if (event_type == EventType::HealLocation) { + event = createNewHealLocationEvent(map_name); } else if (event_type == EventType::CoordScript) { event = createNewCoordScriptEvent(); } else if (event_type == EventType::CoordWeather) { @@ -64,6 +68,15 @@ Event* Event::createNewWarpEvent(QString map_name) return event; } +Event* Event::createNewHealLocationEvent(QString map_name) +{ + Event *event = new Event; + event->put("event_group_type", "heal_event_group"); + event->put("event_type", EventType::HealLocation); + event->put("loc_name", QString(Map::mapConstantFromName(map_name)).remove(0,4)); + return event; +} + Event* Event::createNewCoordScriptEvent() { Event *event = new Event; @@ -150,6 +163,21 @@ QString Event::buildWarpEventMacro(QMap *mapNamesToMapConstant return text; } +HealLocation Event::buildHealLocation() +{ + HealLocation hl; + hl.name = this->get("loc_name"); + try { + hl.index = this->get("index").toInt(); + } + catch(...) { + hl.index = 0; + } + hl.x = this->get("x").toInt(); + hl.y = this->get("y").toInt(); + return hl; +} + QString Event::buildCoordScriptEventMacro() { QString text = ""; diff --git a/event.h b/event.h index 03313d27..13aa114a 100755 --- a/event.h +++ b/event.h @@ -1,6 +1,7 @@ #ifndef EVENT_H #define EVENT_H +#include "heallocation.h" #include #include #include @@ -16,6 +17,7 @@ public: static QString Sign; static QString HiddenItem; static QString SecretBase; + static QString HealLocation; }; class Event @@ -54,6 +56,7 @@ public: static Event* createNewEvent(QString, QString); static Event* createNewObjectEvent(); static Event* createNewWarpEvent(QString); + static Event* createNewHealLocationEvent(QString); static Event* createNewCoordScriptEvent(); static Event* createNewCoordWeatherEvent(); static Event* createNewSignEvent(); @@ -62,6 +65,7 @@ public: QString buildObjectEventMacro(int); QString buildWarpEventMacro(QMap*); + HealLocation buildHealLocation(); QString buildCoordScriptEventMacro(); QString buildCoordWeatherEventMacro(); QString buildSignEventMacro(); diff --git a/heallocation.cpp b/heallocation.cpp new file mode 100644 index 00000000..7652b96a --- /dev/null +++ b/heallocation.cpp @@ -0,0 +1,19 @@ +#include "heallocation.h" + +//HealLocation::HealLocation() {} + +HealLocation::HealLocation(QString map, int i, size_t x0, size_t y0) { + + name = map; + index = i; + x = x0; + y = y0; + +} + +QDebug operator<<(QDebug debug, const HealLocation &hl) { + + debug << "HealLocation_" + hl.name << "(" << hl.x << ',' << hl.y << ")"; + return debug; + +} diff --git a/heallocation.h b/heallocation.h new file mode 100644 index 00000000..bf01b30a --- /dev/null +++ b/heallocation.h @@ -0,0 +1,23 @@ +#ifndef HEALLOCATION_H +#define HEALLOCATION_H + +#include +#include + +class HealLocation { + +public: + HealLocation()=default; + HealLocation(QString, int, size_t, size_t); + friend QDebug operator<<(QDebug debug, const HealLocation &hl); + +public: + //QString group; + QString name; + int index; + size_t x; + size_t y; + +}; + +#endif // HEALLOCATION_H diff --git a/mainwindow.cpp b/mainwindow.cpp index b9979dc3..06a86926 100755 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -862,11 +862,16 @@ void MainWindow::on_toolButton_deleteObject_clicked() if (editor && editor->selected_events) { if (editor->selected_events->length()) { for (DraggablePixmapItem *item : *editor->selected_events) { - editor->deleteEvent(item->event); - if (editor->scene->items().contains(item)) { - editor->scene->removeItem(item); + if (item->event->get("event_type") != EventType::HealLocation) { + editor->deleteEvent(item->event); + if (editor->scene->items().contains(item)) { + editor->scene->removeItem(item); + } + editor->selected_events->removeOne(item); + } + else { // don't allow deletion of heal locations + qDebug() << "Cannot delete event of type " << item->event->get("event_type"); } - editor->selected_events->removeOne(item); } updateSelectedObjects(); } diff --git a/map.h b/map.h index 82e70675..017c7b8b 100755 --- a/map.h +++ b/map.h @@ -128,6 +128,7 @@ public: QString layout_id; QString location; QString requiresFlash; + QString isFlyable; // TODO: implement this QString weather; QString type; QString unknown; diff --git a/neweventtoolbutton.cpp b/neweventtoolbutton.cpp index 51d4ee2b..cfd0adab 100644 --- a/neweventtoolbutton.cpp +++ b/neweventtoolbutton.cpp @@ -23,6 +23,12 @@ void NewEventToolButton::initButton() this->newWarpAction->setIcon(QIcon(":/icons/add.ico")); connect(this->newWarpAction, SIGNAL(triggered(bool)), this, SLOT(newWarp())); + /* // disable this functionality for now + this->newHealLocationAction = new QAction("New Heal Location", this); + this->newHealLocationAction->setIcon(QIcon(":/icons/add.ico")); + connect(this->newHealLocationAction, SIGNAL(triggered(bool)), this, SLOT(newHealLocation())); + */ + this->newCoordScriptAction = new QAction("New Coord Script", this); this->newCoordScriptAction->setIcon(QIcon(":/icons/add.ico")); connect(this->newCoordScriptAction, SIGNAL(triggered(bool)), this, SLOT(newCoordScript())); @@ -46,6 +52,7 @@ void NewEventToolButton::initButton() QMenu *alignMenu = new QMenu(); alignMenu->addAction(this->newObjectAction); alignMenu->addAction(this->newWarpAction); + //alignMenu->addAction(this->newHealLocationAction); alignMenu->addAction(this->newCoordScriptAction); alignMenu->addAction(this->newCoordWeatherAction); alignMenu->addAction(this->newSignAction); @@ -72,6 +79,12 @@ void NewEventToolButton::newWarp() emit newEventAdded(this->selectedEventType); } +void NewEventToolButton::newHealLocation() +{ + this->selectedEventType = EventType::HealLocation; + emit newEventAdded(this->selectedEventType); +} + void NewEventToolButton::newCoordScript() { this->selectedEventType = EventType::CoordScript; diff --git a/neweventtoolbutton.h b/neweventtoolbutton.h index f4bb7f55..d75be3b4 100644 --- a/neweventtoolbutton.h +++ b/neweventtoolbutton.h @@ -14,6 +14,7 @@ public: public slots: void newObject(); void newWarp(); + void newHealLocation(); void newCoordScript(); void newCoordWeather(); void newSign(); @@ -25,6 +26,7 @@ private: QString selectedEventType; QAction *newObjectAction; QAction *newWarpAction; + QAction *newHealLocationAction; QAction *newCoordScriptAction; QAction *newCoordWeatherAction; QAction *newSignAction; diff --git a/parseutil.cpp b/parseutil.cpp index 9b481159..15c24b16 100755 --- a/parseutil.cpp +++ b/parseutil.cpp @@ -68,6 +68,24 @@ int ParseUtil::evaluateDefine(QString define, QMap* knownDefines) return evaluatePostfix(postfixExpression); } +// arg here is the text in the file src/data/heal_locations.h +// returns a list of HealLocations (mapname, x, y) +QList* ParseUtil::parseHealLocs(QString text) { + QList *parsed = new QList; + QStringList lines = text.split('\n'); + + int i = 1; + for (auto line : lines){ + if (line.contains("MAP_GROUP")){ + QList li = line.replace(" ","").chopped(2).remove('{').split(','); + HealLocation hloc = HealLocation(li[1].remove("MAP_NUM(").remove(")"), i, li[2].toInt(), li[3].toInt()); + parsed->append(hloc); + i++; + } + } + return parsed; +} + QList ParseUtil::tokenizeExpression(QString expression, QMap* knownIdentifiers) { QList tokens; diff --git a/parseutil.h b/parseutil.h index dfd52c16..23e095fc 100755 --- a/parseutil.h +++ b/parseutil.h @@ -1,6 +1,8 @@ #ifndef PARSEUTIL_H #define PARSEUTIL_H +#include "heallocation.h" + #include #include #include @@ -35,6 +37,7 @@ public: void strip_comment(QString*); QList* parseAsm(QString); int evaluateDefine(QString, QMap*); + QList* parseHealLocs(QString); private: QList tokenizeExpression(QString expression, QMap* knownIdentifiers); QList generatePostfix(QList tokens); diff --git a/pretmap.pro b/pretmap.pro index 96014047..9d3ae04e 100755 --- a/pretmap.pro +++ b/pretmap.pro @@ -1,52 +1,54 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2016-08-31T15:19:13 -# -#------------------------------------------------- - -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -TARGET = pretmap -TEMPLATE = app - - -SOURCES += main.cpp\ - mainwindow.cpp \ - project.cpp \ - map.cpp \ - blockdata.cpp \ - block.cpp \ - tileset.cpp \ - tile.cpp \ - event.cpp \ - editor.cpp \ - objectpropertiesframe.cpp \ - graphicsview.cpp \ - parseutil.cpp \ - neweventtoolbutton.cpp \ - noscrollcombobox.cpp \ - noscrollspinbox.cpp - -HEADERS += mainwindow.h \ - project.h \ - map.h \ - blockdata.h \ - block.h \ - tileset.h \ - tile.h \ - event.h \ - editor.h \ - objectpropertiesframe.h \ - graphicsview.h \ - parseutil.h \ - neweventtoolbutton.h \ - noscrollcombobox.h \ - noscrollspinbox.h - -FORMS += mainwindow.ui \ - objectpropertiesframe.ui - -RESOURCES += \ - resources/images.qrc +#------------------------------------------------- +# +# Project created by QtCreator 2016-08-31T15:19:13 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = pretmap +TEMPLATE = app + + +SOURCES += main.cpp\ + mainwindow.cpp \ + project.cpp \ + map.cpp \ + blockdata.cpp \ + block.cpp \ + tileset.cpp \ + tile.cpp \ + event.cpp \ + editor.cpp \ + objectpropertiesframe.cpp \ + graphicsview.cpp \ + parseutil.cpp \ + neweventtoolbutton.cpp \ + noscrollcombobox.cpp \ + noscrollspinbox.cpp \ + heallocation.cpp + +HEADERS += mainwindow.h \ + project.h \ + map.h \ + blockdata.h \ + block.h \ + tileset.h \ + tile.h \ + event.h \ + editor.h \ + objectpropertiesframe.h \ + graphicsview.h \ + parseutil.h \ + neweventtoolbutton.h \ + noscrollcombobox.h \ + noscrollspinbox.h \ + heallocation.h + +FORMS += mainwindow.ui \ + objectpropertiesframe.ui + +RESOURCES += \ + resources/images.qrc diff --git a/project.cpp b/project.cpp index fd352dfa..bdd4c8ec 100755 --- a/project.cpp +++ b/project.cpp @@ -501,6 +501,82 @@ void Project::saveMapConstantsHeader() { saveTextFile(root + "/include/constants/maps.h", text); } +// saves heal location coords in root + /src/data/heal_locations.h +// and indexes as defines in root + /include/constants/heal_locations.h +void Project::saveHealLocationStruct(Map *map) { + QString tab = QString(" "); + + QString data_text = QString("static const struct HealLocation sHealLocations[] =\n{\n"); + + QString constants_text = QString("#ifndef GUARD_CONSTANTS_HEAL_LOCATIONS_H\n"); + constants_text += QString("#define GUARD_CONSTANTS_HEAL_LOCATIONS_H\n\n"); + + QMap flyableMapsDupes; + QSet flyableMapsUnique; + + // erase old location from flyableMaps list + // set flyableMapsDupes and flyableMapsUnique + for (auto it = flyableMaps->begin(); it != flyableMaps->end(); it++) { + HealLocation loc = *it; + QString xname = loc.name; + if (flyableMapsUnique.contains(xname)) { + flyableMapsDupes[xname] = 1; + } + if (xname == QString(mapNamesToMapConstants->value(map->name)).remove(0,4)) { + it = flyableMaps->erase(it) - 1; + } + else { + flyableMapsUnique.insert(xname); + } + } + + // set new location in flyableMapsList + if (map->events["heal_event_group"].length() > 0) { + QList* flymaps = flyableMaps; + + for (Event *heal : map->events["heal_event_group"]) { + HealLocation hl = heal->buildHealLocation(); + flymaps->insert(hl.index - 1, hl); + } + flyableMaps = flymaps; + } + + int i = 1; + + for (auto map_in : *flyableMaps) { + data_text += QString(" {MAP_GROUP(%1), MAP_NUM(%1), %2, %3},\n") + .arg(map_in.name) + .arg(map_in.x) + .arg(map_in.y); + + QString ending = QString(""); + + // must add _1 / _2 for maps that have duplicates + if (flyableMapsDupes.keys().contains(map_in.name)) { + // map contains multiple heal locations + ending += QString("_%1").arg(flyableMapsDupes[map_in.name]); + flyableMapsDupes[map_in.name]++; + } + if (map_in.index != 0) { + constants_text += QString("#define HEAL_LOCATION_%1 %2\n") + .arg(map_in.name + ending) + .arg(map_in.index); + } + else { + constants_text += QString("#define HEAL_LOCATION_%1 %2\n") + .arg(map_in.name + ending) + .arg(i); + } + i++; + } + + data_text += QString("};\n"); + constants_text += QString("\n#endif // GUARD_CONSTANTS_HEAL_LOCATIONS_H\n"); + + saveTextFile(root + "/src/data/heal_locations.h", data_text); + saveTextFile(root + "/include/constants/heal_locations.h", constants_text); +} + void Project::loadMapTilesets(Map* map) { if (map->layout->has_unsaved_changes) { return; @@ -947,6 +1023,10 @@ void Project::readMapGroups() { groupNames = groups; groupedMapNames = groupedMaps; mapNames = maps; + + QString hltext = readTextFile(root + QString("/src/data/heal_locations.h")); + QList* hl = parser->parseHealLocs(hltext); + flyableMaps = hl; } Map* Project::addNewMapToGroup(QString mapName, int groupNum) { @@ -1221,6 +1301,8 @@ void Project::loadEventPixmaps(QList objects) { object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(32, 0, 16, 16); } else if (event_type == EventType::Sign || event_type == EventType::HiddenItem || event_type == EventType::SecretBase) { object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(48, 0, 16, 16); + } else if (event_type == EventType::HealLocation) { + object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(64, 0, 16, 16); } if (event_type == EventType::Object) { @@ -1309,6 +1391,17 @@ void Project::saveMapEvents(Map *map) { .arg(bgEventsLabel); saveTextFile(path, text); + + // save heal event changes + if (map->events["heal_event_group"].length() > 0) { + QList* flymaps = flyableMaps; + for (Event *heal : map->events["heal_event_group"]) { + HealLocation hl = heal->buildHealLocation(); + flymaps->append(hl); + } + flyableMaps = flymaps; + } + saveHealLocationStruct(map); } void Project::readMapEvents(Map *map) { @@ -1379,6 +1472,29 @@ void Project::readMapEvents(Map *map) { } } + map->events["heal_event_group"].clear(); + + for (auto it = flyableMaps->begin(); it != flyableMaps->end(); it++) { + + HealLocation loc = *it; + + //if TRUE map is flyable / has healing location + if (loc.name == QString(mapNamesToMapConstants->value(map->name)).remove(0,4)) { + Event *heal = new Event; + heal->put("map_name", map->name); + heal->put("x", loc.x); + heal->put("y", loc.y); + heal->put("loc_name", loc.name); + heal->put("index", loc.index); + heal->put("elevation", 3); // TODO: change this? + heal->put("destination_map_name", mapConstantsToMapNames->value(map->name)); + heal->put("event_group_type", "heal_event_group"); + heal->put("event_type", EventType::HealLocation); + map->events["heal_event_group"].append(heal); + } + + } + QList *coords = getLabelMacros(parseAsm(text), coordEventsLabel); map->events["coord_event_group"].clear(); for (QStringList command : *coords) { @@ -1455,6 +1571,7 @@ void Project::readMapEvents(Map *map) { void Project::setNewMapEvents(Map *map) { map->events["object_event_group"].clear(); map->events["warp_event_group"].clear(); + map->events["heal_event_group"].clear(); map->events["coord_event_group"].clear(); map->events["bg_event_group"].clear(); } diff --git a/project.h b/project.h index 90796295..d965e4c6 100755 --- a/project.h +++ b/project.h @@ -3,6 +3,7 @@ #include "map.h" #include "blockdata.h" +#include "heallocation.h" #include #include @@ -17,6 +18,7 @@ public: QMap *map_groups; QList groupedMapNames; QStringList *mapNames = NULL; + QList *flyableMaps = NULL; // can't be a QMap because duplicates QMap* mapConstantsToMapNames; QMap* mapNamesToMapConstants; QList mapLayoutsTable; @@ -77,6 +79,7 @@ public: void saveAllMapLayouts(); void saveMapGroupsTable(); void saveMapConstantsHeader(); + void saveHealLocationStruct(Map*); QList* parseAsm(QString text); QStringList getSongNames(); diff --git a/resources/images/Entities_16x16.png b/resources/images/Entities_16x16.png index db480f6e7b609a066e504367fb1338fe629d60b2..2d35d31d63e3699af7a0d0bd8880ac270403fa75 100755 GIT binary patch literal 490 zcmVME?3!eUtof542}5RoeLxW;q`|R-+mYv@ht$WOS2^V>Gd7J;=E1r z--aCkwdFOE-+S%?uxpHgf{_Bh$kLbDxQJvzyL77kX9 zM%&%leeM#2meS3+$=4IOuG8;l4Z{rof>KIE7PijI*kBQfr(pO&>zk>RazwnwL<_JA zks$JaT$50U)%uns4T?p5{N)7_R{*N&$JE zN5hg-kuKOM!1_3pw?XlF<~4iOYFGmJYl$o>WrHlv1r#mbWW6;dnH*=hC=aYL#xfIV z&hEMgK*TZHBclxeINtP^lM`8EjAcyLQj>lDa$++~lB4vd4yW|EcZ~y=R literal 274 zcmV+t0qy>YP)J5hbP53Dm7H1u76_11A|jb<0Px6M14y4S z`HKMD>;lMj*8re*z=^N{xKlFx41lkm7LwoI1_-whU*`qDV>JvFfNz@@01RLIr!d5R zfLwhg0Hd8O0DlWr1>i-;0765|Pr1?z Date: Tue, 11 Sep 2018 20:39:41 -0400 Subject: [PATCH 02/16] zero-base index warps --- mainwindow.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mainwindow.cpp b/mainwindow.cpp index b9979dc3..ed84e18f 100755 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -647,9 +647,12 @@ void MainWindow::updateSelectedObjects() { QString event_type = item->event->get("event_type"); QString event_group_type = item->event->get("event_group_type"); QString map_name = item->event->get("map_name"); + int event_offs; + if (event_type == "event_warp") { event_offs = 0; } + else { event_offs = 1; } frame->ui->label_name->setText( QString("%1: %2 %3") - .arg(editor->project->getMap(map_name)->events.value(event_group_type).indexOf(item->event) + 1) + .arg(editor->project->getMap(map_name)->events.value(event_group_type).indexOf(item->event) + event_offs) .arg(map_name) .arg(event_type) ); @@ -707,8 +710,8 @@ void MainWindow::updateSelectedObjects() { fields << "sight_radius_tree_id"; } else if (event_type == EventType::Warp) { - fields << "destination_warp"; fields << "destination_map_name"; + fields << "destination_warp"; } else if (event_type == EventType::CoordScript) { fields << "script_label"; From 378d5bb660ee2e53c65e538ff0154bfd3ccfe69b Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 11 Sep 2018 20:41:58 -0400 Subject: [PATCH 03/16] Open Map Scripts button --- mainwindow.cpp | 34 ++++++++++++++++++++++++++++++++++ mainwindow.h | 3 +++ mainwindow.ui | 49 ++++++++++++++++++++++++++++++++++++------------- 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/mainwindow.cpp b/mainwindow.cpp index b9979dc3..7b09396c 100755 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -15,8 +15,11 @@ #include #include #include +#include #include #include +#include +#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), @@ -549,6 +552,32 @@ void MainWindow::redo() { editor->redo(); } +// Open current map scripts in system default editor for .inc files +void MainWindow::openInTextEditor() { + QProcess *process = new QProcess(this); + QSysInfo sysInfo; + process->setWorkingDirectory(editor->project->root); + + #ifdef Q_OS_DARWIN + QString cmd = "open "; + #elif defined Q_OS_LINUX + QString cmd = "xdg-open "; + #elif defined Q_OS_WIN + QString cmd = "cmd /c start \""; + #else + qDebug() << "Functionality is not available with this OS (" + << sysInfo.productType() << ")"; + #endif + + cmd += "data/maps/" + editor->map->name + "/scripts.inc"; + + #ifdef Q_OS_WIN + cmd += "\""; + #endif + + process->start(cmd); +} + void MainWindow::on_action_Save_triggered() { editor->save(); updateMapList(); @@ -873,6 +902,11 @@ void MainWindow::on_toolButton_deleteObject_clicked() } } +void MainWindow::on_toolButton_Open_Scripts_clicked() +{ + openInTextEditor(); +} + void MainWindow::on_toolButton_Paint_clicked() { editor->map_edit_mode = "paint"; diff --git a/mainwindow.h b/mainwindow.h index b8a12f8b..be782842 100755 --- a/mainwindow.h +++ b/mainwindow.h @@ -37,6 +37,8 @@ private slots: void undo(); void redo(); + void openInTextEditor(); + void onLoadMapRequested(QString, QString); void onMapChanged(Map *map); void onMapNeedsRedrawing(Map *map); @@ -59,6 +61,7 @@ private slots: void on_actionRedo_triggered(); void on_toolButton_deleteObject_clicked(); + void on_toolButton_Open_Scripts_clicked(); void addNewEvent(QString); void updateSelectedObjects(); diff --git a/mainwindow.ui b/mainwindow.ui index f3f19222..d24583d2 100755 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -334,8 +334,8 @@ 0 0 - 429 - 620 + 462 + 599 @@ -708,7 +708,7 @@ 0 0 - 315 + 252 86 @@ -812,10 +812,10 @@ - 0 + 8 0 - 365 - 405 + 323 + 368 @@ -1050,8 +1050,8 @@ 0 0 - 381 - 657 + 371 + 643 @@ -1216,8 +1216,8 @@ 0 0 - 420 - 584 + 410 + 560 @@ -1330,6 +1330,29 @@ + + + + Open Map Scripts + + + false + + + + + + + Qt::Horizontal + + + + 20 + 20 + + + + @@ -1849,8 +1872,8 @@ 0 0 - 826 - 557 + 818 + 539 @@ -2022,7 +2045,7 @@ 0 0 1117 - 21 + 22 From f5f763d32c15679ed60aedb95955a0770823549b Mon Sep 17 00:00:00 2001 From: garak Date: Tue, 11 Sep 2018 20:52:57 -0400 Subject: [PATCH 04/16] add move drag mode with changing cursor --- editor.cpp | 2 + editor.h | 3 ++ mainwindow.cpp | 83 +++++++++++++++++++++++++++++++++++++++ mainwindow.h | 9 +++++ mainwindow.ui | 76 +++++++++++++++++++++++++++++------ map.cpp | 5 ++- map.h | 3 ++ resources/icons/move.ico | Bin 0 -> 1150 bytes resources/images.qrc | 1 + 9 files changed, 167 insertions(+), 15 deletions(-) create mode 100644 resources/icons/move.ico diff --git a/editor.cpp b/editor.cpp index 962907d9..a3652d10 100755 --- a/editor.cpp +++ b/editor.cpp @@ -1484,9 +1484,11 @@ void MapPixmapItem::updateCurHoveredTile(QPointF pos) { void MapPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { updateCurHoveredTile(event->pos()); + setCursor(editor->cursor); } void MapPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { map->clearHoveredTile(); + unsetCursor(); } void MapPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { QPointF pos = event->pos(); diff --git a/editor.h b/editor.h index 863b096f..0bc22ddb 100755 --- a/editor.h +++ b/editor.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "project.h" #include "ui_mainwindow.h" @@ -108,6 +109,8 @@ public: QList *copiedMetatileSelection = new QList; QString map_edit_mode; + QString prev_edit_mode; + QCursor cursor; void objectsView_onMousePress(QMouseEvent *event); void objectsView_onMouseMove(QMouseEvent *event); diff --git a/mainwindow.cpp b/mainwindow.cpp index b9979dc3..e47eb792 100755 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -17,6 +17,8 @@ #include #include #include +#include +#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), @@ -31,6 +33,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->newEventToolButton, SIGNAL(newEventAdded(QString)), this, SLOT(addNewEvent(QString))); new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Z), this, SLOT(redo())); + new QShortcut(Qt::Key_M, this, SLOT(toggleEditModeMove())); editor = new Editor(ui); connect(editor, SIGNAL(objectsChanged()), this, SLOT(updateSelectedObjects())); @@ -589,6 +592,31 @@ void MainWindow::on_actionRedo_triggered() redo(); } +void MainWindow::on_actionZoom_In_triggered() { + scaleMapView(1); +} + +void MainWindow::on_actionZoom_Out_triggered() { + scaleMapView(-1); +} + +void MainWindow::scaleMapView(int s) { + editor->map->scale_exp += s; + + double base = (double)editor->map->scale_base; + double exp = editor->map->scale_exp; + double sfactor = pow(base,s); + + ui->graphicsView_Map->scale(sfactor,sfactor); + ui->graphicsView_Objects_Map->scale(sfactor,sfactor); + + ui->graphicsView_Map->setFixedSize((editor->scene->width() + 2) * pow(base,exp), + (editor->scene->height() + 2) * pow(base,exp)); + + ui->graphicsView_Objects_Map->setFixedSize((editor->scene->width() + 2) * pow(base,exp), + (editor->scene->height() + 2) * pow(base,exp)); +} + void MainWindow::addNewEvent(QString event_type) { if (editor) { @@ -876,24 +904,60 @@ void MainWindow::on_toolButton_deleteObject_clicked() void MainWindow::on_toolButton_Paint_clicked() { editor->map_edit_mode = "paint"; + editor->cursor = QCursor(QPixmap(":/icons/pencil.ico"), 0, 14); + + ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + QScroller::ungrabGesture(ui->scrollArea); + checkToolButtons(); } void MainWindow::on_toolButton_Select_clicked() { editor->map_edit_mode = "select"; + editor->cursor = QCursor(QPixmap(":/icons/cursor.ico"), 0, 0); + + ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + QScroller::ungrabGesture(ui->scrollArea); + checkToolButtons(); } void MainWindow::on_toolButton_Fill_clicked() { editor->map_edit_mode = "fill"; + editor->cursor = QCursor(QPixmap(":/icons/fill_color.ico"), 12, 10); + + ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + QScroller::ungrabGesture(ui->scrollArea); + checkToolButtons(); } void MainWindow::on_toolButton_Dropper_clicked() { editor->map_edit_mode = "pick"; + editor->cursor = QCursor(QPixmap(":/icons/pipette.ico"), 1, 14); + + ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + QScroller::ungrabGesture(ui->scrollArea); + + checkToolButtons(); +} + +void MainWindow::on_toolButton_Move_clicked() +{ + editor->map_edit_mode = "move"; + editor->cursor = QCursor(QPixmap(":/icons/move.ico"), 7, 7); + + ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + QScroller::grabGesture(ui->scrollArea, QScroller::LeftMouseButtonGesture); + checkToolButtons(); } @@ -902,6 +966,25 @@ void MainWindow::checkToolButtons() { ui->toolButton_Select->setChecked(editor->map_edit_mode == "select"); ui->toolButton_Fill->setChecked(editor->map_edit_mode == "fill"); ui->toolButton_Dropper->setChecked(editor->map_edit_mode == "pick"); + ui->toolButton_Move->setChecked(editor->map_edit_mode == "move"); +} + +void MainWindow::toggleEditModeMove() { + if (editor->map_edit_mode == "move") { + if (editor->prev_edit_mode == "paint") { + on_toolButton_Paint_clicked(); + } else if (editor->prev_edit_mode == "fill") { + on_toolButton_Fill_clicked(); + } else if (editor->prev_edit_mode == "pick") { + on_toolButton_Dropper_clicked(); + } else if (editor->prev_edit_mode == "select") { + on_toolButton_Select_clicked(); + } + } + else { + editor->prev_edit_mode = editor->map_edit_mode; + on_toolButton_Move_clicked(); + } } void MainWindow::onLoadMapRequested(QString mapName, QString fromMapName) { diff --git a/mainwindow.h b/mainwindow.h index b8a12f8b..d6509a50 100755 --- a/mainwindow.h +++ b/mainwindow.h @@ -37,6 +37,8 @@ private slots: void undo(); void redo(); + void toggleEditModeMove(); + void onLoadMapRequested(QString, QString); void onMapChanged(Map *map); void onMapNeedsRedrawing(Map *map); @@ -58,6 +60,9 @@ private slots: void on_actionRedo_triggered(); + void on_actionZoom_In_triggered(); + void on_actionZoom_Out_triggered(); + void on_toolButton_deleteObject_clicked(); void addNewEvent(QString); @@ -71,6 +76,8 @@ private slots: void on_toolButton_Dropper_clicked(); + void on_toolButton_Move_clicked(); + void onOpenMapListContextMenu(const QPoint &point); void onAddNewMapToGroupClick(QAction* triggeredAction); void onTilesetChanged(QString); @@ -124,6 +131,8 @@ private: void displayMapProperties(); void checkToolButtons(); + + void scaleMapView(int); }; enum MapListUserRoles { diff --git a/mainwindow.ui b/mainwindow.ui index f3f19222..ad6b7925 100755 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -245,6 +245,23 @@ + + + + <html><head/><body><p>Move</p><p>Click to drag map around.</p></body></html> + + + ... + + + + :/icons/move.ico:/icons/move.ico + + + true + + + @@ -334,8 +351,8 @@ 0 0 - 429 - 620 + 492 + 599 @@ -362,9 +379,18 @@ 0 + + false + false + + QAbstractScrollArea::AdjustIgnored + + + QGraphicsView::NoDrag + @@ -708,7 +734,7 @@ 0 0 - 315 + 222 86 @@ -812,10 +838,10 @@ - 0 + 8 0 - 365 - 405 + 293 + 368 @@ -1050,8 +1076,8 @@ 0 0 - 381 - 657 + 371 + 643 @@ -1216,8 +1242,8 @@ 0 0 - 420 - 584 + 410 + 560 @@ -1849,8 +1875,8 @@ 0 0 - 826 - 557 + 818 + 539 @@ -2022,7 +2048,7 @@ 0 0 1117 - 21 + 22 @@ -2044,8 +2070,16 @@ + + + View + + + + + @@ -2104,6 +2138,22 @@ Export Map Image... + + + Zoom In + + + + + + + + + Zoom Out + + + - + + diff --git a/map.cpp b/map.cpp index f114884f..626724f2 100755 --- a/map.cpp +++ b/map.cpp @@ -608,10 +608,11 @@ bool Map::hasUnsavedChanges() { } void Map::hoveredTileChanged(int x, int y, int block) { - emit statusBarMessage(QString("X: %1, Y: %2, Metatile: 0x%3") + emit statusBarMessage(QString("X: %1, Y: %2, Metatile: 0x%3, Scale = %4x") .arg(x) .arg(y) - .arg(QString("%1").arg(block, 3, 16, QChar('0')).toUpper())); + .arg(QString("%1").arg(block, 3, 16, QChar('0')).toUpper()) + .arg(QString::number(pow(this->scale_base,this->scale_exp)))); } void Map::clearHoveredTile() { diff --git a/map.h b/map.h index 82e70675..550e6a9b 100755 --- a/map.h +++ b/map.h @@ -9,6 +9,7 @@ #include #include #include +#include class HistoryItem { public: @@ -134,6 +135,8 @@ public: QString show_location; QString battle_scene; MapLayout *layout; + int scale_exp = 0; + double scale_base = sqrt(2); // adjust scale factor with this bool isPersistedToFile = true; diff --git a/resources/icons/move.ico b/resources/icons/move.ico new file mode 100644 index 0000000000000000000000000000000000000000..1d2474018e984fc151bb21044c5cba022e77e6f5 GIT binary patch literal 1150 zcmb7Bu}Z{H5S#;hud>zBK7|khwg)Nl1xcq^`3s7I*!d+MXlrjFL9r8$6e1!XqLvoo zb0+updBxV39-HC9;|8RW2-Z7_yc}d+VFVq6XVqQ zfBcWE-O8h*NZjkLj1AcR+q~b$o4k4>)Afn!ktB)B^SpkeK3>ztajbbY|Cyhu)BN(& z^Db|&gE7A!YGSsR`Mt=yfS2#ayaBH{4ukJS{*$)XJc_Ix5O+kw&+jR56l(vsAIre&22gU${lTwN Nxj5CNkyajge*iccQeOZ7 literal 0 HcmV?d00001 diff --git a/resources/images.qrc b/resources/images.qrc index dfca147d..59c14728 100755 --- a/resources/images.qrc +++ b/resources/images.qrc @@ -9,6 +9,7 @@ icons/map.ico icons/cursor.ico icons/fill_color.ico + icons/move.ico icons/pencil.ico icons/pipette.ico images/Entities_16x16.png From 5b96af47db19b878078b001f25514baf430ee264 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Wed, 12 Sep 2018 08:52:24 -0500 Subject: [PATCH 05/16] Add reticule-styled cursors --- mainwindow.cpp | 6 +++--- resources/icons/fill_color_cursor.ico | Bin 0 -> 4286 bytes resources/icons/pencil_cursor.ico | Bin 0 -> 4286 bytes resources/icons/pipette_cursor.ico | Bin 0 -> 4286 bytes resources/images.qrc | 3 +++ 5 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 resources/icons/fill_color_cursor.ico create mode 100644 resources/icons/pencil_cursor.ico create mode 100644 resources/icons/pipette_cursor.ico diff --git a/mainwindow.cpp b/mainwindow.cpp index e47eb792..65c36747 100755 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -904,7 +904,7 @@ void MainWindow::on_toolButton_deleteObject_clicked() void MainWindow::on_toolButton_Paint_clicked() { editor->map_edit_mode = "paint"; - editor->cursor = QCursor(QPixmap(":/icons/pencil.ico"), 0, 14); + editor->cursor = QCursor(QPixmap(":/icons/pencil_cursor.ico"), 10, 10); ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); @@ -928,7 +928,7 @@ void MainWindow::on_toolButton_Select_clicked() void MainWindow::on_toolButton_Fill_clicked() { editor->map_edit_mode = "fill"; - editor->cursor = QCursor(QPixmap(":/icons/fill_color.ico"), 12, 10); + editor->cursor = QCursor(QPixmap(":/icons/fill_color_cursor.ico"), 10, 10); ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); @@ -940,7 +940,7 @@ void MainWindow::on_toolButton_Fill_clicked() void MainWindow::on_toolButton_Dropper_clicked() { editor->map_edit_mode = "pick"; - editor->cursor = QCursor(QPixmap(":/icons/pipette.ico"), 1, 14); + editor->cursor = QCursor(QPixmap(":/icons/pipette_cursor.ico"), 10, 10); ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); diff --git a/resources/icons/fill_color_cursor.ico b/resources/icons/fill_color_cursor.ico new file mode 100644 index 0000000000000000000000000000000000000000..712ab9926f9b13715c1d8077e84cca091fc24466 GIT binary patch literal 4286 zcmchZTTEMZ9LK*t`Cwv9OqOMv+F4+Tn@W}$qegxA$z&SCpg>Pst{Ve}6qwvB!pcRK zMU9E`!MJ4cvW#RiX2~|mM1j(B6C2kMnA3TU+1`90`TG4IEVL?%aHyyG^_>1r&-wiR zxAQr`9s0OjFyAy02TYcZ1<}!Zz3L-*$f3bN^Q?agEXY zV1&NxC8bCAobuPYJ~-jglcGIXMKR-W}jVyFK^^GtN_p+;2~J!(&x>bHvExt)&wg-HHTc=r zR;2ZKbShTo-j#)d!R!c2toQ=@DSyv&*LD?I(qAm8d~VW_E)NA@i;ll=JPI3sF% z(Ek#Dzj2+T7lwG@!}m27$9e9P6RdmemyGevob0Oev;AN(VurB{s`m?9b-fsRnJr}C=F%h5P7oUF2tI-kO`uPUUoOF8M^;~b}-A~^y8YbJS zJ?w4>m_tXNTkrLuT8pn8wruXPV8#E=Ppvl`tXh+=b^D(-`v(8=&s5Gvj^%I2Uy#2c ze?$I;{0;dV@;BsfGj8VjWp-u{`5W>#`wKHxrO@EuMdUqmOLt0+%502QnH4bbaLD7yecT02cr49eeW`J>PL;D~MN ze(~;E40aWvzs+m2^{j;a4fz}LH{@@d`Bw>)zv0h`+3Up0nsCe?X!D`3rOal_-;lo{ ze?$I;o}-Yz)A{aYzNx{4lfF0ChMOu84pu_`hWrir8}c{gZ^++}zcb4ZR^eFVGGG3N z{0;dV@;Bsf$ln@^<8}@5H}w9XzF+MF$L$wi&u8?!QepfJ`5W>#+}B3p(r4S?yEv_WzXn`}QYTii|)2 literal 0 HcmV?d00001 diff --git a/resources/icons/pencil_cursor.ico b/resources/icons/pencil_cursor.ico new file mode 100644 index 0000000000000000000000000000000000000000..1ff8d8fb6dd8f748d5d6e752f755d46d1ca38b11 GIT binary patch literal 4286 zcmd6pPe@cz6vjVk(Xwb^&_dk=xoBf;46LACgd(k4xs4JRu0$GU3{$fxp^VBzh!80# z3Ni-!2Sb5HmWc}qDhf(+BhjM3`ufhBcdu_oH#7QPJvr~(ci(yU`_7#=^Ao7hUri0{ zjIqr?C4e0YO<}*n=3_i|Y3*plD7A9wBdsTR@Mt%iF3$1r*=dGeRu;xI({gf{nH%>x zF#DS=6Xc%bR}=Mc=;k+$d?ByA`^D`e4JYei zcSnwmugHchxpR!H)*dA7p+5DD&9Bw>KlSkZzxB}2Hk8=+qCQo)4^?^}Diw9D*Aw?( z?_{ms$u0U`q;E|#)7hS=hsG)OEf1HTyyswl7qjDc*pX^W%tKvjlG)EcIB+V(nKv)l zf3BP3?e}>3*bDQJ$Z?^kliwE?*mF9=$$?2uq#y8hYN{-KvaH9@+neTmcAm4NZ~6Gl zOj(OKZI?^kyj=erAN7^3E!n*7;#{haXubFi@f+ed#P8@WKMsX01qQ+dmwjOw1MwT; zH^gs<-w?kGRxu5Q=~}WQxNq4-!2=~;h~E&uA$~*rhWHKf+iTb$6tz^)zmp25-DOEx z{D$}q@f+ed#BYe5zS%%D->cIOr-BshK}mwE6pP;wzoFksh~K_nmHK_R$4t@9g_nUR zySLUu{D$}q@!NZFjoRAb*yZT0wMzTv#jOGl`ai~h7S4hd=eJ=w`vulvu$l*JHZL2r z?Nyu)Ke0}OVh>UMs6<@)rr|u;J1Kq#pS$=C@!MO7Q{QiMeQQnphWHKf8{&7+Z4&z* z-B$4%;Mcbs2skwmS9K%z*nHu;y- zLQTsSO;9r`PLlKk(cdzn!bFxcFckGVnAk4kDGkkOJJ?ESAzTY{A`;15hKb4iD z-_o~PWQ&OGV6aQ}Ftp#}7V>!hQqzZ0sT7#-Up%Px&mZ%M$KwSL>LXCfu-jv*ozG7p z8jT_ri)noFdp#`6!t9sNn3;Zp$?=@=;im_!eSU5ZBX@22o@H8e+-`LK;7Bf z*neRN;fA7j#73`;Y(HS3W9%(1-FuC?eS_Z2GX##e z-3T|Oebo;)wbWEMB)A_5sP@idt?7cd^<4G6vNCU#u9Ye4dL~0l=GoeMDe|!5vE&?U z4XQTzEoA6gDPrsD#dUoZRc-QH$S@&COgPP~rSHrs_n!O~@>|GnA-_${reM2f+e1;m zJyfo=`MuUoehc}%yxttp^)@y%$@XCSoc%ghZqs$wddP1fzn4Uf^3tB$+C}}E?`9*n zj0f_Y9)^YgA-ErTqe&g(#;NDFzRs;4$Zt^(-Tkl()Rs|WI1$ZsLP zh5R-i$Zs85ZeFba^5ncBzlHo3@>|GnA-{$E7V=xjZ}sF%cm1CH7V=xjZy~>h{1)@M1BkTE#$Y5-_%d~s!x6k`7PwPkl#Xv`l?TUb1xDmRGa*EMIU&;W3-L2 wfpMOZ(KyH04ZPn3%rbs47At^1cHkkCmf{`nF8+(fdS+KLn^$K)G;fvm7x-#{I{*Lx literal 0 HcmV?d00001 diff --git a/resources/images.qrc b/resources/images.qrc index 59c14728..fcee557f 100755 --- a/resources/images.qrc +++ b/resources/images.qrc @@ -17,5 +17,8 @@ icons/delete.ico icons/viewsprites.ico images/collisions.png + icons/fill_color_cursor.ico + icons/pencil_cursor.ico + icons/pipette_cursor.ico From 65adc2bdd0e375e29ae3550aa3f9001ef4e2d050 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Wed, 12 Sep 2018 09:17:50 -0500 Subject: [PATCH 06/16] Use Qt built-in functionality for opening scripts with default editor --- mainwindow.cpp | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/mainwindow.cpp b/mainwindow.cpp index 7b09396c..a596f0b3 100755 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -20,6 +20,7 @@ #include #include #include +#include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), @@ -554,28 +555,8 @@ void MainWindow::redo() { // Open current map scripts in system default editor for .inc files void MainWindow::openInTextEditor() { - QProcess *process = new QProcess(this); - QSysInfo sysInfo; - process->setWorkingDirectory(editor->project->root); - - #ifdef Q_OS_DARWIN - QString cmd = "open "; - #elif defined Q_OS_LINUX - QString cmd = "xdg-open "; - #elif defined Q_OS_WIN - QString cmd = "cmd /c start \""; - #else - qDebug() << "Functionality is not available with this OS (" - << sysInfo.productType() << ")"; - #endif - - cmd += "data/maps/" + editor->map->name + "/scripts.inc"; - - #ifdef Q_OS_WIN - cmd += "\""; - #endif - - process->start(cmd); + QString path = QDir::cleanPath(editor->project->root + QDir::separator() + "data/maps/" + editor->map->name + "/scripts.inc"); + QDesktopServices::openUrl(QUrl(path)); } void MainWindow::on_action_Save_triggered() { From 23efdc2bea60bbcc2b2379a2899365f409a182e0 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Wed, 12 Sep 2018 17:44:30 -0500 Subject: [PATCH 07/16] Support spritesheets instead of individual frames for event object pics --- editor.cpp | 1 + editor.h | 7 +++---- event.cpp | 22 ++++++++++++++++++++++ event.h | 5 +++++ project.cpp | 26 ++++++++++++++++++++++---- 5 files changed, 53 insertions(+), 8 deletions(-) diff --git a/editor.cpp b/editor.cpp index 962907d9..13790463 100755 --- a/editor.cpp +++ b/editor.cpp @@ -1653,6 +1653,7 @@ QList *Editor::getObjects() { void Editor::redrawObject(DraggablePixmapItem *item) { if (item) { item->setPixmap(item->event->pixmap); + item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape); if (selected_events && selected_events->contains(item)) { QImage image = item->pixmap().toImage(); QPainter painter(&image); diff --git a/editor.h b/editor.h index 29b832dc..1beadf75 100755 --- a/editor.h +++ b/editor.h @@ -174,10 +174,8 @@ public: int last_x; int last_y; void updatePosition() { - int x = event->x() * 16; - int y = event->y() * 16; - x -= pixmap().width() / 32 * 16; - y -= pixmap().height() - 16; + int x = event->getPixelX(); + int y = event->getPixelY(); setX(x); setY(y); setZValue(event->y()); @@ -193,6 +191,7 @@ public: objects.append(event); event->pixmap = QPixmap(); editor->project->loadEventPixmaps(objects); + this->updatePosition(); editor->redrawObject(this); emit spriteChanged(event->pixmap); } diff --git a/event.cpp b/event.cpp index c92b9a26..a1c6f5e4 100755 --- a/event.cpp +++ b/event.cpp @@ -12,6 +12,8 @@ QString EventType::HealLocation = "event_heal_location"; Event::Event() { + this->spriteWidth = 16; + this->spriteHeight = 16; } Event* Event::createNewEvent(QString event_type, QString map_name) @@ -126,6 +128,16 @@ Event* Event::createNewSecretBaseEvent() return event; } +int Event::getPixelX() +{ + return (this->x() * 16) - qMax(0, (this->spriteWidth - 16) / 2); +} + +int Event::getPixelY() +{ + return (this->y() * 16) - qMax(0, this->spriteHeight - 16); +} + QString Event::buildObjectEventMacro(int item_index) { int radius_x = this->getInt("radius_x"); @@ -236,3 +248,13 @@ QString Event::buildSecretBaseEventMacro() text += "\n"; return text; } + +void Event::setPixmapFromSpritesheet(QImage spritesheet, int spriteWidth, int spriteHeight) +{ + // Set first palette color fully transparent. + QImage img = spritesheet.copy(0, 0, spriteWidth, spriteHeight); + img.setColor(0, qRgba(0, 0, 0, 0)); + pixmap = QPixmap::fromImage(img); + this->spriteWidth = spriteWidth; + this->spriteHeight = spriteHeight; +} diff --git a/event.h b/event.h index 13aa114a..fc71e8a7 100755 --- a/event.h +++ b/event.h @@ -71,9 +71,14 @@ public: QString buildSignEventMacro(); QString buildHiddenItemEventMacro(); QString buildSecretBaseEventMacro(); + void setPixmapFromSpritesheet(QImage, int, int); + int getPixelX(); + int getPixelY(); QMap values; QPixmap pixmap; + int spriteWidth; + int spriteHeight; }; #endif // EVENT_H diff --git a/project.cpp b/project.cpp index bdd4c8ec..61baae72 100755 --- a/project.cpp +++ b/project.cpp @@ -1292,6 +1292,9 @@ void Project::loadEventPixmaps(QList objects) { if (!object->pixmap.isNull()) { continue; } + + object->spriteWidth = 16; + object->spriteHeight = 16; QString event_type = object->get("event_type"); if (event_type == EventType::Object) { object->pixmap = QPixmap(":/images/Entities_16x16.png").copy(0, 0, 16, 16); @@ -1309,16 +1312,31 @@ void Project::loadEventPixmaps(QList objects) { int sprite_id = constants.value(object->get("sprite")); QString info_label = pointers.value(sprite_id).replace("&", ""); - QString pic_label = readCArray(info_text, info_label).value(14); + QStringList gfx_info = readCArray(info_text, info_label); + QString pic_label = gfx_info.value(14); + QString dimensions_label = gfx_info.value(11); + QString subsprites_label = gfx_info.value(12); QString gfx_label = readCArray(pic_text, pic_label).value(0); gfx_label = gfx_label.section(QRegExp("[\\(\\)]"), 1, 1); QString path = readCIncbin(assets_text, gfx_label); if (!path.isNull()) { path = fixGraphicPath(path); - QPixmap pixmap(root + "/" + path); - if (!pixmap.isNull()) { - object->pixmap = pixmap; + QImage spritesheet(root + "/" + path); + if (!spritesheet.isNull()) { + // Infer the sprite dimensions from the OAM labels. + int spriteWidth = spritesheet.width(); + int spriteHeight = spritesheet.height(); + QRegularExpression re("\\S+_(\\d+)x(\\d+)"); + QRegularExpressionMatch dimensionMatch = re.match(dimensions_label); + if (dimensionMatch.hasMatch()) { + QRegularExpressionMatch oamTablesMatch = re.match(subsprites_label); + if (oamTablesMatch.hasMatch()) { + spriteWidth = dimensionMatch.captured(1).toInt(); + spriteHeight = dimensionMatch.captured(2).toInt(); + } + } + object->setPixmapFromSpritesheet(spritesheet, spriteWidth, spriteHeight); } } } From 2a00e8aee95989caa69fcc40137d2bf1637e0a2b Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Wed, 12 Sep 2018 17:44:37 -0500 Subject: [PATCH 08/16] Fix bug when saving heal locations for maps with multiple heal locations --- project.cpp | 26 ++++++++------------------ project.h | 2 +- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/project.cpp b/project.cpp index 61baae72..5bd0d2bb 100755 --- a/project.cpp +++ b/project.cpp @@ -514,36 +514,27 @@ void Project::saveHealLocationStruct(Map *map) { QMap flyableMapsDupes; QSet flyableMapsUnique; - // erase old location from flyableMaps list // set flyableMapsDupes and flyableMapsUnique - for (auto it = flyableMaps->begin(); it != flyableMaps->end(); it++) { + for (auto it = flyableMaps.begin(); it != flyableMaps.end(); it++) { HealLocation loc = *it; QString xname = loc.name; if (flyableMapsUnique.contains(xname)) { flyableMapsDupes[xname] = 1; } - if (xname == QString(mapNamesToMapConstants->value(map->name)).remove(0,4)) { - it = flyableMaps->erase(it) - 1; - } - else { - flyableMapsUnique.insert(xname); - } + flyableMapsUnique.insert(xname); } // set new location in flyableMapsList if (map->events["heal_event_group"].length() > 0) { - QList* flymaps = flyableMaps; - for (Event *heal : map->events["heal_event_group"]) { HealLocation hl = heal->buildHealLocation(); - flymaps->insert(hl.index - 1, hl); + flyableMaps[hl.index - 1] = hl; } - flyableMaps = flymaps; } int i = 1; - for (auto map_in : *flyableMaps) { + for (auto map_in : flyableMaps) { data_text += QString(" {MAP_GROUP(%1), MAP_NUM(%1), %2, %3},\n") .arg(map_in.name) .arg(map_in.x) @@ -1026,7 +1017,8 @@ void Project::readMapGroups() { QString hltext = readTextFile(root + QString("/src/data/heal_locations.h")); QList* hl = parser->parseHealLocs(hltext); - flyableMaps = hl; + flyableMaps = *hl; + delete hl; } Map* Project::addNewMapToGroup(QString mapName, int groupNum) { @@ -1412,12 +1404,10 @@ void Project::saveMapEvents(Map *map) { // save heal event changes if (map->events["heal_event_group"].length() > 0) { - QList* flymaps = flyableMaps; for (Event *heal : map->events["heal_event_group"]) { HealLocation hl = heal->buildHealLocation(); - flymaps->append(hl); + flyableMaps[hl.index - 1] = hl; } - flyableMaps = flymaps; } saveHealLocationStruct(map); } @@ -1492,7 +1482,7 @@ void Project::readMapEvents(Map *map) { map->events["heal_event_group"].clear(); - for (auto it = flyableMaps->begin(); it != flyableMaps->end(); it++) { + for (auto it = flyableMaps.begin(); it != flyableMaps.end(); it++) { HealLocation loc = *it; diff --git a/project.h b/project.h index d965e4c6..49e348b2 100755 --- a/project.h +++ b/project.h @@ -18,7 +18,7 @@ public: QMap *map_groups; QList groupedMapNames; QStringList *mapNames = NULL; - QList *flyableMaps = NULL; // can't be a QMap because duplicates + QList flyableMaps; QMap* mapConstantsToMapNames; QMap* mapNamesToMapConstants; QList mapLayoutsTable; From 62b9d97a313a259ada1e97bfc0512dbc05d339aa Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Wed, 12 Sep 2018 17:44:40 -0500 Subject: [PATCH 09/16] Smart path now draws a 2x2 region, instead of 3x3 region --- editor.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/editor.cpp b/editor.cpp index 13790463..9a07e9b7 100755 --- a/editor.cpp +++ b/editor.cpp @@ -1145,8 +1145,8 @@ void MapPixmapItem::paintSmartPath(int x, int y) { int openTile = map->selected_metatiles->at(4); // Fill the region with the open tile. - for (int i = -1; i <= 1; i++) - for (int j = -1; j <= 1; j++) { + for (int i = 0; i <= 1; i++) + for (int j = 0; j <= 1; j++) { // Check if in map bounds. if (!(i + x < map->getWidth() && i + x >= 0 && j + y < map->getHeight() && j + y >= 0)) continue; @@ -1160,14 +1160,14 @@ void MapPixmapItem::paintSmartPath(int x, int y) { } // Go back and resolve the edge tiles - for (int i = -2; i <= 2; i++) - for (int j = -2; j <= 2; j++) { + for (int i = -1; i <= 2; i++) + for (int j = -1; j <= 2; j++) { // Check if in map bounds. if (!(i + x < map->getWidth() && i + x >= 0 && j + y < map->getHeight() && j + y >= 0)) continue; // Ignore the corners, which can't possible be affected by the smart path. - if ((i == -2 && j == -2) || (i == 2 && j == -2) || - (i == -2 && j == 2) || (i == 2 && j == 2)) + if ((i == -1 && j == -1) || (i == 2 && j == -1) || + (i == -1 && j == 2) || (i == 2 && j == 2)) continue; // Ignore tiles that aren't part of the smart path set. From ece612a86550123419669e80a8ffd151caad850e Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 12 Sep 2018 20:43:04 -0400 Subject: [PATCH 10/16] using different cursors is checkable and added to settings --- editor.cpp | 8 ++++++-- mainwindow.cpp | 9 +++++++++ mainwindow.h | 1 + mainwindow.ui | 15 +++++++++++++++ 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/editor.cpp b/editor.cpp index a3652d10..1afbf783 100755 --- a/editor.cpp +++ b/editor.cpp @@ -1484,11 +1484,15 @@ void MapPixmapItem::updateCurHoveredTile(QPointF pos) { void MapPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { updateCurHoveredTile(event->pos()); - setCursor(editor->cursor); + if (editor->ui->actionBetter_Cursors->isChecked()){ + setCursor(editor->cursor); + } } void MapPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { map->clearHoveredTile(); - unsetCursor(); + if (editor->ui->actionBetter_Cursors->isChecked()){ + unsetCursor(); + } } void MapPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { QPointF pos = event->pos(); diff --git a/mainwindow.cpp b/mainwindow.cpp index 65c36747..85dd6403 100755 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -54,6 +54,10 @@ MainWindow::MainWindow(QWidget *parent) : openProject(default_dir); } } + + if (settings.contains("cursor_mode") && settings.value("cursor_mode") == "0") { + ui->actionBetter_Cursors->setChecked(false); + } } MainWindow::~MainWindow() @@ -600,6 +604,11 @@ void MainWindow::on_actionZoom_Out_triggered() { scaleMapView(-1); } +void MainWindow::on_actionBetter_Cursors_triggered() { + QSettings settings; + settings.setValue("cursor_mode", QString::number(ui->actionBetter_Cursors->isChecked())); +} + void MainWindow::scaleMapView(int s) { editor->map->scale_exp += s; diff --git a/mainwindow.h b/mainwindow.h index d6509a50..b8f9169d 100755 --- a/mainwindow.h +++ b/mainwindow.h @@ -62,6 +62,7 @@ private slots: void on_actionZoom_In_triggered(); void on_actionZoom_Out_triggered(); + void on_actionBetter_Cursors_triggered(); void on_toolButton_deleteObject_clicked(); diff --git a/mainwindow.ui b/mainwindow.ui index ad6b7925..160b223c 100755 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -2076,6 +2076,7 @@ + @@ -2154,6 +2155,20 @@ - + + + true + + + true + + + Better Cursors + + + <html><head/><body><p>Use reticule-styled cursors with icon showing currently selected tool.</p></body></html> + + From 475f63d0f279a8c2953354ddf87517fed8ea0d4a Mon Sep 17 00:00:00 2001 From: garak Date: Wed, 12 Sep 2018 21:10:11 -0400 Subject: [PATCH 11/16] small fix --- mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mainwindow.cpp b/mainwindow.cpp index a596f0b3..a6484c80 100755 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -555,7 +555,7 @@ void MainWindow::redo() { // Open current map scripts in system default editor for .inc files void MainWindow::openInTextEditor() { - QString path = QDir::cleanPath(editor->project->root + QDir::separator() + "data/maps/" + editor->map->name + "/scripts.inc"); + QString path = QDir::cleanPath("file://" + editor->project->root + QDir::separator() + "data/maps/" + editor->map->name + "/scripts.inc"); QDesktopServices::openUrl(QUrl(path)); } From 0932ce671186a8b79a2ec45f19dc4d67e0960dcc Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Thu, 13 Sep 2018 17:01:49 -0500 Subject: [PATCH 12/16] Change text to 'Cursor Icons' --- mainwindow.ui | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/mainwindow.ui b/mainwindow.ui index 65b1adfd..09e9f9d1 100755 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -351,8 +351,8 @@ 0 0 - 462 - 599 + 429 + 620 @@ -734,7 +734,7 @@ 0 0 - 222 + 315 86 @@ -838,10 +838,10 @@ - 8 + 0 0 - 323 - 368 + 365 + 405 @@ -1076,8 +1076,8 @@ 0 0 - 371 - 643 + 381 + 657 @@ -1242,8 +1242,8 @@ 0 0 - 410 - 560 + 420 + 584 @@ -1898,8 +1898,8 @@ 0 0 - 818 - 539 + 826 + 557 @@ -2071,7 +2071,7 @@ 0 0 1117 - 22 + 21 @@ -2186,7 +2186,7 @@ true - Better Cursors + Cursor Icons <html><head/><body><p>Use reticule-styled cursors with icon showing currently selected tool.</p></body></html> From ab0eff8c20a56dcbe3a6a70fb291f8b41258fa36 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Thu, 13 Sep 2018 17:48:32 -0500 Subject: [PATCH 13/16] Shift tool, shift+click for smart paths, middle button click for fill, and toggle border/connections visibility --- editor.cpp | 130 ++++++++++++++++++++++++++++++-------- editor.h | 2 + mainwindow.cpp | 15 +++++ mainwindow.h | 4 ++ mainwindow.ui | 39 ++++++++++-- resources/icons/shift.ico | Bin 0 -> 10462 bytes resources/images.qrc | 1 + 7 files changed, 157 insertions(+), 34 deletions(-) create mode 100644 resources/icons/shift.ico diff --git a/editor.cpp b/editor.cpp index 8bafbb4d..17909121 100755 --- a/editor.cpp +++ b/editor.cpp @@ -50,7 +50,7 @@ void Editor::setEditingMap() { map_item->draw(); map_item->setVisible(true); map_item->setEnabled(true); - setConnectionsVisibility(true); + setConnectionsVisibility(ui->checkBox_ToggleBorder->isChecked()); } if (collision_item) { collision_item->setVisible(false); @@ -58,7 +58,7 @@ void Editor::setEditingMap() { if (events_group) { events_group->setVisible(false); } - setBorderItemsVisible(true); + setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked()); setConnectionItemsVisible(false); } @@ -68,7 +68,7 @@ void Editor::setEditingCollision() { displayMapConnections(); collision_item->draw(); collision_item->setVisible(true); - setConnectionsVisibility(true); + setConnectionsVisibility(ui->checkBox_ToggleBorder->isChecked()); } if (map_item) { map_item->setVisible(false); @@ -76,7 +76,7 @@ void Editor::setEditingCollision() { if (events_group) { events_group->setVisible(false); } - setBorderItemsVisible(true); + setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked()); setConnectionItemsVisible(false); } @@ -88,12 +88,12 @@ void Editor::setEditingObjects() { if (map_item) { map_item->setVisible(true); map_item->setEnabled(false); - setConnectionsVisibility(true); + setConnectionsVisibility(ui->checkBox_ToggleBorder->isChecked()); } if (collision_item) { collision_item->setVisible(false); } - setBorderItemsVisible(true); + setBorderItemsVisible(ui->checkBox_ToggleBorder->isChecked()); setConnectionItemsVisible(false); } @@ -338,33 +338,54 @@ void Editor::setMap(QString map_name) { } void Editor::mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item) { - if (event->buttons() & Qt::RightButton) { - item->updateMetatileSelection(event); - } else { - if (map_edit_mode == "paint") { - item->paint(event); - } else if (map_edit_mode == "fill") { + if (map_edit_mode == "paint") { + if (event->buttons() & Qt::RightButton) { + item->updateMetatileSelection(event); + } else if (event->buttons() & Qt::MiddleButton) { item->floodFill(event); - } else if (map_edit_mode == "pick") { - item->pick(event); - } else if (map_edit_mode == "select") { - item->select(event); + } else { + item->paint(event); } + } else if (map_edit_mode == "select") { + item->select(event); + } else if (map_edit_mode == "fill") { + if (event->buttons() & Qt::RightButton) { + item->updateMetatileSelection(event); + } else { + item->floodFill(event); + } + } else if (map_edit_mode == "pick") { + + if (event->buttons() & Qt::RightButton) { + item->updateMetatileSelection(event); + } else { + item->pick(event); + } + } else if (map_edit_mode == "shift") { + item->shift(event); } } void Editor::mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item) { - if (event->buttons() & Qt::RightButton) { - item->updateMovementPermissionSelection(event); - } else { - if (map_edit_mode == "paint") { - item->paint(event); - } else if (map_edit_mode == "fill") { + if (map_edit_mode == "paint") { + if (event->buttons() & Qt::RightButton) { + item->updateMovementPermissionSelection(event); + } else if (event->buttons() & Qt::MiddleButton) { item->floodFill(event); - } else if (map_edit_mode == "pick") { - item->pick(event); - } else if (map_edit_mode == "select") { - item->select(event); + } else { + item->paint(event); } + } else if (map_edit_mode == "select") { + item->select(event); + } else if (map_edit_mode == "fill") { + if (event->buttons() & Qt::RightButton) { + item->pick(event); + } else { + item->floodFill(event); + } + } else if (map_edit_mode == "pick") { + item->pick(event); + } else if (map_edit_mode == "shift") { + item->shift(event); } } @@ -861,6 +882,12 @@ void Editor::updateSecondaryTileset(QString tilesetLabel) } } +void Editor::toggleBorderVisibility(bool visible) +{ + this->setBorderItemsVisible(visible); + this->setConnectionsVisibility(visible); +} + void MetatilesPixmapItem::paintTileChanged(Map *map) { draw(); } @@ -1080,7 +1107,8 @@ void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) { int y = (int)(pos.y()) / 16; // Paint onto the map. - if (map->smart_paths_enabled && map->selected_metatiles_width == 3 && map->selected_metatiles_height == 3) { + bool smartPathsEnabled = event->modifiers() & Qt::ShiftModifier; + if ((map->smart_paths_enabled || smartPathsEnabled) && map->selected_metatiles_width == 3 && map->selected_metatiles_height == 3) { paintSmartPath(x, y); } else { paintNormal(x, y); @@ -1091,6 +1119,51 @@ void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) { } } +void MapPixmapItem::shift(QGraphicsSceneMouseEvent *event) { + if (map) { + if (event->type() == QEvent::GraphicsSceneMouseRelease) { + map->commit(); + } else { + QPointF pos = event->pos(); + int x = (int)(pos.x()) / 16; + int y = (int)(pos.y()) / 16; + + if (event->type() == QEvent::GraphicsSceneMousePress) { + selection_origin = QPoint(x, y); + selection.clear(); + } else if (event->type() == QEvent::GraphicsSceneMouseMove) { + if (x != selection_origin.x() || y != selection_origin.y()) { + int xDelta = x - selection_origin.x(); + int yDelta = y - selection_origin.y(); + Blockdata *backupBlockdata = map->layout->blockdata->copy(); + for (int i = 0; i < map->getWidth(); i++) + for (int j = 0; j < map->getHeight(); j++) { + int srcX = i; + int srcY = j; + int destX = i + xDelta; + int destY = j + yDelta; + if (destX < 0) + do { destX += map->getWidth(); } while (destX < 0); + if (destY < 0) + do { destY += map->getHeight(); } while (destY < 0); + destX %= map->getWidth(); + destY %= map->getHeight(); + + int blockIndex = j * map->getWidth() + i; + Block srcBlock = backupBlockdata->blocks->at(blockIndex); + map->_setBlock(destX, destY, srcBlock); + } + + delete backupBlockdata; + selection_origin = QPoint(x, y); + selection.clear(); + draw(); + } + } + } + } +} + void MapPixmapItem::paintNormal(int x, int y) { // Snap the selected position to the top-left of the block boundary. // This allows painting via dragging the mouse to tile the painted region. @@ -1260,7 +1333,8 @@ void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) { Block *block = map->getBlock(x, y); int tile = map->selected_metatiles->first(); if (block && block->tile != tile) { - if (map->smart_paths_enabled && map->selected_metatiles_width == 3 && map->selected_metatiles_height == 3) + bool smartPathsEnabled = event->modifiers() & Qt::ShiftModifier; + if ((map->smart_paths_enabled || smartPathsEnabled) && map->selected_metatiles_width == 3 && map->selected_metatiles_height == 3) this->_floodFillSmartPath(x, y); else this->_floodFill(x, y); diff --git a/editor.h b/editor.h index 4bfbfb23..ab09c365 100755 --- a/editor.h +++ b/editor.h @@ -67,6 +67,7 @@ public: void setSelectedConnectionFromMap(QString mapName); void updatePrimaryTileset(QString tilesetLabel); void updateSecondaryTileset(QString tilesetLabel); + void toggleBorderVisibility(bool visible); DraggablePixmapItem *addMapEvent(Event *event); void selectMapEvent(DraggablePixmapItem *object); @@ -273,6 +274,7 @@ public: void _floodFillSmartPath(int initialX, int initialY); virtual void pick(QGraphicsSceneMouseEvent*); virtual void select(QGraphicsSceneMouseEvent*); + virtual void shift(QGraphicsSceneMouseEvent*); virtual void draw(bool ignoreCache = false); void updateMetatileSelection(QGraphicsSceneMouseEvent *event); diff --git a/mainwindow.cpp b/mainwindow.cpp index daf19ceb..7ffac85c 100755 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -993,12 +993,19 @@ void MainWindow::on_toolButton_Move_clicked() checkToolButtons(); } +void MainWindow::on_toolButton_Shift_clicked() +{ + editor->map_edit_mode = "shift"; + checkToolButtons(); +} + void MainWindow::checkToolButtons() { ui->toolButton_Paint->setChecked(editor->map_edit_mode == "paint"); ui->toolButton_Select->setChecked(editor->map_edit_mode == "select"); ui->toolButton_Fill->setChecked(editor->map_edit_mode == "fill"); ui->toolButton_Dropper->setChecked(editor->map_edit_mode == "pick"); ui->toolButton_Move->setChecked(editor->map_edit_mode == "move"); + ui->toolButton_Shift->setChecked(editor->map_edit_mode == "shift"); } void MainWindow::toggleEditModeMove() { @@ -1011,6 +1018,8 @@ void MainWindow::toggleEditModeMove() { on_toolButton_Dropper_clicked(); } else if (editor->prev_edit_mode == "select") { on_toolButton_Select_clicked(); + } else if (editor->prev_edit_mode == "shift") { + on_toolButton_Shift_clicked(); } } else { @@ -1151,3 +1160,9 @@ void MainWindow::on_checkBox_smartPaths_stateChanged(int selected) { editor->map->smart_paths_enabled = selected == Qt::Checked; } + +void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected) +{ + bool visible = selected != 0; + editor->toggleBorderVisibility(visible); +} diff --git a/mainwindow.h b/mainwindow.h index b2c74610..a9f9bf99 100755 --- a/mainwindow.h +++ b/mainwindow.h @@ -81,6 +81,8 @@ private slots: void on_toolButton_Move_clicked(); + void on_toolButton_Shift_clicked(); + void onOpenMapListContextMenu(const QPoint &point); void onAddNewMapToGroupClick(QAction* triggeredAction); void onTilesetChanged(QString); @@ -112,6 +114,8 @@ private slots: void on_checkBox_Visibility_clicked(bool checked); + void on_checkBox_ToggleBorder_stateChanged(int arg1); + private: Ui::MainWindow *ui; QStandardItemModel *mapListModel; diff --git a/mainwindow.ui b/mainwindow.ui index 09e9f9d1..6b4ce23d 100755 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -231,7 +231,7 @@ - <html><head/><body><p>Eye Dropper</p><p>Click to select a metatile or collision attribute.</p></body></html> + <html><head/><body><p>Eye Dropper</p><p><span style=" font-weight:600;">Click</span> to select a metatile or collision attribute.</p></body></html> Dropper @@ -256,6 +256,23 @@ :/icons/move.ico:/icons/move.ico + + + true + + + + + + + <html><head/><body><p>Map Shift</p><p><span style=" font-weight:600;">Click and drag</span> on the map to shift the positions all metatiles at once. This is useful after resizing a map.</p></body></html> + + + Shift + + + + :/icons/shift.ico:/icons/shift.ico true @@ -265,7 +282,7 @@ - <html><head/><body><p>Smart-path mode allows easier drawing of paths. If a 3x3 metatile block is selcted in the right panel, then smart path mode will automatically form a pathway using those selected blocks.</p><p>When smart-path mode is <span style=" font-weight:600;">not</span> enabled, clicking and dragging a selection will tile it in a grid.</p></body></html> + <html><head/><body><p>Smart-path mode allows easier drawing of paths. If a 3x3 metatile block is selcted in the right panel, then smart path mode will automatically form a pathway using those selected blocks.</p><p>When smart-path mode is <span style=" font-weight:600;">not</span> enabled, clicking and dragging a selection will tile it in a grid.</p><p>Hold down the <span style=" font-weight:600;">shift</span> key while editing to quickly enable smart-path mode.</p></body></html> margin-left: 10px @@ -284,7 +301,17 @@ - Show Grid + Grid + + + + + + + Border + + + true @@ -351,7 +378,7 @@ 0 0 - 429 + 442 620 @@ -734,7 +761,7 @@ 0 0 - 315 + 302 86 @@ -840,7 +867,7 @@ 0 0 - 365 + 352 405 diff --git a/resources/icons/shift.ico b/resources/icons/shift.ico new file mode 100644 index 0000000000000000000000000000000000000000..dab33a4e5cd297fad52ddc5e638965fcc56e6272 GIT binary patch literal 10462 zcmeI2%THZJ9LJ}r)%$)hn{eI@0Gc&*y z;uL-^UKBXKFTx)P@s0x8l^)l*v-*7|To0^N<{! zot>8UV8!(Gw8>KK7|WN?6DP~~_;^sdRi2rd(Q_E*u^Pu%zR)aVV`G-~V8!h0tX^9f z>l|ab0zHr6a&&YwDBUV67VkbH=WEAUESXeMwzHyA@Q_V6kFc6e(l@}KmO_mnN zSn@PWe}BKFJy@}{v}Ceeb&Mrfv-I`#1*Kc%<>h6WnVG5Imv+Zka-b&$m%Y8cmiA!9 z%E}5kym=4tTewU13B>#jmpwf_LFramv3T#+%*x8r z&)9VbSq`B|c6D_HrCa5-wKbFFd&gKlf}R7i3=R%j+JhDA>+2>}!hlhujZnJ_61qB6~;TG~(&Pu5#Wv&Ny%J-Di6^=K>cPxXyBp^ybV&7&r&B zJ)Cp0D-0oO;@ZV^_&DP_&b5&3;anTJMkd>MAGl|rrau#5;GRUa=N^T76&LJRh@h^& zxTibLxF_V^P_^e?k$Xm0Yz{(XdwaW##bVFIAVYn9y=Gv}8?FE-9q%DNfIpLk3=Itp znqeMo-&DD-g>(p7hg0jMd0)uT*x0BU7IEEG21xVl0*?3LvbD9cj4aet1T@pvbnigGc2Q?UvWt#dk11y;hJFu=WnMHfT8s~&biN6fb;ysPDbE= zGXnmi91?cSKo#nb&iOI^f*)h2{TMyv#|Tr=E+X2z7!n_Hf|JT&# y;mcRdV>)A8>0>&}OlM@eAAP>a6W%t}4wBF=rp70(#_I^_te0v$QS!@A$A19>pa?1e literal 0 HcmV?d00001 diff --git a/resources/images.qrc b/resources/images.qrc index fcee557f..2c0cf39d 100755 --- a/resources/images.qrc +++ b/resources/images.qrc @@ -20,5 +20,6 @@ icons/fill_color_cursor.ico icons/pencil_cursor.ico icons/pipette_cursor.ico + icons/shift.ico From fa2574ad48acd3f0d70d359f02816ee9255a95d9 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Thu, 13 Sep 2018 17:48:40 -0500 Subject: [PATCH 14/16] Add cursor for 'shift' mode --- mainwindow.cpp | 27 ++++++--------------------- mainwindow.h | 1 - resources/icons/shift_cursor.ico | Bin 0 -> 4286 bytes resources/images.qrc | 1 + 4 files changed, 7 insertions(+), 22 deletions(-) create mode 100644 resources/icons/shift_cursor.ico diff --git a/mainwindow.cpp b/mainwindow.cpp index 7ffac85c..985f2831 100755 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -37,7 +37,6 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->newEventToolButton, SIGNAL(newEventAdded(QString)), this, SLOT(addNewEvent(QString))); new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Z), this, SLOT(redo())); - new QShortcut(Qt::Key_M, this, SLOT(toggleEditModeMove())); editor = new Editor(ui); connect(editor, SIGNAL(objectsChanged()), this, SLOT(updateSelectedObjects())); @@ -996,6 +995,12 @@ void MainWindow::on_toolButton_Move_clicked() void MainWindow::on_toolButton_Shift_clicked() { editor->map_edit_mode = "shift"; + editor->cursor = QCursor(QPixmap(":/icons/shift_cursor.ico"), 10, 10); + + ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); + ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); + QScroller::ungrabGesture(ui->scrollArea); + checkToolButtons(); } @@ -1008,26 +1013,6 @@ void MainWindow::checkToolButtons() { ui->toolButton_Shift->setChecked(editor->map_edit_mode == "shift"); } -void MainWindow::toggleEditModeMove() { - if (editor->map_edit_mode == "move") { - if (editor->prev_edit_mode == "paint") { - on_toolButton_Paint_clicked(); - } else if (editor->prev_edit_mode == "fill") { - on_toolButton_Fill_clicked(); - } else if (editor->prev_edit_mode == "pick") { - on_toolButton_Dropper_clicked(); - } else if (editor->prev_edit_mode == "select") { - on_toolButton_Select_clicked(); - } else if (editor->prev_edit_mode == "shift") { - on_toolButton_Shift_clicked(); - } - } - else { - editor->prev_edit_mode = editor->map_edit_mode; - on_toolButton_Move_clicked(); - } -} - void MainWindow::onLoadMapRequested(QString mapName, QString fromMapName) { setMap(mapName); editor->setSelectedConnectionFromMap(fromMapName); diff --git a/mainwindow.h b/mainwindow.h index a9f9bf99..58380406 100755 --- a/mainwindow.h +++ b/mainwindow.h @@ -37,7 +37,6 @@ private slots: void undo(); void redo(); - void toggleEditModeMove(); void openInTextEditor(); void onLoadMapRequested(QString, QString); diff --git a/resources/icons/shift_cursor.ico b/resources/icons/shift_cursor.ico new file mode 100644 index 0000000000000000000000000000000000000000..0c8722c39f0e67ecdce4d49e3321bf0e7a554ef6 GIT binary patch literal 4286 zcmcJSe@t6d6vw}yVgI4Y3|ZFVDqRuhCKMwPHO~L|%f!v$7Pb}WF^(n5YRxlZ8PM!i-tiN>forY565K+7LFU!{128lCiZs&w1rR+rVP_R@44^Z z&pG$Kd(Q!gqCb@i{EG{Z0&xJ6NJxcONLasF5k(Q9$Y$%3{^19Vtqq03=D7#9UxM!O z?~tRq27Q7Jc^W&f{a8juMt?#=!mHGdDou96sQnS;&$>|g+$>H!KZlbq+<-A{JS5+l ze?&R#$0y!agTY{#pPv`Iy1JHBD%ES7@oQeX843RWfq{X0D=RCa+wB&+ySta-;^Ovi zZ-`)`x}kni*1Y%{d6LJ!lYAK>E0?{hbb z_Tf0$;3kgrJhL%h#BjvSD^&1g8oPfj9?xdwcJAJRXt7Y&PGeJHZfcHm}Eg=lCdW z4g8&E2hulMxyEHan<9vT{2roAZTcM=J{WJ5(h>PxesP$>4%nOoxXzskO+(P)g! z&eu#t`upG8+1dFwv$>Gp_ft|*BsSX^X(1mKRaI5?g@pwVvE6BDY0Qp}G}m{1;wg1H zoh>~*y^PuCs*gq7Z(lyQscd03w_Bn*}A0iRIC4S-rijt;LylV!A-9PyGFZ1Qsz*`cE_~tLU zDm&#+lMtS8dN-RloJz@Vmu!QdJ{9xppMmjvYSfAgA9X~QPj}rwH{BJ$KTC`g>5JK8J3`Yq4%^`G1PEwBxZyiTxnAYbmY9V~L6&q*tt)3#axZS}cmug{SrSnm2f4>j-BiQ>O3 zdr5Xs{}K9cVGCvK4~e2kvO;a{v!2KKIi5o~-kd0k@2-n`AC0JJglb>C^c<-I%YR{7 BErS36 literal 0 HcmV?d00001 diff --git a/resources/images.qrc b/resources/images.qrc index 2c0cf39d..2094922f 100755 --- a/resources/images.qrc +++ b/resources/images.qrc @@ -21,5 +21,6 @@ icons/pencil_cursor.ico icons/pipette_cursor.ico icons/shift.ico + icons/shift_cursor.ico From 61311940656e8dfff0e32af0c0659747ac86ce8a Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Thu, 13 Sep 2018 17:48:43 -0500 Subject: [PATCH 15/16] Add keyboard shortcuts for each of the editing tool buttons --- mainwindow.cpp | 30 ++++++++++++++++++++ mainwindow.h | 6 ++++ mainwindow.ui | 74 +++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 103 insertions(+), 7 deletions(-) diff --git a/mainwindow.cpp b/mainwindow.cpp index 985f2831..bc0b41e3 100755 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -618,6 +618,36 @@ void MainWindow::on_actionBetter_Cursors_triggered() { settings.setValue("cursor_mode", QString::number(ui->actionBetter_Cursors->isChecked())); } +void MainWindow::on_actionPencil_triggered() +{ + on_toolButton_Paint_clicked(); +} + +void MainWindow::on_actionPointer_triggered() +{ + on_toolButton_Select_clicked(); +} + +void MainWindow::on_actionFlood_Fill_triggered() +{ + on_toolButton_Fill_clicked(); +} + +void MainWindow::on_actionEyedropper_triggered() +{ + on_toolButton_Dropper_clicked(); +} + +void MainWindow::on_actionMove_triggered() +{ + on_toolButton_Move_clicked(); +} + +void MainWindow::on_actionMap_Shift_triggered() +{ + on_toolButton_Shift_clicked(); +} + void MainWindow::scaleMapView(int s) { editor->map->scale_exp += s; diff --git a/mainwindow.h b/mainwindow.h index 58380406..b020ee52 100755 --- a/mainwindow.h +++ b/mainwindow.h @@ -63,6 +63,12 @@ private slots: void on_actionZoom_In_triggered(); void on_actionZoom_Out_triggered(); void on_actionBetter_Cursors_triggered(); + void on_actionPencil_triggered(); + void on_actionPointer_triggered(); + void on_actionFlood_Fill_triggered(); + void on_actionEyedropper_triggered(); + void on_actionMove_triggered(); + void on_actionMap_Shift_triggered(); void on_toolButton_deleteObject_clicked(); void on_toolButton_Open_Scripts_clicked(); diff --git a/mainwindow.ui b/mainwindow.ui index 6b4ce23d..cde58531 100755 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -171,7 +171,7 @@ true - <html><head/><body><p>Editor</p><p><span style=" font-weight:600;">Click</span> and drag to draw on the map.</p><p><span style=" font-weight:600;">Right-click</span> and drag to select tiles.</p></body></html> + <html><head/><body><p>Pencil</p><p><span style=" font-weight:600;">Click</span> and drag to draw on the map.</p><p><span style=" font-weight:600;">Right-click</span> and drag to select tiles.</p></body></html> Paint @@ -214,7 +214,7 @@ - <html><head/><body><p>Flood Fill</p><p>Fills all similar tiles in a region with the selected metatiles or collision attributes</p></body></html> + <html><head/><body><p>Bucket Fill</p><p>Fills all similar tiles in a region with the selected metatiles or collision attributes</p></body></html> Fill @@ -231,7 +231,7 @@ - <html><head/><body><p>Eye Dropper</p><p><span style=" font-weight:600;">Click</span> to select a metatile or collision attribute.</p></body></html> + <html><head/><body><p>Eyedropper</p><p><span style=" font-weight:600;">Click</span> to select a metatile or collision attribute.</p></body></html> Dropper @@ -256,7 +256,7 @@ :/icons/move.ico:/icons/move.ico - + true @@ -378,7 +378,7 @@ 0 0 - 442 + 469 620 @@ -761,7 +761,7 @@ 0 0 - 302 + 275 86 @@ -867,7 +867,7 @@ 0 0 - 352 + 325 405 @@ -2128,9 +2128,21 @@ + + + Tools + + + + + + + + + @@ -2219,6 +2231,54 @@ <html><head/><body><p>Use reticule-styled cursors with icon showing currently selected tool.</p></body></html> + + + Pencil + + + N + + + + + Bucket Fill + + + B + + + + + Eyedropper + + + E + + + + + Move + + + M + + + + + Map Shift + + + S + + + + + Pointer + + + P + + From 9916295e41f585a53378f3f36d03e6038c23c218 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Fri, 14 Sep 2018 08:44:21 -0500 Subject: [PATCH 16/16] Create LICENSE.md --- LICENSE.md | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 LICENSE.md diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..65c5ca88 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library.