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.
diff --git a/editor.cpp b/editor.cpp
index 962907d9..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.
@@ -1145,8 +1218,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 +1233,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.
@@ -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);
@@ -1484,9 +1558,15 @@ void MapPixmapItem::updateCurHoveredTile(QPointF pos) {
void MapPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
updateCurHoveredTile(event->pos());
+ if (editor->ui->actionBetter_Cursors->isChecked()){
+ setCursor(editor->cursor);
+ }
}
void MapPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) {
map->clearHoveredTile();
+ if (editor->ui->actionBetter_Cursors->isChecked()){
+ unsetCursor();
+ }
}
void MapPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
QPointF pos = event->pos();
@@ -1653,6 +1733,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 863b096f..ab09c365 100755
--- a/editor.h
+++ b/editor.h
@@ -7,6 +7,7 @@
#include
#include
#include
+#include
#include "project.h"
#include "ui_mainwindow.h"
@@ -66,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);
@@ -108,6 +110,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);
@@ -130,6 +134,7 @@ private:
void updateMirroredConnection(Connection*, QString, QString, bool isDelete = false);
Event* createNewObjectEvent();
Event* createNewWarpEvent();
+ Event* createNewHealLocationEvent();
Event* createNewCoordScriptEvent();
Event* createNewCoordWeatherEvent();
Event* createNewSignEvent();
@@ -173,10 +178,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());
@@ -192,6 +195,7 @@ public:
objects.append(event);
event->pixmap = QPixmap();
editor->project->loadEventPixmaps(objects);
+ this->updatePosition();
editor->redrawObject(this);
emit spriteChanged(event->pixmap);
}
@@ -270,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/event.cpp b/event.cpp
index e26b4540..a1c6f5e4 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,9 +8,12 @@ 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()
{
+ this->spriteWidth = 16;
+ this->spriteHeight = 16;
}
Event* Event::createNewEvent(QString event_type, QString map_name)
@@ -19,6 +23,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 +70,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;
@@ -113,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");
@@ -150,6 +175,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 = "";
@@ -208,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 03313d27..fc71e8a7 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,14 +65,20 @@ public:
QString buildObjectEventMacro(int);
QString buildWarpEventMacro(QMap*);
+ HealLocation buildHealLocation();
QString buildCoordScriptEventMacro();
QString buildCoordWeatherEventMacro();
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/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 0320f809..1b05d0f1 100755
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -15,8 +15,14 @@
#include
#include
#include
+#include
#include
#include
+#include
+#include
+#include
+#include
+#include
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
@@ -53,6 +59,9 @@ MainWindow::MainWindow(QWidget *parent) :
}
}
+ if (settings.contains("cursor_mode") && settings.value("cursor_mode") == "0") {
+ ui->actionBetter_Cursors->setChecked(false);
+ }
}
MainWindow::~MainWindow()
@@ -551,6 +560,12 @@ void MainWindow::redo() {
editor->redo();
}
+// Open current map scripts in system default editor for .inc files
+void MainWindow::openInTextEditor() {
+ QString path = QDir::cleanPath("file://" + editor->project->root + QDir::separator() + "data/maps/" + editor->map->name + "/scripts.inc");
+ QDesktopServices::openUrl(QUrl(path));
+}
+
void MainWindow::on_action_Save_triggered() {
editor->save();
updateMapList();
@@ -591,6 +606,66 @@ void MainWindow::on_actionRedo_triggered()
redo();
}
+void MainWindow::on_actionZoom_In_triggered() {
+ scaleMapView(1);
+}
+
+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::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;
+
+ 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) {
@@ -649,9 +724,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)
);
@@ -709,8 +787,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";
@@ -864,38 +942,96 @@ 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();
}
}
}
+void MainWindow::on_toolButton_Open_Scripts_clicked()
+{
+ openInTextEditor();
+}
+
void MainWindow::on_toolButton_Paint_clicked()
{
editor->map_edit_mode = "paint";
+ editor->cursor = QCursor(QPixmap(":/icons/pencil_cursor.ico"), 10, 10);
+
+ 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_cursor.ico"), 10, 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_cursor.ico"), 10, 10);
+
+ 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();
+}
+
+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();
}
@@ -904,6 +1040,8 @@ 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");
+ ui->toolButton_Shift->setChecked(editor->map_edit_mode == "shift");
}
void MainWindow::onLoadMapRequested(QString mapName, QString fromMapName) {
@@ -1038,3 +1176,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 b8a12f8b..b020ee52 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);
@@ -58,7 +60,18 @@ private slots:
void on_actionRedo_triggered();
+ 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();
void addNewEvent(QString);
void updateSelectedObjects();
@@ -71,6 +84,10 @@ private slots:
void on_toolButton_Dropper_clicked();
+ void on_toolButton_Move_clicked();
+
+ void on_toolButton_Shift_clicked();
+
void onOpenMapListContextMenu(const QPoint &point);
void onAddNewMapToGroupClick(QAction* triggeredAction);
void onTilesetChanged(QString);
@@ -102,6 +119,8 @@ private slots:
void on_checkBox_Visibility_clicked(bool checked);
+ void on_checkBox_ToggleBorder_stateChanged(int arg1);
+
private:
Ui::MainWindow *ui;
QStandardItemModel *mapListModel;
@@ -124,6 +143,8 @@ private:
void displayMapProperties();
void checkToolButtons();
+
+ void scaleMapView(int);
};
enum MapListUserRoles {
diff --git a/mainwindow.ui b/mainwindow.ui
index dccacb4c..936ccaf2 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>Click 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
@@ -245,10 +245,44 @@
+ -
+
+
+ <html><head/><body><p>Move</p><p>Click to drag map around.</p></body></html>
+
+
+ ...
+
+
+
+ :/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
+
+
+
-
- <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
@@ -267,7 +301,17 @@
- Show Grid
+ Grid
+
+
+
+ -
+
+
+ Border
+
+
+ true
@@ -334,7 +378,7 @@
0
0
- 429
+ 469
620
@@ -362,9 +406,18 @@
0
+
+ false
+
false
+
+ QAbstractScrollArea::AdjustIgnored
+
+
+ QGraphicsView::NoDrag
+
-
@@ -708,7 +761,7 @@
0
0
- 315
+ 275
86
@@ -814,7 +867,7 @@
0
0
- 365
+ 325
405
@@ -1330,6 +1383,29 @@
+ -
+
+
+ Open Map Scripts
+
+
+ false
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 20
+ 20
+
+
+
+
@@ -2044,8 +2120,29 @@
+
+
+
+
@@ -2104,6 +2201,84 @@
Export Map Image...
+
+
+ Zoom In
+
+
+ +
+
+
+
+
+ Zoom Out
+
+
+ -
+
+
+
+
+ true
+
+
+ true
+
+
+ Cursor Icons
+
+
+ <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
+
+
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..b41c97c4 100755
--- a/map.h
+++ b/map.h
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
class HistoryItem {
public:
@@ -128,12 +129,15 @@ public:
QString layout_id;
QString location;
QString requiresFlash;
+ QString isFlyable; // TODO: implement this
QString weather;
QString type;
QString unknown;
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/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/porymap.pro b/porymap.pro
index 7c1e9358..f1d68efb 100755
--- a/porymap.pro
+++ b/porymap.pro
@@ -1,54 +1,56 @@
-#-------------------------------------------------
-#
-# Project created by QtCreator 2016-08-31T15:19:13
-#
-#-------------------------------------------------
-
-QT += core gui
-
-greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
-TARGET = porymap
-TEMPLATE = app
-RC_ICONS = resources/icons/porymap-icon-1.ico
-ICON = resources/icons/porymap-icon-1.ico
-
-
-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 = porymap
+TEMPLATE = app
+RC_ICONS = resources/icons/porymap-icon-1.ico
+ICON = resources/icons/porymap-icon-1.ico
+
+
+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..5bd0d2bb 100755
--- a/project.cpp
+++ b/project.cpp
@@ -501,6 +501,73 @@ 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;
+
+ // 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;
+ }
+ flyableMapsUnique.insert(xname);
+ }
+
+ // set new location in flyableMapsList
+ if (map->events["heal_event_group"].length() > 0) {
+ for (Event *heal : map->events["heal_event_group"]) {
+ HealLocation hl = heal->buildHealLocation();
+ flyableMaps[hl.index - 1] = hl;
+ }
+ }
+
+ 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 +1014,11 @@ 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;
+ delete hl;
}
Map* Project::addNewMapToGroup(QString mapName, int groupNum) {
@@ -1212,6 +1284,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);
@@ -1221,22 +1296,39 @@ 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) {
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);
}
}
}
@@ -1309,6 +1401,15 @@ void Project::saveMapEvents(Map *map) {
.arg(bgEventsLabel);
saveTextFile(path, text);
+
+ // save heal event changes
+ if (map->events["heal_event_group"].length() > 0) {
+ for (Event *heal : map->events["heal_event_group"]) {
+ HealLocation hl = heal->buildHealLocation();
+ flyableMaps[hl.index - 1] = hl;
+ }
+ }
+ saveHealLocationStruct(map);
}
void Project::readMapEvents(Map *map) {
@@ -1379,6 +1480,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 +1579,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..49e348b2 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;
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/icons/fill_color_cursor.ico b/resources/icons/fill_color_cursor.ico
new file mode 100644
index 00000000..712ab992
Binary files /dev/null and b/resources/icons/fill_color_cursor.ico differ
diff --git a/resources/icons/move.ico b/resources/icons/move.ico
new file mode 100644
index 00000000..1d247401
Binary files /dev/null and b/resources/icons/move.ico differ
diff --git a/resources/icons/pencil_cursor.ico b/resources/icons/pencil_cursor.ico
new file mode 100644
index 00000000..1ff8d8fb
Binary files /dev/null and b/resources/icons/pencil_cursor.ico differ
diff --git a/resources/icons/pipette_cursor.ico b/resources/icons/pipette_cursor.ico
new file mode 100644
index 00000000..8c226945
Binary files /dev/null and b/resources/icons/pipette_cursor.ico differ
diff --git a/resources/icons/shift.ico b/resources/icons/shift.ico
new file mode 100644
index 00000000..dab33a4e
Binary files /dev/null and b/resources/icons/shift.ico differ
diff --git a/resources/icons/shift_cursor.ico b/resources/icons/shift_cursor.ico
new file mode 100644
index 00000000..0c8722c3
Binary files /dev/null and b/resources/icons/shift_cursor.ico differ
diff --git a/resources/images.qrc b/resources/images.qrc
index 920c6aad..78fbe6a1 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
@@ -16,6 +17,11 @@
icons/delete.ico
icons/viewsprites.ico
images/collisions.png
+ icons/fill_color_cursor.ico
+ icons/pencil_cursor.ico
+ icons/pipette_cursor.ico
+ icons/shift.ico
+ icons/shift_cursor.ico
icons/porymap-icon-1.ico
diff --git a/resources/images/Entities_16x16.png b/resources/images/Entities_16x16.png
index db480f6e..2d35d31d 100755
Binary files a/resources/images/Entities_16x16.png and b/resources/images/Entities_16x16.png differ