pull upstream changes
merge branch 'huderlem/master' into 'garakmon/master'
437
editor.h
|
@ -1,437 +0,0 @@
|
|||
#ifndef EDITOR_H
|
||||
#define EDITOR_H
|
||||
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsItemGroup>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QGraphicsItemAnimation>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QCursor>
|
||||
|
||||
#include "project.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
class DraggablePixmapItem;
|
||||
class MapPixmapItem;
|
||||
class CollisionPixmapItem;
|
||||
class ConnectionPixmapItem;
|
||||
class MetatilesPixmapItem;
|
||||
class BorderMetatilesPixmapItem;
|
||||
class CurrentSelectedMetatilesPixmapItem;
|
||||
class MovementPermissionsPixmapItem;
|
||||
|
||||
#define SWAP(a, b) do { if (a != b) { a ^= b; b ^= a; a ^= b; } } while (0)
|
||||
|
||||
class Editor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Editor(Ui::MainWindow* ui);
|
||||
public:
|
||||
Ui::MainWindow* ui;
|
||||
QObject *parent = nullptr;
|
||||
Project *project = nullptr;
|
||||
Map *map = nullptr;
|
||||
void saveProject();
|
||||
void save();
|
||||
void undo();
|
||||
void redo();
|
||||
void setMap(QString map_name);
|
||||
void updateCurrentMetatilesSelection();
|
||||
void displayMap();
|
||||
void displayMetatiles();
|
||||
void displayBorderMetatiles();
|
||||
void displayCurrentMetatilesSelection();
|
||||
void redrawCurrentMetatilesSelection();
|
||||
void displayCollisionMetatiles();
|
||||
void displayElevationMetatiles();
|
||||
void displayMapEvents();
|
||||
void displayMapConnections();
|
||||
void displayMapBorder();
|
||||
void displayMapGrid();
|
||||
|
||||
void setEditingMap();
|
||||
void setEditingCollision();
|
||||
void setEditingObjects();
|
||||
void setEditingConnections();
|
||||
void setCurrentConnectionDirection(QString curDirection);
|
||||
void updateCurrentConnectionDirection(QString curDirection);
|
||||
void setConnectionsVisibility(bool visible);
|
||||
void updateConnectionOffset(int offset);
|
||||
void setConnectionMap(QString mapName);
|
||||
void addNewConnection();
|
||||
void removeCurrentConnection();
|
||||
void updateDiveMap(QString mapName);
|
||||
void updateEmergeMap(QString mapName);
|
||||
void setSelectedConnectionFromMap(QString mapName);
|
||||
void updatePrimaryTileset(QString tilesetLabel);
|
||||
void updateSecondaryTileset(QString tilesetLabel);
|
||||
void toggleBorderVisibility(bool visible);
|
||||
|
||||
DraggablePixmapItem *addMapEvent(Event *event);
|
||||
void selectMapEvent(DraggablePixmapItem *object);
|
||||
void selectMapEvent(DraggablePixmapItem *object, bool toggle);
|
||||
DraggablePixmapItem *addNewEvent(QString event_type);
|
||||
Event* createNewEvent(QString event_type);
|
||||
void deleteEvent(Event *);
|
||||
void updateSelectedEvents();
|
||||
void redrawObject(DraggablePixmapItem *item);
|
||||
QList<DraggablePixmapItem *> *getObjects();
|
||||
|
||||
QGraphicsScene *scene = nullptr;
|
||||
QGraphicsPixmapItem *current_view = nullptr;
|
||||
MapPixmapItem *map_item = nullptr;
|
||||
ConnectionPixmapItem* selected_connection_item = nullptr;
|
||||
QList<QGraphicsPixmapItem*> connection_items;
|
||||
QList<ConnectionPixmapItem*> connection_edit_items;
|
||||
CollisionPixmapItem *collision_item = nullptr;
|
||||
QGraphicsItemGroup *events_group = nullptr;
|
||||
QList<QGraphicsPixmapItem*> borderItems;
|
||||
QList<QGraphicsLineItem*> gridLines;
|
||||
|
||||
QGraphicsScene *scene_metatiles = nullptr;
|
||||
QGraphicsScene *scene_current_metatile_selection = nullptr;
|
||||
QGraphicsScene *scene_selected_border_metatiles = nullptr;
|
||||
QGraphicsScene *scene_collision_metatiles = nullptr;
|
||||
QGraphicsScene *scene_elevation_metatiles = nullptr;
|
||||
MetatilesPixmapItem *metatiles_item = nullptr;
|
||||
|
||||
BorderMetatilesPixmapItem *selected_border_metatiles_item = nullptr;
|
||||
CurrentSelectedMetatilesPixmapItem *scene_current_metatile_selection_item = nullptr;
|
||||
MovementPermissionsPixmapItem *collision_metatiles_item = nullptr;
|
||||
|
||||
QList<DraggablePixmapItem*> *events = nullptr;
|
||||
QList<DraggablePixmapItem*> *selected_events = nullptr;
|
||||
|
||||
bool lastSelectedMetatilesFromMap = false;
|
||||
int copiedMetatileSelectionWidth = 0;
|
||||
int copiedMetatileSelectionHeight = 0;
|
||||
QList<uint16_t> *copiedMetatileSelection = new QList<uint16_t>;
|
||||
|
||||
QString map_edit_mode;
|
||||
QString prev_edit_mode;
|
||||
QCursor cursor;
|
||||
|
||||
void objectsView_onMousePress(QMouseEvent *event);
|
||||
void objectsView_onMouseMove(QMouseEvent *event);
|
||||
void objectsView_onMouseRelease(QMouseEvent *event);
|
||||
|
||||
private:
|
||||
void setConnectionItemsVisible(bool);
|
||||
void setBorderItemsVisible(bool, qreal = 1);
|
||||
void setConnectionEditControlValues(Connection*);
|
||||
void setConnectionEditControlsEnabled(bool);
|
||||
void createConnectionItem(Connection* connection, bool hide);
|
||||
void populateConnectionMapPickers();
|
||||
void setDiveEmergeControls();
|
||||
void updateDiveEmergeMap(QString mapName, QString direction);
|
||||
void onConnectionOffsetChanged(int newOffset);
|
||||
void removeMirroredConnection(Connection*);
|
||||
void updateMirroredConnectionOffset(Connection*);
|
||||
void updateMirroredConnectionDirection(Connection*, QString);
|
||||
void updateMirroredConnectionMap(Connection*, QString);
|
||||
void updateMirroredConnection(Connection*, QString, QString, bool isDelete = false);
|
||||
Event* createNewObjectEvent();
|
||||
Event* createNewWarpEvent();
|
||||
Event* createNewHealLocationEvent();
|
||||
Event* createNewCoordScriptEvent();
|
||||
Event* createNewCoordWeatherEvent();
|
||||
Event* createNewSignEvent();
|
||||
Event* createNewHiddenItemEvent();
|
||||
Event* createNewSecretBaseEvent();
|
||||
|
||||
private slots:
|
||||
void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
|
||||
void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item);
|
||||
void onConnectionMoved(Connection*);
|
||||
void onConnectionItemSelected(ConnectionPixmapItem* connectionItem);
|
||||
void onConnectionItemDoubleClicked(ConnectionPixmapItem* connectionItem);
|
||||
void onConnectionDirectionChanged(QString newDirection);
|
||||
void onBorderMetatilesChanged();
|
||||
|
||||
signals:
|
||||
void objectsChanged();
|
||||
void selectedObjectsChanged();
|
||||
void loadMapRequested(QString, QString);
|
||||
void tilesetChanged(QString);
|
||||
void warpEventDoubleClicked(QString mapName, QString warpNum);
|
||||
void currentMetatilesSelectionChanged();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DraggablePixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DraggablePixmapItem(QPixmap pixmap): QGraphicsPixmapItem(pixmap) {
|
||||
}
|
||||
Editor *editor = nullptr;
|
||||
Event *event = nullptr;
|
||||
QGraphicsItemAnimation *pos_anim = nullptr;
|
||||
DraggablePixmapItem(Event *event_, Editor *editor_) : QGraphicsPixmapItem(event_->pixmap) {
|
||||
event = event_;
|
||||
editor = editor_;
|
||||
updatePosition();
|
||||
}
|
||||
bool active;
|
||||
int last_x;
|
||||
int last_y;
|
||||
void updatePosition() {
|
||||
int x = event->getPixelX();
|
||||
int y = event->getPixelY();
|
||||
setX(x);
|
||||
setY(y);
|
||||
setZValue(event->y());
|
||||
}
|
||||
void move(int x, int y);
|
||||
void emitPositionChanged() {
|
||||
emit xChanged(event->x());
|
||||
emit yChanged(event->y());
|
||||
emit elevationChanged(event->elevation());
|
||||
}
|
||||
void updatePixmap() {
|
||||
QList<Event*> objects;
|
||||
objects.append(event);
|
||||
event->pixmap = QPixmap();
|
||||
editor->project->loadEventPixmaps(objects);
|
||||
this->updatePosition();
|
||||
editor->redrawObject(this);
|
||||
emit spriteChanged(event->pixmap);
|
||||
}
|
||||
void bind(QComboBox *combo, QString key) {
|
||||
connect(combo, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
|
||||
this, [this, key](QString value){
|
||||
this->event->put(key, value);
|
||||
});
|
||||
connect(this, &DraggablePixmapItem::onPropertyChanged,
|
||||
this, [combo, key](QString key2, QString value){
|
||||
if (key2 == key) {
|
||||
combo->addItem(value);
|
||||
combo->setCurrentText(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
signals:
|
||||
void positionChanged(Event *event);
|
||||
void xChanged(int);
|
||||
void yChanged(int);
|
||||
void elevationChanged(int);
|
||||
void spriteChanged(QPixmap pixmap);
|
||||
void onPropertyChanged(QString key, QString value);
|
||||
|
||||
public slots:
|
||||
void set_x(const QString &text) {
|
||||
event->put("x", text);
|
||||
updatePosition();
|
||||
}
|
||||
void set_y(const QString &text) {
|
||||
event->put("y", text);
|
||||
updatePosition();
|
||||
}
|
||||
void set_elevation(const QString &text) {
|
||||
event->put("elevation", text);
|
||||
updatePosition();
|
||||
}
|
||||
void set_sprite(const QString &text) {
|
||||
event->put("sprite", text);
|
||||
updatePixmap();
|
||||
}
|
||||
void set_script(const QString &text) {
|
||||
event->put("script_label", text);
|
||||
}
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*);
|
||||
};
|
||||
|
||||
class EventGroup : public QGraphicsItemGroup {
|
||||
};
|
||||
|
||||
class MapPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MapPixmapItem(QPixmap pixmap): QGraphicsPixmapItem(pixmap) {
|
||||
}
|
||||
Map *map = nullptr;
|
||||
Editor *editor = nullptr;
|
||||
MapPixmapItem(Map *map_, Editor *editor_) {
|
||||
map = map_;
|
||||
editor = editor_;
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
bool active;
|
||||
bool right_click;
|
||||
QPoint selection_origin;
|
||||
QList<QPoint> selection;
|
||||
virtual void paint(QGraphicsSceneMouseEvent*);
|
||||
virtual void floodFill(QGraphicsSceneMouseEvent*);
|
||||
void _floodFill(int x, int y);
|
||||
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);
|
||||
|
||||
private:
|
||||
void updateCurHoveredTile(QPointF pos);
|
||||
void paintNormal(int x, int y);
|
||||
void paintSmartPath(int x, int y);
|
||||
static QList<int> smartPathTable;
|
||||
|
||||
signals:
|
||||
void mouseEvent(QGraphicsSceneMouseEvent *, MapPixmapItem *);
|
||||
|
||||
protected:
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
};
|
||||
|
||||
class CollisionPixmapItem : public MapPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CollisionPixmapItem(QPixmap pixmap): MapPixmapItem(pixmap) {
|
||||
}
|
||||
CollisionPixmapItem(Map *map_, Editor *editor_): MapPixmapItem(map_, editor_) {
|
||||
}
|
||||
void updateMovementPermissionSelection(QGraphicsSceneMouseEvent *event);
|
||||
virtual void paint(QGraphicsSceneMouseEvent*);
|
||||
virtual void floodFill(QGraphicsSceneMouseEvent*);
|
||||
virtual void pick(QGraphicsSceneMouseEvent*);
|
||||
virtual void draw(bool ignoreCache = false);
|
||||
|
||||
signals:
|
||||
void mouseEvent(QGraphicsSceneMouseEvent *, CollisionPixmapItem *);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
};
|
||||
|
||||
class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ConnectionPixmapItem(QPixmap pixmap, Connection* connection, int x, int y, int baseMapWidth, int baseMapHeight): QGraphicsPixmapItem(pixmap) {
|
||||
this->basePixmap = pixmap;
|
||||
this->connection = connection;
|
||||
setFlag(ItemIsMovable);
|
||||
setFlag(ItemSendsGeometryChanges);
|
||||
this->initialX = x;
|
||||
this->initialY = y;
|
||||
this->initialOffset = connection->offset.toInt();
|
||||
this->baseMapWidth = baseMapWidth;
|
||||
this->baseMapHeight = baseMapHeight;
|
||||
}
|
||||
void render(qreal opacity = 1) {
|
||||
QPixmap newPixmap = basePixmap.copy(0, 0, basePixmap.width(), basePixmap.height());
|
||||
if (opacity < 1) {
|
||||
QPainter painter(&newPixmap);
|
||||
int alpha = static_cast<int>(255 * (1 - opacity));
|
||||
painter.fillRect(0, 0, newPixmap.width(), newPixmap.height(), QColor(0, 0, 0, alpha));
|
||||
painter.end();
|
||||
}
|
||||
this->setPixmap(newPixmap);
|
||||
}
|
||||
int getMinOffset();
|
||||
int getMaxOffset();
|
||||
QPixmap basePixmap;
|
||||
Connection* connection;
|
||||
int initialX;
|
||||
int initialY;
|
||||
int initialOffset;
|
||||
int baseMapWidth;
|
||||
int baseMapHeight;
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*);
|
||||
signals:
|
||||
void connectionItemSelected(ConnectionPixmapItem* connectionItem);
|
||||
void connectionItemDoubleClicked(ConnectionPixmapItem* connectionItem);
|
||||
void connectionMoved(Connection*);
|
||||
};
|
||||
|
||||
class MetatilesPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MetatilesPixmapItem(Map *map_) {
|
||||
map = map_;
|
||||
setAcceptHoverEvents(true);
|
||||
connect(map, SIGNAL(paintTileChanged()), this, SLOT(paintTileChanged()));
|
||||
}
|
||||
Map* map = nullptr;
|
||||
virtual void draw();
|
||||
private:
|
||||
void updateSelection(QPointF pos);
|
||||
protected:
|
||||
virtual void updateCurHoveredMetatile(QPointF pos);
|
||||
private slots:
|
||||
void paintTileChanged();
|
||||
protected:
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
};
|
||||
|
||||
class BorderMetatilesPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
BorderMetatilesPixmapItem(Map *map_) {
|
||||
map = map_;
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
Map* map = nullptr;
|
||||
virtual void draw();
|
||||
signals:
|
||||
void borderMetatilesChanged();
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
};
|
||||
|
||||
class CurrentSelectedMetatilesPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CurrentSelectedMetatilesPixmapItem(Map *map_) {
|
||||
map = map_;
|
||||
}
|
||||
Map* map = nullptr;
|
||||
virtual void draw();
|
||||
};
|
||||
|
||||
class MovementPermissionsPixmapItem : public MetatilesPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MovementPermissionsPixmapItem(Map *map_): MetatilesPixmapItem(map_) {
|
||||
connect(map, SIGNAL(paintCollisionChanged(Map*)), this, SLOT(paintCollisionChanged(Map *)));
|
||||
}
|
||||
virtual void pick(uint16_t collision, uint16_t elevation) {
|
||||
map->paint_collision = collision;
|
||||
map->paint_elevation = elevation;
|
||||
draw();
|
||||
}
|
||||
virtual void draw() {
|
||||
setPixmap(map->renderCollisionMetatiles());
|
||||
}
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
virtual void updateCurHoveredMetatile(QPointF pos);
|
||||
private slots:
|
||||
void paintCollisionChanged(Map *) {
|
||||
draw();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // EDITOR_H
|
4
objectpropertiesframe.ui → forms/eventpropertiesframe.ui
Executable file → Normal file
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ObjectPropertiesFrame</class>
|
||||
<widget class="QFrame" name="ObjectPropertiesFrame">
|
||||
<class>EventPropertiesFrame</class>
|
||||
<widget class="QFrame" name="EventPropertiesFrame">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
31
mainwindow.ui → forms/mainwindow.ui
Executable file → Normal file
|
@ -73,7 +73,7 @@
|
|||
<string/>
|
||||
</property>
|
||||
<attribute name="icon">
|
||||
<iconset resource="resources/images.qrc">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/map.ico</normaloff>:/icons/map.ico</iconset>
|
||||
</attribute>
|
||||
<attribute name="title">
|
||||
|
@ -177,7 +177,7 @@
|
|||
<string>Paint</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources/images.qrc">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/pencil.ico</normaloff>:/icons/pencil.ico</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
|
@ -203,7 +203,7 @@
|
|||
<string>Select</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources/images.qrc">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/cursor.ico</normaloff>:/icons/cursor.ico</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
|
@ -220,7 +220,7 @@
|
|||
<string>Fill</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources/images.qrc">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/fill_color.ico</normaloff>:/icons/fill_color.ico</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
|
@ -237,7 +237,7 @@
|
|||
<string>Dropper</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources/images.qrc">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/pipette.ico</normaloff>:/icons/pipette.ico</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
|
@ -254,7 +254,7 @@
|
|||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources/images.qrc">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/move.ico</normaloff>:/icons/move.ico</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
|
@ -271,7 +271,7 @@
|
|||
<string>Shift</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources/images.qrc">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/shift.ico</normaloff>:/icons/shift.ico</iconset>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
|
@ -1355,7 +1355,7 @@
|
|||
<string>New Object</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources/images.qrc">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/add.ico</normaloff>:/icons/add.ico</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
|
@ -1384,7 +1384,7 @@
|
|||
<string>Delete</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources/images.qrc">
|
||||
<iconset resource="../resources/images.qrc">
|
||||
<normaloff>:/icons/delete.ico</normaloff>:/icons/delete.ico</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
|
@ -2127,6 +2127,8 @@
|
|||
<addaction name="actionEyedropper"/>
|
||||
<addaction name="actionMove"/>
|
||||
<addaction name="actionMap_Shift"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionTileset_Editor"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuEdit"/>
|
||||
|
@ -2195,7 +2197,7 @@
|
|||
<string>Zoom In</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>+</string>
|
||||
<string>Ctrl++</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZoom_Out">
|
||||
|
@ -2203,7 +2205,7 @@
|
|||
<string>Zoom Out</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>-</string>
|
||||
<string>Ctrl+-</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionBetter_Cursors">
|
||||
|
@ -2268,6 +2270,11 @@
|
|||
<string>P</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTileset_Editor">
|
||||
<property name="text">
|
||||
<string>Tileset Editor</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
|
@ -2288,7 +2295,7 @@
|
|||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="resources/images.qrc"/>
|
||||
<include location="../resources/images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
1536
forms/paletteeditor.ui
Normal file
445
forms/tileseteditor.ui
Normal file
|
@ -0,0 +1,445 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TilesetEditor</class>
|
||||
<widget class="QMainWindow" name="TilesetEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>MainWindow</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea_Metatiles">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>386</width>
|
||||
<height>539</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGraphicsView" name="graphicsView_Metatiles">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item alignment="Qt::AlignTop">
|
||||
<widget class="QFrame" name="frame_4">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Tile Properties</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Palette</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBox_paletteSelector"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>X Flip</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Y Flip</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Selection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_xFlip">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="checkBox_yFlip">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QGraphicsView" name="graphicsView_selectedTile">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Metatile Properties</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Bottom/Top</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGraphicsView" name="graphicsView_metatileLayers">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>64</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Metatile Behavior</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QComboBox" name="comboBox_metatileBehaviors"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>Layer Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QComboBox" name="comboBox_layerType"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea_Tiles">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>386</width>
|
||||
<height>359</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="1" column="2">
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QGraphicsView" name="graphicsView_Tiles">
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionSave_Tileset"/>
|
||||
<addaction name="separator"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuTools">
|
||||
<property name="title">
|
||||
<string>Tools</string>
|
||||
</property>
|
||||
<addaction name="actionImport_Primary_Tiles"/>
|
||||
<addaction name="actionImport_Secondary_Tiles"/>
|
||||
<addaction name="actionChange_Metatiles_Count"/>
|
||||
<addaction name="actionChange_Palettes"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuTools"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="actionSave_Tileset">
|
||||
<property name="text">
|
||||
<string>Save Tileset</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+S</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_Primary_Tiles">
|
||||
<property name="text">
|
||||
<string>Import Primary Tiles</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImport_Secondary_Tiles">
|
||||
<property name="text">
|
||||
<string>Import Secondary Tiles</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionChange_Metatiles_Count">
|
||||
<property name="text">
|
||||
<string>Change Number of Metatiles</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionChange_Palettes">
|
||||
<property name="text">
|
||||
<string>Change Palettes</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
0
block.h → include/core/block.h
Executable file → Normal file
0
blockdata.h → include/core/blockdata.h
Executable file → Normal file
2
event.h → include/core/event.h
Executable file → Normal file
|
@ -1,7 +1,6 @@
|
|||
#ifndef EVENT_H
|
||||
#define EVENT_H
|
||||
|
||||
#include "heallocation.h"
|
||||
#include <QString>
|
||||
#include <QPixmap>
|
||||
#include <QMap>
|
||||
|
@ -68,7 +67,6 @@ public:
|
|||
|
||||
QString buildObjectEventMacro(int);
|
||||
QString buildWarpEventMacro(QMap<QString, QString>*);
|
||||
HealLocation buildHealLocation();
|
||||
QString buildCoordScriptEventMacro();
|
||||
QString buildCoordWeatherEventMacro();
|
||||
QString buildSignEventMacro();
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef HEALLOCATION_H
|
||||
#define HEALLOCATION_H
|
||||
|
||||
#include "event.h"
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
|
@ -17,7 +18,7 @@ public:
|
|||
int index;
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
|
||||
static HealLocation fromEvent(Event*);
|
||||
};
|
||||
|
||||
#endif // HEALLOCATION_H
|
58
include/core/history.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
#ifndef HISTORY_H
|
||||
#define HISTORY_H
|
||||
|
||||
#include <QList>
|
||||
|
||||
template <typename T>
|
||||
class History {
|
||||
public:
|
||||
History() { }
|
||||
T back() {
|
||||
if (head > 0) {
|
||||
return history.at(--head);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
T next() {
|
||||
if (head + 1 < history.length()) {
|
||||
return history.at(++head);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void push(T commit) {
|
||||
while (head + 1 < history.length()) {
|
||||
T item = history.last();
|
||||
history.removeLast();
|
||||
delete item;
|
||||
}
|
||||
if (saved > head) {
|
||||
saved = -1;
|
||||
}
|
||||
history.append(commit);
|
||||
head++;
|
||||
}
|
||||
|
||||
T current() {
|
||||
if (head < 0 || history.length() == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return history.at(head);
|
||||
}
|
||||
|
||||
void save() {
|
||||
saved = head;
|
||||
}
|
||||
|
||||
bool isSaved() {
|
||||
return saved == head;
|
||||
}
|
||||
|
||||
private:
|
||||
QList<T> history;
|
||||
int head = -1;
|
||||
int saved = -1;
|
||||
};
|
||||
|
||||
#endif // HISTORY_H
|
15
include/core/historyitem.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef HISTORYITEM_H
|
||||
#define HISTORYITEM_H
|
||||
|
||||
#include "blockdata.h"
|
||||
|
||||
class HistoryItem {
|
||||
public:
|
||||
Blockdata *metatiles;
|
||||
int layoutWidth;
|
||||
int layoutHeight;
|
||||
HistoryItem(Blockdata *metatiles, int layoutWidth, int layoutHeight);
|
||||
~HistoryItem();
|
||||
};
|
||||
|
||||
#endif // HISTORYITEM_H
|
89
include/core/map.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
#ifndef MAP_H
|
||||
#define MAP_H
|
||||
|
||||
#include "blockdata.h"
|
||||
#include "history.h"
|
||||
#include "historyitem.h"
|
||||
#include "mapconnection.h"
|
||||
#include "maplayout.h"
|
||||
#include "tileset.h"
|
||||
#include "event.h"
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <math.h>
|
||||
|
||||
class Map : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Map(QObject *parent = nullptr);
|
||||
|
||||
public:
|
||||
QString name;
|
||||
QString constantName;
|
||||
QString group_num;
|
||||
QString layout_label;
|
||||
QString events_label;
|
||||
QString scripts_label;
|
||||
QString connections_label;
|
||||
QString song;
|
||||
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;
|
||||
bool isPersistedToFile = true;
|
||||
QImage collision_image;
|
||||
QPixmap collision_pixmap;
|
||||
QImage image;
|
||||
QPixmap pixmap;
|
||||
History<HistoryItem*> metatileHistory;
|
||||
QMap<QString, QList<Event*>> events;
|
||||
QList<MapConnection*> connections;
|
||||
void setName(QString mapName);
|
||||
static QString mapConstantFromName(QString mapName);
|
||||
static QString objectEventsLabelFromName(QString mapName);
|
||||
static QString warpEventsLabelFromName(QString mapName);
|
||||
static QString coordEventsLabelFromName(QString mapName);
|
||||
static QString bgEventsLabelFromName(QString mapName);
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
QPixmap render(bool ignoreCache);
|
||||
QPixmap renderCollision(bool ignoreCache);
|
||||
bool blockChanged(int, Blockdata*);
|
||||
void cacheBlockdata();
|
||||
void cacheCollision();
|
||||
Block *getBlock(int x, int y);
|
||||
void setBlock(int x, int y, Block block);
|
||||
void _setBlock(int x, int y, Block block);
|
||||
void floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
|
||||
void _floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
|
||||
void undo();
|
||||
void redo();
|
||||
void commit();
|
||||
QList<Event*> getAllEvents();
|
||||
void removeEvent(Event*);
|
||||
void addEvent(Event*);
|
||||
QPixmap renderConnection(MapConnection);
|
||||
QPixmap renderBorder();
|
||||
void setDimensions(int newWidth, int newHeight, bool setNewBlockData = true);
|
||||
void cacheBorder();
|
||||
bool hasUnsavedChanges();
|
||||
|
||||
private:
|
||||
void setNewDimensionsBlockdata(int newWidth, int newHeight);
|
||||
|
||||
signals:
|
||||
void mapChanged(Map *map);
|
||||
void mapNeedsRedrawing();
|
||||
};
|
||||
|
||||
#endif // MAP_H
|
14
include/core/mapconnection.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef MAPCONNECTION_H
|
||||
#define MAPCONNECTION_H
|
||||
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
|
||||
class MapConnection {
|
||||
public:
|
||||
QString direction;
|
||||
QString offset;
|
||||
QString map_name;
|
||||
};
|
||||
|
||||
#endif // MAPCONNECTION_H
|
41
include/core/maplayout.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef MAPLAYOUT_H
|
||||
#define MAPLAYOUT_H
|
||||
|
||||
#include "blockdata.h"
|
||||
#include "tileset.h"
|
||||
#include <QImage>
|
||||
#include <QPixmap>
|
||||
#include <QString>
|
||||
|
||||
class MapLayout {
|
||||
public:
|
||||
MapLayout() {}
|
||||
int index;
|
||||
QString name;
|
||||
QString label;
|
||||
QString width;
|
||||
QString height;
|
||||
QString border_label;
|
||||
QString border_path;
|
||||
QString blockdata_label;
|
||||
QString blockdata_path;
|
||||
QString tileset_primary_label;
|
||||
QString tileset_secondary_label;
|
||||
Tileset *tileset_primary = nullptr;
|
||||
Tileset *tileset_secondary = nullptr;
|
||||
Blockdata* blockdata = nullptr;
|
||||
QImage border_image;
|
||||
QPixmap border_pixmap;
|
||||
Blockdata *border = nullptr;
|
||||
Blockdata *cached_blockdata = nullptr;
|
||||
Blockdata *cached_collision = nullptr;
|
||||
Blockdata *cached_border = nullptr;
|
||||
bool has_unsaved_changes = false;
|
||||
public:
|
||||
static QString getNameFromLabel(QString label) {
|
||||
// ASSUMPTION: strip off "_Layout" from layout label. Directories in 'data/layouts/' must be well-formed.
|
||||
return label.replace(label.lastIndexOf("_Layout"), label.length(), "");
|
||||
}
|
||||
};
|
||||
|
||||
#endif // MAPLAYOUT_H
|
20
include/core/metatile.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef METATILE_H
|
||||
#define METATILE_H
|
||||
|
||||
#include "tile.h"
|
||||
#include <QImage>
|
||||
|
||||
class Metatile
|
||||
{
|
||||
public:
|
||||
Metatile();
|
||||
public:
|
||||
QList<Tile> *tiles = nullptr;
|
||||
uint8_t behavior;
|
||||
uint8_t layerType;
|
||||
|
||||
Metatile *copy();
|
||||
static int getBlockIndex(int);
|
||||
};
|
||||
|
||||
#endif // METATILE_H
|
0
parseutil.h → include/core/parseutil.h
Executable file → Normal file
0
tile.h → include/core/tile.h
Executable file → Normal file
23
tileset.h → include/core/tileset.h
Executable file → Normal file
|
@ -1,11 +1,10 @@
|
|||
#ifndef TILESET_H
|
||||
#define TILESET_H
|
||||
|
||||
#include "metatile.h"
|
||||
#include "tile.h"
|
||||
#include <QImage>
|
||||
|
||||
class Metatile;
|
||||
|
||||
class Tileset
|
||||
{
|
||||
public:
|
||||
|
@ -18,28 +17,24 @@ public:
|
|||
QString tiles_label;
|
||||
QString palettes_label;
|
||||
QString metatiles_label;
|
||||
QString metatiles_path;
|
||||
QString callback_label;
|
||||
QString metatile_attrs_label;
|
||||
QString metatile_attrs_path;
|
||||
QString tilesImagePath;
|
||||
QImage tilesImage;
|
||||
QList<QString> palettePaths;
|
||||
|
||||
QList<QImage> *tiles = nullptr;
|
||||
QList<Metatile*> *metatiles = nullptr;
|
||||
QList<QList<QRgb>> *palettes = nullptr;
|
||||
};
|
||||
|
||||
class Metatile
|
||||
{
|
||||
public:
|
||||
Metatile();
|
||||
public:
|
||||
QList<Tile> *tiles = nullptr;
|
||||
int attr;
|
||||
Tileset* copy();
|
||||
|
||||
static QImage getMetatileImage(int, Tileset*, Tileset*);
|
||||
static Metatile* getMetatile(int, Tileset*, Tileset*);
|
||||
static QImage getMetatileTile(int, Tileset*, Tileset*);
|
||||
static Tileset* getBlockTileset(int, Tileset*, Tileset*);
|
||||
static int getBlockIndex(int);
|
||||
static Metatile* getMetatile(int, Tileset*, Tileset*);
|
||||
static QList<QList<QRgb>> getBlockPalettes(Tileset*, Tileset*);
|
||||
static QList<QRgb> getPalette(int, Tileset*, Tileset*);
|
||||
};
|
||||
|
||||
#endif // TILESET_H
|
264
include/editor.h
Normal file
|
@ -0,0 +1,264 @@
|
|||
#ifndef EDITOR_H
|
||||
#define EDITOR_H
|
||||
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsItemGroup>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QGraphicsItemAnimation>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QCursor>
|
||||
|
||||
#include "mapconnection.h"
|
||||
#include "metatileselector.h"
|
||||
#include "movementpermissionsselector.h"
|
||||
#include "project.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "bordermetatilespixmapitem.h"
|
||||
#include "connectionpixmapitem.h"
|
||||
#include "currentselectedmetatilespixmapitem.h"
|
||||
#include "collisionpixmapitem.h"
|
||||
#include "mappixmapitem.h"
|
||||
#include "settings.h"
|
||||
|
||||
class DraggablePixmapItem;
|
||||
class MetatilesPixmapItem;
|
||||
|
||||
class Editor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Editor(Ui::MainWindow* ui);
|
||||
public:
|
||||
Ui::MainWindow* ui;
|
||||
QObject *parent = nullptr;
|
||||
Project *project = nullptr;
|
||||
Map *map = nullptr;
|
||||
Settings *settings;
|
||||
void saveProject();
|
||||
void save();
|
||||
void undo();
|
||||
void redo();
|
||||
void setMap(QString map_name);
|
||||
void displayMap();
|
||||
void displayMetatileSelector();
|
||||
void displayMapMetatiles();
|
||||
void displayMapMovementPermissions();
|
||||
void displayBorderMetatiles();
|
||||
void displayCurrentMetatilesSelection();
|
||||
void redrawCurrentMetatilesSelection();
|
||||
void displayMovementPermissionSelector();
|
||||
void displayElevationMetatiles();
|
||||
void displayMapEvents();
|
||||
void displayMapConnections();
|
||||
void displayMapBorder();
|
||||
void displayMapGrid();
|
||||
|
||||
void setEditingMap();
|
||||
void setEditingCollision();
|
||||
void setEditingObjects();
|
||||
void setEditingConnections();
|
||||
void setCurrentConnectionDirection(QString curDirection);
|
||||
void updateCurrentConnectionDirection(QString curDirection);
|
||||
void setConnectionsVisibility(bool visible);
|
||||
void updateConnectionOffset(int offset);
|
||||
void setConnectionMap(QString mapName);
|
||||
void addNewConnection();
|
||||
void removeCurrentConnection();
|
||||
void updateDiveMap(QString mapName);
|
||||
void updateEmergeMap(QString mapName);
|
||||
void setSelectedConnectionFromMap(QString mapName);
|
||||
void updatePrimaryTileset(QString tilesetLabel, bool forceLoad = false);
|
||||
void updateSecondaryTileset(QString tilesetLabel, bool forceLoad = false);
|
||||
void toggleBorderVisibility(bool visible);
|
||||
Tileset *getCurrentMapPrimaryTileset();
|
||||
|
||||
DraggablePixmapItem *addMapEvent(Event *event);
|
||||
void selectMapEvent(DraggablePixmapItem *object);
|
||||
void selectMapEvent(DraggablePixmapItem *object, bool toggle);
|
||||
DraggablePixmapItem *addNewEvent(QString event_type);
|
||||
Event* createNewEvent(QString event_type);
|
||||
void deleteEvent(Event *);
|
||||
void updateSelectedEvents();
|
||||
void redrawObject(DraggablePixmapItem *item);
|
||||
QList<DraggablePixmapItem *> *getObjects();
|
||||
|
||||
QGraphicsScene *scene = nullptr;
|
||||
QGraphicsPixmapItem *current_view = nullptr;
|
||||
MapPixmapItem *map_item = nullptr;
|
||||
ConnectionPixmapItem* selected_connection_item = nullptr;
|
||||
QList<QGraphicsPixmapItem*> connection_items;
|
||||
QList<ConnectionPixmapItem*> connection_edit_items;
|
||||
CollisionPixmapItem *collision_item = nullptr;
|
||||
QGraphicsItemGroup *events_group = nullptr;
|
||||
QList<QGraphicsPixmapItem*> borderItems;
|
||||
QList<QGraphicsLineItem*> gridLines;
|
||||
|
||||
QGraphicsScene *scene_metatiles = nullptr;
|
||||
QGraphicsScene *scene_current_metatile_selection = nullptr;
|
||||
QGraphicsScene *scene_selected_border_metatiles = nullptr;
|
||||
QGraphicsScene *scene_collision_metatiles = nullptr;
|
||||
QGraphicsScene *scene_elevation_metatiles = nullptr;
|
||||
MetatileSelector *metatile_selector_item = nullptr;
|
||||
|
||||
BorderMetatilesPixmapItem *selected_border_metatiles_item = nullptr;
|
||||
CurrentSelectedMetatilesPixmapItem *scene_current_metatile_selection_item = nullptr;
|
||||
MovementPermissionsSelector *movement_permissions_selector_item = nullptr;
|
||||
|
||||
QList<DraggablePixmapItem*> *events = nullptr;
|
||||
QList<DraggablePixmapItem*> *selected_events = nullptr;
|
||||
|
||||
QString map_edit_mode;
|
||||
QString prev_edit_mode;
|
||||
|
||||
int scale_exp = 0;
|
||||
double scale_base = sqrt(2); // adjust scale factor with this
|
||||
|
||||
void objectsView_onMousePress(QMouseEvent *event);
|
||||
void objectsView_onMouseMove(QMouseEvent *event);
|
||||
void objectsView_onMouseRelease(QMouseEvent *event);
|
||||
|
||||
private:
|
||||
void setConnectionItemsVisible(bool);
|
||||
void setBorderItemsVisible(bool, qreal = 1);
|
||||
void setConnectionEditControlValues(MapConnection*);
|
||||
void setConnectionEditControlsEnabled(bool);
|
||||
void createConnectionItem(MapConnection* connection, bool hide);
|
||||
void populateConnectionMapPickers();
|
||||
void setDiveEmergeControls();
|
||||
void updateDiveEmergeMap(QString mapName, QString direction);
|
||||
void onConnectionOffsetChanged(int newOffset);
|
||||
void removeMirroredConnection(MapConnection*);
|
||||
void updateMirroredConnectionOffset(MapConnection*);
|
||||
void updateMirroredConnectionDirection(MapConnection*, QString);
|
||||
void updateMirroredConnectionMap(MapConnection*, QString);
|
||||
void updateMirroredConnection(MapConnection*, QString, QString, bool isDelete = false);
|
||||
Event* createNewObjectEvent();
|
||||
Event* createNewWarpEvent();
|
||||
Event* createNewHealLocationEvent();
|
||||
Event* createNewCoordScriptEvent();
|
||||
Event* createNewCoordWeatherEvent();
|
||||
Event* createNewSignEvent();
|
||||
Event* createNewHiddenItemEvent();
|
||||
Event* createNewSecretBaseEvent();
|
||||
QString getMovementPermissionText(uint16_t collision, uint16_t elevation);
|
||||
|
||||
private slots:
|
||||
void mouseEvent_map(QGraphicsSceneMouseEvent *event, MapPixmapItem *item);
|
||||
void mouseEvent_collision(QGraphicsSceneMouseEvent *event, CollisionPixmapItem *item);
|
||||
void onConnectionMoved(MapConnection*);
|
||||
void onConnectionItemSelected(ConnectionPixmapItem* connectionItem);
|
||||
void onConnectionItemDoubleClicked(ConnectionPixmapItem* connectionItem);
|
||||
void onConnectionDirectionChanged(QString newDirection);
|
||||
void onBorderMetatilesChanged();
|
||||
void onHoveredMovementPermissionChanged(uint16_t, uint16_t);
|
||||
void onHoveredMovementPermissionCleared();
|
||||
void onHoveredMetatileSelectionChanged(uint16_t);
|
||||
void onHoveredMetatileSelectionCleared();
|
||||
void onHoveredMapMetatileChanged(int, int);
|
||||
void onHoveredMapMetatileCleared();
|
||||
void onHoveredMapMovementPermissionChanged(int, int);
|
||||
void onHoveredMapMovementPermissionCleared();
|
||||
void onSelectedMetatilesChanged();
|
||||
|
||||
signals:
|
||||
void objectsChanged();
|
||||
void selectedObjectsChanged();
|
||||
void loadMapRequested(QString, QString);
|
||||
void tilesetChanged(QString);
|
||||
void warpEventDoubleClicked(QString mapName, QString warpNum);
|
||||
void currentMetatilesSelectionChanged();
|
||||
void wheelZoom(int delta);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DraggablePixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DraggablePixmapItem(QPixmap pixmap): QGraphicsPixmapItem(pixmap) {
|
||||
}
|
||||
Editor *editor = nullptr;
|
||||
Event *event = nullptr;
|
||||
QGraphicsItemAnimation *pos_anim = nullptr;
|
||||
DraggablePixmapItem(Event *event_, Editor *editor_) : QGraphicsPixmapItem(event_->pixmap) {
|
||||
event = event_;
|
||||
editor = editor_;
|
||||
updatePosition();
|
||||
}
|
||||
bool active;
|
||||
int last_x;
|
||||
int last_y;
|
||||
void updatePosition() {
|
||||
int x = event->getPixelX();
|
||||
int y = event->getPixelY();
|
||||
setX(x);
|
||||
setY(y);
|
||||
setZValue(event->y());
|
||||
}
|
||||
void move(int x, int y);
|
||||
void emitPositionChanged() {
|
||||
emit xChanged(event->x());
|
||||
emit yChanged(event->y());
|
||||
emit elevationChanged(event->elevation());
|
||||
}
|
||||
void updatePixmap() {
|
||||
QList<Event*> objects;
|
||||
objects.append(event);
|
||||
event->pixmap = QPixmap();
|
||||
editor->project->loadEventPixmaps(objects);
|
||||
this->updatePosition();
|
||||
editor->redrawObject(this);
|
||||
emit spriteChanged(event->pixmap);
|
||||
}
|
||||
void bind(QComboBox *combo, QString key) {
|
||||
connect(combo, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentTextChanged),
|
||||
this, [this, key](QString value){
|
||||
this->event->put(key, value);
|
||||
});
|
||||
connect(this, &DraggablePixmapItem::onPropertyChanged,
|
||||
this, [combo, key](QString key2, QString value){
|
||||
if (key2 == key) {
|
||||
combo->addItem(value);
|
||||
combo->setCurrentText(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
signals:
|
||||
void positionChanged(Event *event);
|
||||
void xChanged(int);
|
||||
void yChanged(int);
|
||||
void elevationChanged(int);
|
||||
void spriteChanged(QPixmap pixmap);
|
||||
void onPropertyChanged(QString key, QString value);
|
||||
|
||||
public slots:
|
||||
void set_x(const QString &text) {
|
||||
event->put("x", text);
|
||||
updatePosition();
|
||||
}
|
||||
void set_y(const QString &text) {
|
||||
event->put("y", text);
|
||||
updatePosition();
|
||||
}
|
||||
void set_elevation(const QString &text) {
|
||||
event->put("elevation", text);
|
||||
updatePosition();
|
||||
}
|
||||
void set_sprite(const QString &text) {
|
||||
event->put("sprite", text);
|
||||
updatePixmap();
|
||||
}
|
||||
void set_script(const QString &text) {
|
||||
event->put("script_label", text);
|
||||
}
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*);
|
||||
};
|
||||
|
||||
#endif // EDITOR_H
|
20
mainwindow.h → include/mainwindow.h
Executable file → Normal file
|
@ -12,6 +12,7 @@
|
|||
#include "project.h"
|
||||
#include "map.h"
|
||||
#include "editor.h"
|
||||
#include "tileseteditor.h"
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
|
@ -26,7 +27,7 @@ public:
|
|||
~MainWindow();
|
||||
|
||||
public slots:
|
||||
void setStatusBarMessage(QString message, int timeout = 0);
|
||||
void scaleMapView(int);
|
||||
|
||||
private slots:
|
||||
void on_action_Open_Project_triggered();
|
||||
|
@ -42,6 +43,7 @@ private slots:
|
|||
void onLoadMapRequested(QString, QString);
|
||||
void onMapChanged(Map *map);
|
||||
void onMapNeedsRedrawing();
|
||||
void onTilesetsSaved(QString, QString);
|
||||
|
||||
void on_action_Save_triggered();
|
||||
void on_tabWidget_2_currentChanged(int index);
|
||||
|
@ -92,6 +94,7 @@ private slots:
|
|||
void onAddNewMapToGroupClick(QAction* triggeredAction);
|
||||
void onTilesetChanged(QString);
|
||||
void currentMetatilesSelectionChanged();
|
||||
void onTilesetEditorClosed();
|
||||
|
||||
void on_action_Export_Map_Image_triggered();
|
||||
|
||||
|
@ -121,13 +124,19 @@ private slots:
|
|||
|
||||
void on_checkBox_ToggleBorder_stateChanged(int arg1);
|
||||
|
||||
void resetMapViewScale();
|
||||
|
||||
void on_actionTileset_Editor_triggered();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
TilesetEditor *tilesetEditor = nullptr;
|
||||
QStandardItemModel *mapListModel;
|
||||
QList<QStandardItem*> *mapGroupsModel;
|
||||
QMap<QString, QModelIndex> mapListIndexes;
|
||||
Editor *editor = nullptr;
|
||||
QIcon* mapIcon;
|
||||
void setMap(QString);
|
||||
void setMap(QString, bool scrollTreeView = false);
|
||||
void redrawMapScene();
|
||||
void loadDataStructures();
|
||||
void populateMapList();
|
||||
|
@ -144,7 +153,12 @@ private:
|
|||
void displayMapProperties();
|
||||
void checkToolButtons();
|
||||
|
||||
void scaleMapView(int);
|
||||
void initExtraShortcuts();
|
||||
void initExtraSignals();
|
||||
void initEditor();
|
||||
void loadUserSettings();
|
||||
void openRecentProject();
|
||||
void updateTilesetEditor();
|
||||
};
|
||||
|
||||
enum MapListUserRoles {
|
15
project.h → include/project.h
Executable file → Normal file
|
@ -40,14 +40,16 @@ public:
|
|||
QStringList *secretBaseIds = nullptr;
|
||||
QStringList *bgEventFacingDirections = nullptr;
|
||||
QStringList mapsWithConnections;
|
||||
QMap<QString, int> metatileBehaviorMap;
|
||||
QMap<int, QString> metatileBehaviorMapInverse;
|
||||
|
||||
QMap<QString, Map*> *map_cache;
|
||||
Map* loadMap(QString);
|
||||
Map* getMap(QString);
|
||||
|
||||
QMap<QString, Tileset*> *tileset_cache = nullptr;
|
||||
Tileset* loadTileset(QString);
|
||||
Tileset* getTileset(QString);
|
||||
Tileset* loadTileset(QString, Tileset *tileset = nullptr);
|
||||
Tileset* getTileset(QString, bool forceLoad = false);
|
||||
|
||||
Blockdata* readBlockdata(QString);
|
||||
void loadBlockdata(Map*);
|
||||
|
@ -72,6 +74,8 @@ public:
|
|||
void readMapsWithConnections();
|
||||
void loadMapTilesets(Map*);
|
||||
void loadTilesetAssets(Tileset*);
|
||||
void loadTilesetTiles(Tileset*, QImage);
|
||||
void loadTilesetMetatiles(Tileset*);
|
||||
|
||||
void saveBlockdata(Map*);
|
||||
void saveMapBorder(Map*);
|
||||
|
@ -83,6 +87,7 @@ public:
|
|||
void saveMapGroupsTable();
|
||||
void saveMapConstantsHeader();
|
||||
void saveHealLocationStruct(Map*);
|
||||
void saveTilesets(Tileset*, Tileset*);
|
||||
|
||||
QList<QStringList>* parseAsm(QString text);
|
||||
QStringList getSongNames();
|
||||
|
@ -100,9 +105,11 @@ public:
|
|||
void readCoordEventWeatherNames();
|
||||
void readSecretBaseIds();
|
||||
void readBgEventFacingDirections();
|
||||
void readMetatileBehaviors();
|
||||
|
||||
void loadEventPixmaps(QList<Event*> objects);
|
||||
QMap<QString, int> getEventObjGfxConstants();
|
||||
QString fixPalettePath(QString path);
|
||||
QString fixGraphicPath(QString path);
|
||||
|
||||
void readMapEvents(Map *map);
|
||||
|
@ -127,6 +134,10 @@ private:
|
|||
QString getMapLayoutFilepath(QString);
|
||||
void saveMapHeader(Map*);
|
||||
void saveMapConnections(Map*);
|
||||
void saveTilesetMetatileAttributes(Tileset*);
|
||||
void saveTilesetMetatiles(Tileset*);
|
||||
void saveTilesetTilesImage(Tileset*);
|
||||
void saveTilesetPalettes(Tileset*, bool);
|
||||
void updateMapsWithConnections(Map*);
|
||||
void saveMapsWithConnections();
|
||||
void saveMapLayoutsTable();
|
15
include/settings.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef SETTINGS_H
|
||||
#define SETTINGS_H
|
||||
|
||||
#include <QCursor>
|
||||
|
||||
class Settings
|
||||
{
|
||||
public:
|
||||
Settings();
|
||||
bool smartPathsEnabled;
|
||||
bool betterCursors;
|
||||
QCursor mapCursor;
|
||||
};
|
||||
|
||||
#endif // SETTINGS_H
|
25
include/ui/bordermetatilespixmapitem.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef BORDERMETATILESPIXMAPITEM_H
|
||||
#define BORDERMETATILESPIXMAPITEM_H
|
||||
|
||||
#include "map.h"
|
||||
#include "metatileselector.h"
|
||||
#include <QGraphicsPixmapItem>
|
||||
|
||||
class BorderMetatilesPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
BorderMetatilesPixmapItem(Map *map_, MetatileSelector *metatileSelector) {
|
||||
this->map = map_;
|
||||
this->metatileSelector = metatileSelector;
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
MetatileSelector *metatileSelector;
|
||||
Map* map;
|
||||
void draw();
|
||||
signals:
|
||||
void borderMetatilesChanged();
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
};
|
||||
|
||||
#endif // BORDERMETATILESPIXMAPITEM_H
|
37
include/ui/collisionpixmapitem.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef COLLISIONPIXMAPITEM_H
|
||||
#define COLLISIONPIXMAPITEM_H
|
||||
|
||||
#include "metatileselector.h"
|
||||
#include "movementpermissionsselector.h"
|
||||
#include "mappixmapitem.h"
|
||||
#include "map.h"
|
||||
#include "settings.h"
|
||||
|
||||
class CollisionPixmapItem : public MapPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CollisionPixmapItem(Map *map, MovementPermissionsSelector *movementPermissionsSelector, MetatileSelector *metatileSelector, Settings *settings)
|
||||
: MapPixmapItem(map, metatileSelector, settings){
|
||||
this->movementPermissionsSelector = movementPermissionsSelector;
|
||||
}
|
||||
MovementPermissionsSelector *movementPermissionsSelector;
|
||||
void updateMovementPermissionSelection(QGraphicsSceneMouseEvent *event);
|
||||
virtual void paint(QGraphicsSceneMouseEvent*);
|
||||
virtual void floodFill(QGraphicsSceneMouseEvent*);
|
||||
virtual void pick(QGraphicsSceneMouseEvent*);
|
||||
virtual void draw(bool ignoreCache = false);
|
||||
|
||||
signals:
|
||||
void mouseEvent(QGraphicsSceneMouseEvent *, CollisionPixmapItem *);
|
||||
void hoveredMapMovementPermissionChanged(int, int);
|
||||
void hoveredMapMovementPermissionCleared();
|
||||
|
||||
protected:
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
};
|
||||
|
||||
#endif // COLLISIONPIXMAPITEM_H
|
44
include/ui/connectionpixmapitem.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef CONNECTIONPIXMAPITEM_H
|
||||
#define CONNECTIONPIXMAPITEM_H
|
||||
|
||||
#include "mapconnection.h"
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QPainter>
|
||||
|
||||
class ConnectionPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ConnectionPixmapItem(QPixmap pixmap, MapConnection* connection, int x, int y, int baseMapWidth, int baseMapHeight): QGraphicsPixmapItem(pixmap) {
|
||||
this->basePixmap = pixmap;
|
||||
this->connection = connection;
|
||||
setFlag(ItemIsMovable);
|
||||
setFlag(ItemSendsGeometryChanges);
|
||||
this->initialX = x;
|
||||
this->initialY = y;
|
||||
this->initialOffset = connection->offset.toInt();
|
||||
this->baseMapWidth = baseMapWidth;
|
||||
this->baseMapHeight = baseMapHeight;
|
||||
}
|
||||
QPixmap basePixmap;
|
||||
MapConnection* connection;
|
||||
int initialX;
|
||||
int initialY;
|
||||
int initialOffset;
|
||||
int baseMapWidth;
|
||||
int baseMapHeight;
|
||||
void render(qreal opacity = 1);
|
||||
int getMinOffset();
|
||||
int getMaxOffset();
|
||||
|
||||
protected:
|
||||
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent*);
|
||||
|
||||
signals:
|
||||
void connectionItemSelected(ConnectionPixmapItem* connectionItem);
|
||||
void connectionItemDoubleClicked(ConnectionPixmapItem* connectionItem);
|
||||
void connectionMoved(MapConnection*);
|
||||
};
|
||||
|
||||
#endif // CONNECTIONPIXMAPITEM_H
|
20
include/ui/currentselectedmetatilespixmapitem.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef CURRENTSELECTEDMETATILESPIXMAPITEM_H
|
||||
#define CURRENTSELECTEDMETATILESPIXMAPITEM_H
|
||||
|
||||
#include "map.h"
|
||||
#include "metatileselector.h"
|
||||
#include <QGraphicsPixmapItem>
|
||||
|
||||
class CurrentSelectedMetatilesPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CurrentSelectedMetatilesPixmapItem(Map *map, MetatileSelector *metatileSelector) {
|
||||
this->map = map;
|
||||
this->metatileSelector = metatileSelector;
|
||||
}
|
||||
Map* map = nullptr;
|
||||
MetatileSelector *metatileSelector;
|
||||
void draw();
|
||||
};
|
||||
|
||||
#endif // CURRENTSELECTEDMETATILESPIXMAPITEM_H
|
22
include/ui/eventpropertiesframe.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef EVENTPROPERTIESFRAME_H
|
||||
#define EVENTPROPERTIESFRAME_H
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
namespace Ui {
|
||||
class EventPropertiesFrame;
|
||||
}
|
||||
|
||||
class EventPropertiesFrame : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EventPropertiesFrame(QWidget *parent = nullptr);
|
||||
~EventPropertiesFrame();
|
||||
|
||||
public:
|
||||
Ui::EventPropertiesFrame *ui;
|
||||
};
|
||||
|
||||
#endif // EVENTPROPERTIESFRAME_H
|
0
graphicsview.h → include/ui/graphicsview.h
Executable file → Normal file
15
include/ui/imageproviders.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef IMAGEPROVIDERS_H
|
||||
#define IMAGEPROVIDERS_H
|
||||
|
||||
#include "block.h"
|
||||
#include "tileset.h"
|
||||
#include <QImage>
|
||||
#include <QPixmap>
|
||||
|
||||
QImage getCollisionMetatileImage(Block);
|
||||
QImage getCollisionMetatileImage(int, int);
|
||||
QImage getMetatileImage(uint16_t, Tileset*, Tileset*);
|
||||
QImage getTileImage(uint16_t, Tileset*, Tileset*);
|
||||
QImage getColoredTileImage(uint16_t, Tileset*, Tileset*, int);
|
||||
|
||||
#endif // IMAGEPROVIDERS_H
|
55
include/ui/mappixmapitem.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
#ifndef MAPPIXMAPITEM_H
|
||||
#define MAPPIXMAPITEM_H
|
||||
|
||||
#include "map.h"
|
||||
#include "settings.h"
|
||||
#include "metatileselector.h"
|
||||
#include <QGraphicsPixmapItem>
|
||||
|
||||
class MapPixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MapPixmapItem(Map *map_, MetatileSelector *metatileSelector, Settings *settings) {
|
||||
this->map = map_;
|
||||
this->metatileSelector = metatileSelector;
|
||||
this->settings = settings;
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
Map *map;
|
||||
MetatileSelector *metatileSelector;
|
||||
Settings *settings;
|
||||
bool active;
|
||||
bool right_click;
|
||||
int paint_tile_initial_x;
|
||||
int paint_tile_initial_y;
|
||||
QPoint selection_origin;
|
||||
QList<QPoint> selection;
|
||||
virtual void paint(QGraphicsSceneMouseEvent*);
|
||||
virtual void floodFill(QGraphicsSceneMouseEvent*);
|
||||
void _floodFill(int x, int y);
|
||||
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);
|
||||
|
||||
private:
|
||||
void paintNormal(int x, int y);
|
||||
void paintSmartPath(int x, int y);
|
||||
static QList<int> smartPathTable;
|
||||
|
||||
signals:
|
||||
void mouseEvent(QGraphicsSceneMouseEvent *, MapPixmapItem *);
|
||||
void hoveredMapMetatileChanged(int x, int y);
|
||||
void hoveredMapMetatileCleared();
|
||||
|
||||
protected:
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
};
|
||||
|
||||
#endif // MAPPIXMAPITEM_H
|
19
include/ui/mapsceneeventfilter.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef MAPSCENEEVENTFILTER_H
|
||||
#define MAPSCENEEVENTFILTER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class MapSceneEventFilter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||
public:
|
||||
explicit MapSceneEventFilter(QObject *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void wheelZoom(int delta);
|
||||
public slots:
|
||||
};
|
||||
|
||||
#endif // MAPSCENEEVENTFILTER_H
|
29
include/ui/metatilelayersitem.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef METATILELAYERSITEM_H
|
||||
#define METATILELAYERSITEM_H
|
||||
|
||||
#include "tileset.h"
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
|
||||
class MetatileLayersItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MetatileLayersItem(Metatile *metatile, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
this->metatile = metatile;
|
||||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
}
|
||||
void draw();
|
||||
void setTilesets(Tileset*, Tileset*);
|
||||
void setMetatile(Metatile*);
|
||||
private:
|
||||
Metatile* metatile;
|
||||
Tileset *primaryTileset;
|
||||
Tileset *secondaryTileset;
|
||||
signals:
|
||||
void tileChanged(int, int);
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
};
|
||||
|
||||
#endif // METATILELAYERSITEM_H
|
51
include/ui/metatileselector.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
#ifndef METATILESELECTOR_H
|
||||
#define METATILESELECTOR_H
|
||||
|
||||
#include "selectablepixmapitem.h"
|
||||
#include "tileset.h"
|
||||
|
||||
class MetatileSelector: public SelectablePixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MetatileSelector(int numMetatilesWide, Tileset *primaryTileset, Tileset *secondaryTileset): SelectablePixmapItem(16, 16) {
|
||||
this->externalSelection = false;
|
||||
this->numMetatilesWide = numMetatilesWide;
|
||||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
this->selectedMetatiles = new QList<uint16_t>();
|
||||
this->externalSelectedMetatiles = new QList<uint16_t>();
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
QPoint getSelectionDimensions();
|
||||
void draw();
|
||||
void select(uint16_t metatile);
|
||||
void setTilesets(Tileset*, Tileset*);
|
||||
QList<uint16_t>* getSelectedMetatiles();
|
||||
void setExternalSelection(int, int, QList<uint16_t>*);
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||
private:
|
||||
bool externalSelection;
|
||||
int numMetatilesWide;
|
||||
Tileset *primaryTileset;
|
||||
Tileset *secondaryTileset;
|
||||
QList<uint16_t> *selectedMetatiles;
|
||||
int externalSelectionWidth;
|
||||
int externalSelectionHeight;
|
||||
QList<uint16_t> *externalSelectedMetatiles;
|
||||
|
||||
void updateSelectedMetatiles();
|
||||
uint16_t getMetatileId(int x, int y);
|
||||
QPoint getMetatileIdCoords(uint16_t);
|
||||
|
||||
signals:
|
||||
void hoveredMetatileSelectionChanged(uint16_t);
|
||||
void hoveredMetatileSelectionCleared();
|
||||
void selectedMetatilesChanged();
|
||||
};
|
||||
|
||||
#endif // METATILESELECTOR_H
|
29
include/ui/movementpermissionsselector.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef MOVEMENTPERMISSIONSSELECTOR_H
|
||||
#define MOVEMENTPERMISSIONSSELECTOR_H
|
||||
|
||||
#include "selectablepixmapitem.h"
|
||||
|
||||
class MovementPermissionsSelector: public SelectablePixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MovementPermissionsSelector(): SelectablePixmapItem(32, 32, 1, 1) {
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
void draw();
|
||||
uint16_t getSelectedCollision();
|
||||
uint16_t getSelectedElevation();
|
||||
void select(uint16_t collision, uint16_t elevation);
|
||||
|
||||
protected:
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||
|
||||
private:
|
||||
void setSelectedMovementPermissions(QPointF);
|
||||
|
||||
signals:
|
||||
void hoveredMovementPermissionChanged(uint16_t, uint16_t);
|
||||
void hoveredMovementPermissionCleared();
|
||||
};
|
||||
|
||||
#endif // MOVEMENTPERMISSIONSSELECTOR_H
|
|
@ -9,7 +9,6 @@ class NewEventToolButton : public QToolButton
|
|||
Q_OBJECT
|
||||
public:
|
||||
explicit NewEventToolButton(QWidget *parent = nullptr);
|
||||
void initButton();
|
||||
QString getSelectedEventType();
|
||||
public slots:
|
||||
void newObject();
|
||||
|
@ -32,6 +31,7 @@ private:
|
|||
QAction *newSignAction;
|
||||
QAction *newHiddenItemAction;
|
||||
QAction *newSecretBaseAction;
|
||||
void init();
|
||||
};
|
||||
|
||||
#endif // NEWEVENTTOOLBUTTON_H
|
43
include/ui/paletteeditor.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef PALETTEEDITOR_H
|
||||
#define PALETTEEDITOR_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QSlider>
|
||||
#include <QFrame>
|
||||
#include "project.h"
|
||||
|
||||
namespace Ui {
|
||||
class PaletteEditor;
|
||||
}
|
||||
|
||||
class PaletteEditor : public QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PaletteEditor(Project*, Tileset*, Tileset*, QWidget *parent = nullptr);
|
||||
~PaletteEditor();
|
||||
void setPaletteId(int);
|
||||
|
||||
private:
|
||||
Ui::PaletteEditor *ui;
|
||||
Project *project = nullptr;
|
||||
QList<QList<QSlider*>> sliders;
|
||||
QList<QFrame*> frames;
|
||||
Tileset *primaryTileset;
|
||||
Tileset *secondaryTileset;
|
||||
void disableSliderSignals();
|
||||
void enableSliderSignals();
|
||||
void initColorSliders();
|
||||
void refreshColorSliders();
|
||||
void refreshColors();
|
||||
void refreshColor(int);
|
||||
void setColor(int);
|
||||
|
||||
signals:
|
||||
void closed();
|
||||
void changedPaletteColor();
|
||||
void changedPalette(int);
|
||||
private slots:
|
||||
void on_spinBox_PaletteId_valueChanged(int arg1);
|
||||
};
|
||||
|
||||
#endif // PALETTEEDITOR_H
|
40
include/ui/selectablepixmapitem.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef SELECTABLEPIXMAPITEM_H
|
||||
#define SELECTABLEPIXMAPITEM_H
|
||||
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
|
||||
class SelectablePixmapItem : public QObject, public QGraphicsPixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
SelectablePixmapItem(int cellWidth, int cellHeight): SelectablePixmapItem(cellWidth, cellHeight, INT_MAX, INT_MAX) {}
|
||||
SelectablePixmapItem(int cellWidth, int cellHeight, int maxSelectionWidth, int maxSelectionHeight) {
|
||||
this->cellWidth = cellWidth;
|
||||
this->cellHeight = cellHeight;
|
||||
this->maxSelectionWidth = maxSelectionWidth;
|
||||
this->maxSelectionHeight = maxSelectionHeight;
|
||||
}
|
||||
virtual QPoint getSelectionDimensions();
|
||||
virtual void draw() = 0;
|
||||
|
||||
protected:
|
||||
int cellWidth;
|
||||
int cellHeight;
|
||||
int maxSelectionWidth;
|
||||
int maxSelectionHeight;
|
||||
int selectionInitialX;
|
||||
int selectionInitialY;
|
||||
int selectionOffsetX;
|
||||
int selectionOffsetY;
|
||||
|
||||
QPoint getSelectionStart();
|
||||
void select(int, int, int, int);
|
||||
void updateSelection(int, int);
|
||||
QPoint getCellPos(QPointF);
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
virtual void drawSelection();
|
||||
};
|
||||
|
||||
#endif // SELECTABLEPIXMAPITEM_H
|
90
include/ui/tileseteditor.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
#ifndef TILESETEDITOR_H
|
||||
#define TILESETEDITOR_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include "project.h"
|
||||
#include "paletteeditor.h"
|
||||
#include "tileseteditormetatileselector.h"
|
||||
#include "tileseteditortileselector.h"
|
||||
#include "metatilelayersitem.h"
|
||||
|
||||
namespace Ui {
|
||||
class TilesetEditor;
|
||||
}
|
||||
|
||||
class TilesetEditor : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TilesetEditor(Project*, QString, QString, QWidget *parent = nullptr);
|
||||
~TilesetEditor();
|
||||
void setTilesets(QString, QString);
|
||||
void init(Project*, QString, QString);
|
||||
|
||||
private slots:
|
||||
void onHoveredMetatileChanged(uint16_t);
|
||||
void onHoveredMetatileCleared();
|
||||
void onSelectedMetatileChanged(uint16_t);
|
||||
void onHoveredTileChanged(uint16_t);
|
||||
void onHoveredTileCleared();
|
||||
void onSelectedTilesChanged();
|
||||
void onMetatileLayerTileChanged(int, int);
|
||||
void onPaletteEditorClosed();
|
||||
void onPaletteEditorChangedPaletteColor();
|
||||
void onPaletteEditorChangedPalette(int);
|
||||
|
||||
void on_spinBox_paletteSelector_valueChanged(int arg1);
|
||||
|
||||
void on_checkBox_xFlip_stateChanged(int arg1);
|
||||
|
||||
void on_checkBox_yFlip_stateChanged(int arg1);
|
||||
|
||||
void on_comboBox_metatileBehaviors_currentIndexChanged(const QString &arg1);
|
||||
|
||||
void on_comboBox_layerType_currentIndexChanged(int index);
|
||||
|
||||
void on_actionSave_Tileset_triggered();
|
||||
|
||||
void on_actionImport_Primary_Tiles_triggered();
|
||||
|
||||
void on_actionImport_Secondary_Tiles_triggered();
|
||||
|
||||
void on_actionChange_Metatiles_Count_triggered();
|
||||
|
||||
void on_actionChange_Palettes_triggered();
|
||||
|
||||
private:
|
||||
void closeEvent(QCloseEvent*);
|
||||
void initMetatileSelector();
|
||||
void initTileSelector();
|
||||
void initSelectedTileItem();
|
||||
void initMetatileLayersItem();
|
||||
void drawSelectedTiles();
|
||||
void importTilesetTiles(Tileset*, bool);
|
||||
void refresh();
|
||||
Ui::TilesetEditor *ui;
|
||||
TilesetEditorMetatileSelector *metatileSelector = nullptr;
|
||||
TilesetEditorTileSelector *tileSelector = nullptr;
|
||||
MetatileLayersItem *metatileLayersItem = nullptr;
|
||||
PaletteEditor *paletteEditor = nullptr;
|
||||
Project *project = nullptr;
|
||||
Metatile *metatile = nullptr;
|
||||
int paletteId;
|
||||
bool tileXFlip;
|
||||
bool tileYFlip;
|
||||
bool hasUnsavedChanges;
|
||||
Tileset *primaryTileset = nullptr;
|
||||
Tileset *secondaryTileset = nullptr;
|
||||
QGraphicsScene *metatilesScene = nullptr;
|
||||
QGraphicsScene *tilesScene = nullptr;
|
||||
QGraphicsScene *selectedTileScene = nullptr;
|
||||
QGraphicsPixmapItem *selectedTilePixmapItem = nullptr;
|
||||
QGraphicsScene *metatileLayersScene = nullptr;
|
||||
|
||||
signals:
|
||||
void tilesetsSaved(QString, QString);
|
||||
void closed();
|
||||
};
|
||||
|
||||
#endif // TILESETEDITOR_H
|
44
include/ui/tileseteditormetatileselector.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef TILESETEDITORMETATILESELECTOR_H
|
||||
#define TILESETEDITORMETATILESELECTOR_H
|
||||
|
||||
#include "selectablepixmapitem.h"
|
||||
#include "tileset.h"
|
||||
|
||||
class TilesetEditorMetatileSelector: public SelectablePixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset): SelectablePixmapItem(32, 32, 1, 1) {
|
||||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
this->numMetatilesWide = 8;
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
void draw();
|
||||
void select(uint16_t metatileId);
|
||||
void setTilesets(Tileset*, Tileset*);
|
||||
uint16_t getSelectedMetatile();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||
|
||||
private:
|
||||
Tileset *primaryTileset = nullptr;
|
||||
Tileset *secondaryTileset = nullptr;
|
||||
uint16_t selectedMetatile;
|
||||
int numMetatilesWide;
|
||||
void updateSelectedMetatile();
|
||||
uint16_t getMetatileId(int x, int y);
|
||||
QPoint getMetatileIdCoords(uint16_t);
|
||||
uint16_t getValidMetatileId(uint16_t);
|
||||
|
||||
signals:
|
||||
void hoveredMetatileChanged(uint16_t);
|
||||
void hoveredMetatileCleared();
|
||||
void selectedMetatileChanged(uint16_t);
|
||||
};
|
||||
|
||||
#endif // TILESETEDITORMETATILESELECTOR_H
|
52
include/ui/tileseteditortileselector.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#ifndef TILESETEDITORTILESELECTOR_H
|
||||
#define TILESETEDITORTILESELECTOR_H
|
||||
|
||||
#include "selectablepixmapitem.h"
|
||||
#include "tileset.h"
|
||||
|
||||
class TilesetEditorTileSelector: public SelectablePixmapItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
TilesetEditorTileSelector(Tileset *primaryTileset, Tileset *secondaryTileset): SelectablePixmapItem(16, 16, 2, 2) {
|
||||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
this->numTilesWide = 16;
|
||||
this->paletteId = 0;
|
||||
this->xFlip = false;
|
||||
this->yFlip = false;
|
||||
setAcceptHoverEvents(true);
|
||||
}
|
||||
void draw();
|
||||
void select(uint16_t metatileId);
|
||||
void setTilesets(Tileset*, Tileset*);
|
||||
void setPaletteId(int);
|
||||
void setTileFlips(bool, bool);
|
||||
QList<uint16_t> getSelectedTiles();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseMoveEvent(QGraphicsSceneMouseEvent*);
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent*);
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent*);
|
||||
|
||||
private:
|
||||
Tileset *primaryTileset;
|
||||
Tileset *secondaryTileset;
|
||||
QList<uint16_t> selectedTiles;
|
||||
int numTilesWide;
|
||||
int paletteId;
|
||||
bool xFlip;
|
||||
bool yFlip;
|
||||
void updateSelectedTiles();
|
||||
uint16_t getTileId(int x, int y);
|
||||
QPoint getTileCoords(uint16_t);
|
||||
QList<QRgb> getCurPaletteTable();
|
||||
|
||||
signals:
|
||||
void hoveredTileChanged(uint16_t);
|
||||
void hoveredTileCleared();
|
||||
void selectedTilesChanged();
|
||||
};
|
||||
|
||||
#endif // TILESETEDITORTILESELECTOR_H
|
236
map.h
|
@ -1,236 +0,0 @@
|
|||
#ifndef MAP_H
|
||||
#define MAP_H
|
||||
|
||||
#include "tileset.h"
|
||||
#include "blockdata.h"
|
||||
#include "event.h"
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <math.h>
|
||||
|
||||
class HistoryItem {
|
||||
public:
|
||||
Blockdata *metatiles;
|
||||
int layoutWidth;
|
||||
int layoutHeight;
|
||||
HistoryItem(Blockdata *metatiles_, int layoutWidth_, int layoutHeight_) {
|
||||
this->metatiles = metatiles_;
|
||||
this->layoutWidth = layoutWidth_;
|
||||
this->layoutHeight = layoutHeight_;
|
||||
}
|
||||
~HistoryItem() {
|
||||
if (metatiles) delete metatiles;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class History {
|
||||
public:
|
||||
History() {
|
||||
|
||||
}
|
||||
T back() {
|
||||
if (head > 0) {
|
||||
return history.at(--head);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
T next() {
|
||||
if (head + 1 < history.length()) {
|
||||
return history.at(++head);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void push(T commit) {
|
||||
while (head + 1 < history.length()) {
|
||||
HistoryItem *item = history.last();
|
||||
history.removeLast();
|
||||
delete item;
|
||||
}
|
||||
if (saved > head) {
|
||||
saved = -1;
|
||||
}
|
||||
history.append(commit);
|
||||
head++;
|
||||
}
|
||||
T current() {
|
||||
if (head < 0 || history.length() == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return history.at(head);
|
||||
}
|
||||
void save() {
|
||||
saved = head;
|
||||
}
|
||||
bool isSaved() {
|
||||
return saved == head;
|
||||
}
|
||||
|
||||
private:
|
||||
QList<T> history;
|
||||
int head = -1;
|
||||
int saved = -1;
|
||||
};
|
||||
|
||||
class Connection {
|
||||
public:
|
||||
Connection() {
|
||||
}
|
||||
public:
|
||||
QString direction;
|
||||
QString offset;
|
||||
QString map_name;
|
||||
};
|
||||
|
||||
class MapLayout {
|
||||
public:
|
||||
MapLayout() {}
|
||||
int index;
|
||||
QString name;
|
||||
QString label;
|
||||
QString width;
|
||||
QString height;
|
||||
QString border_label;
|
||||
QString border_path;
|
||||
QString blockdata_label;
|
||||
QString blockdata_path;
|
||||
QString tileset_primary_label;
|
||||
QString tileset_secondary_label;
|
||||
Tileset *tileset_primary = nullptr;
|
||||
Tileset *tileset_secondary = nullptr;
|
||||
Blockdata* blockdata = nullptr;
|
||||
QImage border_image;
|
||||
QPixmap border_pixmap;
|
||||
Blockdata *border = nullptr;
|
||||
Blockdata *cached_blockdata = nullptr;
|
||||
Blockdata *cached_collision = nullptr;
|
||||
Blockdata *cached_border = nullptr;
|
||||
bool has_unsaved_changes = false;
|
||||
public:
|
||||
static QString getNameFromLabel(QString label) {
|
||||
// ASSUMPTION: strip off "_Layout" from layout label. Directories in 'data/layouts/' must be well-formed.
|
||||
return label.replace(label.lastIndexOf("_Layout"), label.length(), "");
|
||||
}
|
||||
};
|
||||
|
||||
class Map : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Map(QObject *parent = nullptr);
|
||||
|
||||
public:
|
||||
QString name;
|
||||
QString constantName;
|
||||
QString group_num;
|
||||
QString layout_label;
|
||||
QString events_label;
|
||||
QString scripts_label;
|
||||
QString connections_label;
|
||||
QString song;
|
||||
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;
|
||||
|
||||
public:
|
||||
void setName(QString mapName);
|
||||
static QString mapConstantFromName(QString mapName);
|
||||
static QString objectEventsLabelFromName(QString mapName);
|
||||
static QString warpEventsLabelFromName(QString mapName);
|
||||
static QString coordEventsLabelFromName(QString mapName);
|
||||
static QString bgEventsLabelFromName(QString mapName);
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
uint16_t getSelectedBlockIndex(int);
|
||||
int getDisplayedBlockIndex(int);
|
||||
QPixmap render(bool ignoreCache);
|
||||
QPixmap renderMetatiles();
|
||||
|
||||
QPixmap renderCollision(bool ignoreCache);
|
||||
QImage collision_image;
|
||||
QPixmap collision_pixmap;
|
||||
QImage getCollisionMetatileImage(Block);
|
||||
QImage getCollisionMetatileImage(int, int);
|
||||
QPixmap renderCollisionMetatiles();
|
||||
|
||||
void drawSelection(int i, int w, int selectionWidth, int selectionHeight, QPainter *painter, int gridWidth);
|
||||
|
||||
bool blockChanged(int, Blockdata*);
|
||||
void cacheBlockdata();
|
||||
void cacheCollision();
|
||||
QImage image;
|
||||
QPixmap pixmap;
|
||||
QList<QImage> metatile_images;
|
||||
bool smart_paths_enabled = false;
|
||||
int paint_metatile_initial_x;
|
||||
int paint_metatile_initial_y;
|
||||
int paint_tile_index;
|
||||
int paint_tile_width = 1;
|
||||
int paint_tile_height = 1;
|
||||
int paint_tile_initial_x;
|
||||
int paint_tile_initial_y;
|
||||
int selected_metatiles_width;
|
||||
int selected_metatiles_height;
|
||||
QList<uint16_t> *selected_metatiles = nullptr;
|
||||
uint16_t paint_collision;
|
||||
uint16_t paint_elevation;
|
||||
|
||||
Block *getBlock(int x, int y);
|
||||
void setBlock(int x, int y, Block block);
|
||||
void _setBlock(int x, int y, Block block);
|
||||
|
||||
void floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
|
||||
void _floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_t elevation);
|
||||
|
||||
History<HistoryItem*> history;
|
||||
void undo();
|
||||
void redo();
|
||||
void commit();
|
||||
|
||||
QList<Event*> getAllEvents();
|
||||
void removeEvent(Event *event);
|
||||
void addEvent(Event *event);
|
||||
QMap<QString, QList<Event*>> events;
|
||||
|
||||
QList<Connection*> connections;
|
||||
QPixmap renderConnection(Connection);
|
||||
void setNewDimensionsBlockdata(int newWidth, int newHeight);
|
||||
void setDimensions(int newWidth, int newHeight, bool setNewBlockData = true);
|
||||
|
||||
QPixmap renderBorder();
|
||||
void cacheBorder();
|
||||
|
||||
bool hasUnsavedChanges();
|
||||
void hoveredTileChanged(int x, int y, int block);
|
||||
void clearHoveredTile();
|
||||
void hoveredMetatileChanged(int block);
|
||||
void clearHoveredMetatile();
|
||||
void hoveredMovementPermissionTileChanged(int collision, int elevation);
|
||||
void clearHoveredMovementPermissionTile();
|
||||
void setSelectedMetatilesFromTilePicker();
|
||||
|
||||
signals:
|
||||
void paintTileChanged();
|
||||
void paintCollisionChanged(Map *map);
|
||||
void mapChanged(Map *map);
|
||||
void mapNeedsRedrawing();
|
||||
void statusBarMessage(QString);
|
||||
|
||||
public slots:
|
||||
};
|
||||
|
||||
#endif // MAP_H
|
|
@ -1,14 +0,0 @@
|
|||
#include "objectpropertiesframe.h"
|
||||
#include "ui_objectpropertiesframe.h"
|
||||
|
||||
ObjectPropertiesFrame::ObjectPropertiesFrame(QWidget *parent) :
|
||||
QFrame(parent),
|
||||
ui(new Ui::ObjectPropertiesFrame)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
ObjectPropertiesFrame::~ObjectPropertiesFrame()
|
||||
{
|
||||
delete ui;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef OBJECTPROPERTIESFRAME_H
|
||||
#define OBJECTPROPERTIESFRAME_H
|
||||
|
||||
#include <QFrame>
|
||||
|
||||
namespace Ui {
|
||||
class ObjectPropertiesFrame;
|
||||
}
|
||||
|
||||
class ObjectPropertiesFrame : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ObjectPropertiesFrame(QWidget *parent = nullptr);
|
||||
~ObjectPropertiesFrame();
|
||||
|
||||
public:
|
||||
Ui::ObjectPropertiesFrame *ui;
|
||||
};
|
||||
|
||||
#endif // OBJECTPROPERTIESFRAME_H
|
116
porymap.pro
Executable file → Normal file
|
@ -14,43 +14,89 @@ 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
|
||||
SOURCES += src/core/block.cpp \
|
||||
src/core/blockdata.cpp \
|
||||
src/core/event.cpp \
|
||||
src/core/heallocation.cpp \
|
||||
src/core/historyitem.cpp \
|
||||
src/core/map.cpp \
|
||||
src/core/maplayout.cpp \
|
||||
src/core/metatile.cpp \
|
||||
src/core/parseutil.cpp \
|
||||
src/core/tile.cpp \
|
||||
src/core/tileset.cpp \
|
||||
src/ui/bordermetatilespixmapitem.cpp \
|
||||
src/ui/collisionpixmapitem.cpp \
|
||||
src/ui/connectionpixmapitem.cpp \
|
||||
src/ui/currentselectedmetatilespixmapitem.cpp \
|
||||
src/ui/eventpropertiesframe.cpp \
|
||||
src/ui/graphicsview.cpp \
|
||||
src/ui/imageproviders.cpp \
|
||||
src/ui/mappixmapitem.cpp \
|
||||
src/ui/mapsceneeventfilter.cpp \
|
||||
src/ui/metatilelayersitem.cpp \
|
||||
src/ui/metatileselector.cpp \
|
||||
src/ui/movementpermissionsselector.cpp \
|
||||
src/ui/neweventtoolbutton.cpp \
|
||||
src/ui/noscrollcombobox.cpp \
|
||||
src/ui/noscrollspinbox.cpp \
|
||||
src/ui/paletteeditor.cpp \
|
||||
src/ui/selectablepixmapitem.cpp \
|
||||
src/ui/tileseteditor.cpp \
|
||||
src/ui/tileseteditormetatileselector.cpp \
|
||||
src/ui/tileseteditortileselector.cpp \
|
||||
src/editor.cpp \
|
||||
src/main.cpp \
|
||||
src/mainwindow.cpp \
|
||||
src/project.cpp \
|
||||
src/settings.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
|
||||
HEADERS += include/core/block.h \
|
||||
include/core/blockdata.h \
|
||||
include/core/event.h \
|
||||
include/core/heallocation.h \
|
||||
include/core/history.h \
|
||||
include/core/historyitem.h \
|
||||
include/core/map.h \
|
||||
include/core/mapconnection.h \
|
||||
include/core/maplayout.h \
|
||||
include/core/metatile.h \
|
||||
include/core/parseutil.h \
|
||||
include/core/tile.h \
|
||||
include/core/tileset.h \
|
||||
include/ui/bordermetatilespixmapitem.h \
|
||||
include/ui/collisionpixmapitem.h \
|
||||
include/ui/connectionpixmapitem.h \
|
||||
include/ui/currentselectedmetatilespixmapitem.h \
|
||||
include/ui/eventpropertiesframe.h \
|
||||
include/ui/graphicsview.h \
|
||||
include/ui/imageproviders.h \
|
||||
include/ui/mappixmapitem.h \
|
||||
include/ui/mapsceneeventfilter.h \
|
||||
include/ui/metatilelayersitem.h \
|
||||
include/ui/metatileselector.h \
|
||||
include/ui/movementpermissionsselector.h \
|
||||
include/ui/neweventtoolbutton.h \
|
||||
include/ui/noscrollcombobox.h \
|
||||
include/ui/noscrollspinbox.h \
|
||||
include/ui/paletteeditor.h \
|
||||
include/ui/selectablepixmapitem.h \
|
||||
include/ui/tileseteditor.h \
|
||||
include/ui/tileseteditormetatileselector.h \
|
||||
include/ui/tileseteditortileselector.h \
|
||||
include/editor.h \
|
||||
include/mainwindow.h \
|
||||
include/project.h \
|
||||
include/settings.h
|
||||
|
||||
FORMS += mainwindow.ui \
|
||||
objectpropertiesframe.ui
|
||||
FORMS += forms/mainwindow.ui \
|
||||
forms/eventpropertiesframe.ui \
|
||||
forms/tileseteditor.ui \
|
||||
forms/paletteeditor.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources/images.qrc
|
||||
|
||||
INCLUDEPATH += include
|
||||
INCLUDEPATH += include/core
|
||||
INCLUDEPATH += include/ui
|
||||
|
|
0
resources/icons/add.ico
Executable file → Normal file
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
0
resources/icons/cursor.ico
Executable file → Normal file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
resources/icons/delete.ico
Executable file → Normal file
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
0
resources/icons/fill_color.ico
Executable file → Normal file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
resources/icons/folder.ico
Executable file → Normal file
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
0
resources/icons/folder_closed.ico
Executable file → Normal file
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
0
resources/icons/folder_closed_map.ico
Executable file → Normal file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
resources/icons/folder_image.ico
Executable file → Normal file
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
0
resources/icons/folder_map.ico
Executable file → Normal file
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
0
resources/icons/image.ico
Executable file → Normal file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
resources/icons/map.ico
Executable file → Normal file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
resources/icons/pencil.ico
Executable file → Normal file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
resources/icons/pipette.ico
Executable file → Normal file
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
0
resources/icons/viewsprites.ico
Executable file → Normal file
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
0
resources/images.qrc
Executable file → Normal file
0
resources/images/Entities_16x16.png
Executable file → Normal file
Before Width: | Height: | Size: 490 B After Width: | Height: | Size: 490 B |
0
block.cpp → src/core/block.cpp
Executable file → Normal file
1
blockdata.cpp → src/core/blockdata.cpp
Executable file → Normal file
|
@ -1,5 +1,4 @@
|
|||
#include "blockdata.h"
|
||||
#include <QDebug>
|
||||
|
||||
Blockdata::Blockdata(QObject *parent) : QObject(parent)
|
||||
{
|
15
event.cpp → src/core/event.cpp
Executable file → Normal file
|
@ -175,21 +175,6 @@ QString Event::buildWarpEventMacro(QMap<QString, QString> *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->getU16("x");
|
||||
hl.y = this->getU16("y");
|
||||
return hl;
|
||||
}
|
||||
|
||||
QString Event::buildCoordScriptEventMacro()
|
||||
{
|
||||
QString text = "";
|
|
@ -8,6 +8,21 @@ HealLocation::HealLocation(QString map, int i, uint16_t x, uint16_t y)
|
|||
this->y = y;
|
||||
}
|
||||
|
||||
HealLocation HealLocation::fromEvent(Event *event)
|
||||
{
|
||||
HealLocation hl;
|
||||
hl.name = event->get("loc_name");
|
||||
try {
|
||||
hl.index = event->get("index").toInt();
|
||||
}
|
||||
catch(...) {
|
||||
hl.index = 0;
|
||||
}
|
||||
hl.x = event->getU16("x");
|
||||
hl.y = event->getU16("y");
|
||||
return hl;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, const HealLocation &hl)
|
||||
{
|
||||
debug << "HealLocation_" + hl.name << "(" << hl.x << ',' << hl.y << ")";
|
4
src/core/history.cpp
Normal file
|
@ -0,0 +1,4 @@
|
|||
#include "history.h"
|
||||
#include "historyitem.h"
|
||||
|
||||
|
11
src/core/historyitem.cpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "historyitem.h"
|
||||
|
||||
HistoryItem::HistoryItem(Blockdata *metatiles, int layoutWidth, int layoutHeight) {
|
||||
this->metatiles = metatiles;
|
||||
this->layoutWidth = layoutWidth;
|
||||
this->layoutHeight = layoutHeight;
|
||||
}
|
||||
|
||||
HistoryItem::~HistoryItem() {
|
||||
if (this->metatiles) delete this->metatiles;
|
||||
}
|
174
map.cpp → src/core/map.cpp
Executable file → Normal file
|
@ -1,5 +1,8 @@
|
|||
#include "history.h"
|
||||
#include "historyitem.h"
|
||||
#include "map.h"
|
||||
#include "project.h"
|
||||
#include "imageproviders.h"
|
||||
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
|
@ -10,13 +13,6 @@
|
|||
|
||||
Map::Map(QObject *parent) : QObject(parent)
|
||||
{
|
||||
paint_tile_index = 1;
|
||||
paint_collision = 0;
|
||||
paint_elevation = 3;
|
||||
selected_metatiles_width = 1;
|
||||
selected_metatiles_height = 1;
|
||||
selected_metatiles = new QList<uint16_t>;
|
||||
selected_metatiles->append(1);
|
||||
}
|
||||
|
||||
void Map::setName(QString mapName) {
|
||||
|
@ -65,33 +61,6 @@ int Map::getHeight() {
|
|||
return layout->height.toInt(nullptr, 0);
|
||||
}
|
||||
|
||||
uint16_t Map::getSelectedBlockIndex(int index) {
|
||||
if (index < layout->tileset_primary->metatiles->length()) {
|
||||
return static_cast<uint16_t>(index);
|
||||
} else {
|
||||
return static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - layout->tileset_primary->metatiles->length());
|
||||
}
|
||||
}
|
||||
|
||||
int Map::getDisplayedBlockIndex(int index) {
|
||||
if (index < layout->tileset_primary->metatiles->length()) {
|
||||
return index;
|
||||
} else {
|
||||
return index - Project::getNumMetatilesPrimary() + layout->tileset_primary->metatiles->length();
|
||||
}
|
||||
}
|
||||
|
||||
QImage Map::getCollisionMetatileImage(Block block) {
|
||||
return getCollisionMetatileImage(block.collision, block.elevation);
|
||||
}
|
||||
|
||||
QImage Map::getCollisionMetatileImage(int collision, int elevation) {
|
||||
int x = collision * 16;
|
||||
int y = elevation * 16;
|
||||
QPixmap collisionImage = QPixmap(":/images/collisions.png").copy(x, y, 16, 16);
|
||||
return collisionImage.toImage();
|
||||
}
|
||||
|
||||
bool Map::blockChanged(int i, Blockdata *cache) {
|
||||
if (!cache)
|
||||
return true;
|
||||
|
@ -165,7 +134,7 @@ QPixmap Map::renderCollision(bool ignoreCache) {
|
|||
}
|
||||
changed_any = true;
|
||||
Block block = layout->blockdata->blocks->value(i);
|
||||
QImage metatile_image = Metatile::getMetatileImage(block.tile, layout->tileset_primary, layout->tileset_secondary);
|
||||
QImage metatile_image = getMetatileImage(block.tile, layout->tileset_primary, layout->tileset_secondary);
|
||||
QImage collision_metatile_image = getCollisionMetatileImage(block);
|
||||
int map_y = width_ ? i / width_ : 0;
|
||||
int map_x = width_ ? i % width_ : 0;
|
||||
|
@ -209,7 +178,7 @@ QPixmap Map::render(bool ignoreCache = false) {
|
|||
}
|
||||
changed_any = true;
|
||||
Block block = layout->blockdata->blocks->value(i);
|
||||
QImage metatile_image = Metatile::getMetatileImage(block.tile, layout->tileset_primary, layout->tileset_secondary);
|
||||
QImage metatile_image = getMetatileImage(block.tile, layout->tileset_primary, layout->tileset_secondary);
|
||||
int map_y = width_ ? i / width_ : 0;
|
||||
int map_x = width_ ? i % width_ : 0;
|
||||
QPoint metatile_origin = QPoint(map_x * 16, map_y * 16);
|
||||
|
@ -243,7 +212,7 @@ QPixmap Map::renderBorder() {
|
|||
}
|
||||
changed_any = true;
|
||||
Block block = layout->border->blocks->value(i);
|
||||
QImage metatile_image = Metatile::getMetatileImage(block.tile, layout->tileset_primary, layout->tileset_secondary);
|
||||
QImage metatile_image = getMetatileImage(block.tile, layout->tileset_primary, layout->tileset_secondary);
|
||||
int map_y = i / width_;
|
||||
int map_x = i % width_;
|
||||
painter.drawImage(QPoint(map_x * 16, map_y * 16), metatile_image);
|
||||
|
@ -256,8 +225,8 @@ QPixmap Map::renderBorder() {
|
|||
return layout->border_pixmap;
|
||||
}
|
||||
|
||||
QPixmap Map::renderConnection(Connection connection) {
|
||||
render();
|
||||
QPixmap Map::renderConnection(MapConnection connection) {
|
||||
render(true);
|
||||
int x, y, w, h;
|
||||
if (connection.direction == "up") {
|
||||
x = 0;
|
||||
|
@ -291,68 +260,6 @@ QPixmap Map::renderConnection(Connection connection) {
|
|||
return QPixmap::fromImage(connection_image);
|
||||
}
|
||||
|
||||
QPixmap Map::renderCollisionMetatiles() {
|
||||
int width_ = 2;
|
||||
int height_ = 16;
|
||||
QImage image(width_ * 32, height_ * 32, QImage::Format_RGBA8888);
|
||||
QPainter painter(&image);
|
||||
for (int i = 0; i < width_; i++) {
|
||||
for (int j = 0; j < height_; j++) {
|
||||
QPoint origin(i * 32, j * 32);
|
||||
QImage metatile_image = getCollisionMetatileImage(i, j).scaled(32, 32);
|
||||
painter.drawImage(origin, metatile_image);
|
||||
}
|
||||
}
|
||||
drawSelection(paint_collision + paint_elevation * width_, width_, 1, 1, &painter, 32);
|
||||
painter.end();
|
||||
return QPixmap::fromImage(image);
|
||||
}
|
||||
|
||||
void Map::drawSelection(int i, int w, int selectionWidth, int selectionHeight, QPainter *painter, int gridWidth) {
|
||||
int x = i % w;
|
||||
int y = i / w;
|
||||
painter->save();
|
||||
|
||||
QColor penColor = QColor(0xff, 0xff, 0xff);
|
||||
painter->setPen(penColor);
|
||||
int rectWidth = selectionWidth * gridWidth;
|
||||
int rectHeight = selectionHeight * gridWidth;
|
||||
painter->drawRect(x * gridWidth, y * gridWidth, rectWidth - 1, rectHeight -1);
|
||||
painter->setPen(QColor(0, 0, 0));
|
||||
painter->drawRect(x * gridWidth - 1, y * gridWidth - 1, rectWidth + 1, rectHeight + 1);
|
||||
painter->drawRect(x * gridWidth + 1, y * gridWidth + 1, rectWidth - 3, rectHeight - 3);
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QPixmap Map::renderMetatiles() {
|
||||
if (!layout->tileset_primary || !layout->tileset_primary->metatiles
|
||||
|| !layout->tileset_secondary || !layout->tileset_secondary->metatiles) {
|
||||
return QPixmap();
|
||||
}
|
||||
int primary_length = layout->tileset_primary->metatiles->length();
|
||||
int length_ = primary_length + layout->tileset_secondary->metatiles->length();
|
||||
int width_ = 8;
|
||||
int height_ = length_ / width_;
|
||||
QImage image(width_ * 16, height_ * 16, QImage::Format_RGBA8888);
|
||||
QPainter painter(&image);
|
||||
for (int i = 0; i < length_; i++) {
|
||||
int tile = i;
|
||||
if (i >= primary_length) {
|
||||
tile += Project::getNumMetatilesPrimary() - primary_length;
|
||||
}
|
||||
QImage metatile_image = Metatile::getMetatileImage(tile, layout->tileset_primary, layout->tileset_secondary);
|
||||
int map_y = i / width_;
|
||||
int map_x = i % width_;
|
||||
QPoint metatile_origin = QPoint(map_x * 16, map_y * 16);
|
||||
painter.drawImage(metatile_origin, metatile_image);
|
||||
}
|
||||
|
||||
drawSelection(paint_tile_index, width_, paint_tile_width, paint_tile_height, &painter, 16);
|
||||
|
||||
painter.end();
|
||||
return QPixmap::fromImage(image);
|
||||
}
|
||||
|
||||
void Map::setNewDimensionsBlockdata(int newWidth, int newHeight) {
|
||||
int oldWidth = getWidth();
|
||||
int oldHeight = getHeight();
|
||||
|
@ -438,7 +345,7 @@ void Map::_floodFillCollisionElevation(int x, int y, uint16_t collision, uint16_
|
|||
|
||||
|
||||
void Map::undo() {
|
||||
HistoryItem *commit = history.back();
|
||||
HistoryItem *commit = metatileHistory.back();
|
||||
if (!commit)
|
||||
return;
|
||||
|
||||
|
@ -455,7 +362,7 @@ void Map::undo() {
|
|||
}
|
||||
|
||||
void Map::redo() {
|
||||
HistoryItem *commit = history.next();
|
||||
HistoryItem *commit = metatileHistory.next();
|
||||
if (!commit)
|
||||
return;
|
||||
|
||||
|
@ -473,14 +380,14 @@ void Map::redo() {
|
|||
|
||||
void Map::commit() {
|
||||
if (layout->blockdata) {
|
||||
HistoryItem *item = history.current();
|
||||
HistoryItem *item = metatileHistory.current();
|
||||
bool atCurrentHistory = item
|
||||
&& layout->blockdata->equals(item->metatiles)
|
||||
&& this->getWidth() == item->layoutWidth
|
||||
&& this->getHeight() == item->layoutHeight;
|
||||
if (!atCurrentHistory) {
|
||||
HistoryItem *commit = new HistoryItem(layout->blockdata->copy(), this->getWidth(), this->getHeight());
|
||||
history.push(commit);
|
||||
metatileHistory.push(commit);
|
||||
emit mapChanged(this);
|
||||
}
|
||||
}
|
||||
|
@ -521,60 +428,5 @@ void Map::addEvent(Event *event) {
|
|||
}
|
||||
|
||||
bool Map::hasUnsavedChanges() {
|
||||
return !history.isSaved() || !isPersistedToFile || layout->has_unsaved_changes;
|
||||
return !metatileHistory.isSaved() || !isPersistedToFile || layout->has_unsaved_changes;
|
||||
}
|
||||
|
||||
void Map::hoveredTileChanged(int x, int y, int block) {
|
||||
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::number(pow(this->scale_base,this->scale_exp))));
|
||||
}
|
||||
|
||||
void Map::clearHoveredTile() {
|
||||
emit statusBarMessage(QString(""));
|
||||
}
|
||||
|
||||
void Map::hoveredMetatileChanged(int blockIndex) {
|
||||
uint16_t tile = getSelectedBlockIndex(blockIndex);
|
||||
emit statusBarMessage(QString("Metatile: 0x%1")
|
||||
.arg(QString("%1").arg(tile, 3, 16, QChar('0')).toUpper()));
|
||||
}
|
||||
|
||||
void Map::clearHoveredMetatile() {
|
||||
emit statusBarMessage(QString(""));
|
||||
}
|
||||
|
||||
void Map::hoveredMovementPermissionTileChanged(int collision, int elevation) {
|
||||
QString message;
|
||||
if (collision == 0 && elevation == 0) {
|
||||
message = "Collision: Transition between elevations";
|
||||
} else if (collision == 0 && elevation == 15) {
|
||||
message = "Collision: Multi-Level (Bridge)";
|
||||
} else if (collision == 0 && elevation == 1) {
|
||||
message = "Collision: Surf";
|
||||
} else if (collision == 0) {
|
||||
message = QString("Collision: Passable, Elevation: %1").arg(elevation);
|
||||
} else {
|
||||
message = QString("Collision: Impassable, Elevation: %1").arg(elevation);
|
||||
}
|
||||
emit statusBarMessage(message);
|
||||
}
|
||||
|
||||
void Map::clearHoveredMovementPermissionTile() {
|
||||
emit statusBarMessage(QString(""));
|
||||
}
|
||||
|
||||
void Map::setSelectedMetatilesFromTilePicker() {
|
||||
this->selected_metatiles_width = this->paint_tile_width;
|
||||
this->selected_metatiles_height = this->paint_tile_height;
|
||||
this->selected_metatiles->clear();
|
||||
for (int j = 0; j < this->paint_tile_height; j++) {
|
||||
for (int i = 0; i < this->paint_tile_width; i++) {
|
||||
uint16_t metatile = this->getSelectedBlockIndex(this->paint_tile_index + i + (j * 8));
|
||||
this->selected_metatiles->append(metatile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
src/core/maplayout.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#include "maplayout.h"
|
||||
|
27
src/core/metatile.cpp
Normal file
|
@ -0,0 +1,27 @@
|
|||
#include "metatile.h"
|
||||
#include "tileset.h"
|
||||
#include "project.h"
|
||||
|
||||
Metatile::Metatile()
|
||||
{
|
||||
tiles = new QList<Tile>;
|
||||
}
|
||||
|
||||
Metatile* Metatile::copy() {
|
||||
Metatile *copy = new Metatile;
|
||||
copy->behavior = this->behavior;
|
||||
copy->layerType = this->layerType;
|
||||
copy->tiles = new QList<Tile>;
|
||||
for (Tile tile : *this->tiles) {
|
||||
copy->tiles->append(tile);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
int Metatile::getBlockIndex(int index) {
|
||||
if (index < Project::getNumMetatilesPrimary()) {
|
||||
return index;
|
||||
} else {
|
||||
return index - Project::getNumMetatilesPrimary();
|
||||
}
|
||||
}
|
0
parseutil.cpp → src/core/parseutil.cpp
Executable file → Normal file
0
tile.cpp → src/core/tile.cpp
Executable file → Normal file
89
src/core/tileset.cpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include "tileset.h"
|
||||
#include "metatile.h"
|
||||
#include "project.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QImage>
|
||||
#include <QDebug>
|
||||
|
||||
Tileset::Tileset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Tileset* Tileset::copy() {
|
||||
Tileset *copy = new Tileset;
|
||||
copy->name = this->name;
|
||||
copy->is_compressed = this->is_compressed;
|
||||
copy->is_secondary = this->is_secondary;
|
||||
copy->padding = this->padding;
|
||||
copy->tiles_label = this->tiles_label;
|
||||
copy->palettes_label = this->palettes_label;
|
||||
copy->metatiles_label = this->metatiles_label;
|
||||
copy->metatiles_path = this->metatiles_path;
|
||||
copy->callback_label = this->callback_label;
|
||||
copy->metatile_attrs_label = this->metatile_attrs_label;
|
||||
copy->metatile_attrs_path = this->metatile_attrs_path;
|
||||
copy->tilesImage = this->tilesImage.copy();
|
||||
copy->tilesImagePath = this->tilesImagePath;
|
||||
for (int i = 0; i < this->palettePaths.length(); i++) {
|
||||
copy->palettePaths.append(this->palettePaths.at(i));
|
||||
}
|
||||
copy->tiles = new QList<QImage>;
|
||||
for (QImage tile : *this->tiles) {
|
||||
copy->tiles->append(tile.copy());
|
||||
}
|
||||
copy->metatiles = new QList<Metatile*>;
|
||||
for (Metatile *metatile : *this->metatiles) {
|
||||
copy->metatiles->append(metatile->copy());
|
||||
}
|
||||
copy->palettes = new QList<QList<QRgb>>;
|
||||
for (QList<QRgb> palette : *this->palettes) {
|
||||
QList<QRgb> copyPalette;
|
||||
for (QRgb color : palette) {
|
||||
copyPalette.append(color);
|
||||
}
|
||||
copy->palettes->append(copyPalette);
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
Tileset* Tileset::getBlockTileset(int metatile_index, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
if (metatile_index < Project::getNumMetatilesPrimary()) {
|
||||
return primaryTileset;
|
||||
} else {
|
||||
return secondaryTileset;
|
||||
}
|
||||
}
|
||||
|
||||
Metatile* Tileset::getMetatile(int index, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
Tileset *tileset = Tileset::getBlockTileset(index, primaryTileset, secondaryTileset);
|
||||
int local_index = Metatile::getBlockIndex(index);
|
||||
if (!tileset || !tileset->metatiles) {
|
||||
return nullptr;
|
||||
}
|
||||
Metatile *metatile = tileset->metatiles->value(local_index, nullptr);
|
||||
return metatile;
|
||||
}
|
||||
|
||||
QList<QList<QRgb>> Tileset::getBlockPalettes(Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
QList<QList<QRgb>> palettes;
|
||||
for (int i = 0; i < Project::getNumPalettesPrimary(); i++) {
|
||||
palettes.append(primaryTileset->palettes->at(i));
|
||||
}
|
||||
for (int i = Project::getNumPalettesPrimary(); i < Project::getNumPalettesTotal(); i++) {
|
||||
palettes.append(secondaryTileset->palettes->at(i));
|
||||
}
|
||||
return palettes;
|
||||
}
|
||||
|
||||
QList<QRgb> Tileset::getPalette(int paletteId, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
QList<QRgb> paletteTable;
|
||||
Tileset *tileset = paletteId < Project::getNumPalettesPrimary()
|
||||
? primaryTileset
|
||||
: secondaryTileset;
|
||||
for (int i = 0; i < tileset->palettes->at(paletteId).length(); i++) {
|
||||
paletteTable.append(tileset->palettes->at(paletteId).at(i));
|
||||
}
|
||||
return paletteTable;
|
||||
}
|
1041
editor.cpp → src/editor.cpp
Executable file → Normal file
0
main.cpp → src/main.cpp
Executable file → Normal file
201
mainwindow.cpp → src/mainwindow.cpp
Executable file → Normal file
|
@ -2,8 +2,10 @@
|
|||
#include "ui_mainwindow.h"
|
||||
#include "project.h"
|
||||
#include "editor.h"
|
||||
#include "objectpropertiesframe.h"
|
||||
#include "ui_objectpropertiesframe.h"
|
||||
#include "eventpropertiesframe.h"
|
||||
#include "ui_eventpropertiesframe.h"
|
||||
#include "bordermetatilespixmapitem.h"
|
||||
#include "currentselectedmetatilespixmapitem.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFileDialog>
|
||||
|
@ -30,25 +32,55 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
{
|
||||
QCoreApplication::setOrganizationName("pret");
|
||||
QCoreApplication::setApplicationName("porymap");
|
||||
QApplication::setApplicationDisplayName("porymap");
|
||||
QApplication::setWindowIcon(QIcon(":/icons/porymap-icon-1.ico"));
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->newEventToolButton->initButton();
|
||||
connect(ui->newEventToolButton, SIGNAL(newEventAdded(QString)), this, SLOT(addNewEvent(QString)));
|
||||
|
||||
new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Z), this, SLOT(redo()));
|
||||
|
||||
editor = new Editor(ui);
|
||||
connect(editor, SIGNAL(objectsChanged()), this, SLOT(updateSelectedObjects()));
|
||||
connect(editor, SIGNAL(selectedObjectsChanged()), this, SLOT(updateSelectedObjects()));
|
||||
connect(editor, SIGNAL(loadMapRequested(QString, QString)), this, SLOT(onLoadMapRequested(QString, QString)));
|
||||
connect(editor, SIGNAL(tilesetChanged(QString)), this, SLOT(onTilesetChanged(QString)));
|
||||
connect(editor, SIGNAL(warpEventDoubleClicked(QString,QString)), this, SLOT(openWarpMap(QString,QString)));
|
||||
connect(editor, SIGNAL(currentMetatilesSelectionChanged()), this, SLOT(currentMetatilesSelectionChanged()));
|
||||
this->initExtraSignals();
|
||||
this->initExtraShortcuts();
|
||||
this->initEditor();
|
||||
this->openRecentProject();
|
||||
|
||||
on_toolButton_Paint_clicked();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::initExtraShortcuts() {
|
||||
new QShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Z), this, SLOT(redo()));
|
||||
new QShortcut(QKeySequence("Ctrl+0"), this, SLOT(resetMapViewScale()));
|
||||
ui->actionZoom_In->setShortcuts({QKeySequence("Ctrl++"), QKeySequence("Ctrl+=")});
|
||||
}
|
||||
|
||||
void MainWindow::initExtraSignals() {
|
||||
connect(ui->newEventToolButton, SIGNAL(newEventAdded(QString)), this, SLOT(addNewEvent(QString)));
|
||||
}
|
||||
|
||||
void MainWindow::initEditor() {
|
||||
this->editor = new Editor(ui);
|
||||
connect(this->editor, SIGNAL(objectsChanged()), this, SLOT(updateSelectedObjects()));
|
||||
connect(this->editor, SIGNAL(selectedObjectsChanged()), this, SLOT(updateSelectedObjects()));
|
||||
connect(this->editor, SIGNAL(loadMapRequested(QString, QString)), this, SLOT(onLoadMapRequested(QString, QString)));
|
||||
connect(this->editor, SIGNAL(tilesetChanged(QString)), this, SLOT(onTilesetChanged(QString)));
|
||||
connect(this->editor, SIGNAL(warpEventDoubleClicked(QString,QString)), this, SLOT(openWarpMap(QString,QString)));
|
||||
connect(this->editor, SIGNAL(currentMetatilesSelectionChanged()), this, SLOT(currentMetatilesSelectionChanged()));
|
||||
connect(this->editor, &Editor::wheelZoom, this, &MainWindow::scaleMapView);
|
||||
|
||||
this->loadUserSettings();
|
||||
}
|
||||
|
||||
void MainWindow::loadUserSettings() {
|
||||
QSettings settings;
|
||||
|
||||
bool betterCursors = settings.contains("cursor_mode") && settings.value("cursor_mode") != "0";
|
||||
ui->actionBetter_Cursors->setChecked(betterCursors);
|
||||
this->editor->settings->betterCursors = betterCursors;
|
||||
}
|
||||
|
||||
void MainWindow::openRecentProject() {
|
||||
QSettings settings;
|
||||
QString key = "recent_projects";
|
||||
if (settings.contains(key)) {
|
||||
|
@ -58,19 +90,6 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
openProject(default_dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.contains("cursor_mode") && settings.value("cursor_mode") == "0") {
|
||||
ui->actionBetter_Cursors->setChecked(false);
|
||||
}
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::setStatusBarMessage(QString message, int timeout/* = 0*/) {
|
||||
statusBar()->showMessage(message, timeout);
|
||||
}
|
||||
|
||||
void MainWindow::openProject(QString dir) {
|
||||
|
@ -78,7 +97,7 @@ void MainWindow::openProject(QString dir) {
|
|||
return;
|
||||
}
|
||||
|
||||
setStatusBarMessage(QString("Opening project %1").arg(dir));
|
||||
this->statusBar()->showMessage(QString("Opening project %1").arg(dir));
|
||||
|
||||
bool already_open = (
|
||||
(editor && editor != nullptr)
|
||||
|
@ -88,17 +107,17 @@ void MainWindow::openProject(QString dir) {
|
|||
if (!already_open) {
|
||||
editor->project = new Project;
|
||||
editor->project->root = dir;
|
||||
setWindowTitle(editor->project->getProjectTitle() + " - porymap");
|
||||
setWindowTitle(editor->project->getProjectTitle());
|
||||
loadDataStructures();
|
||||
populateMapList();
|
||||
setMap(getDefaultMap());
|
||||
setMap(getDefaultMap(), true);
|
||||
} else {
|
||||
setWindowTitle(editor->project->getProjectTitle() + " - porymap");
|
||||
setWindowTitle(editor->project->getProjectTitle());
|
||||
loadDataStructures();
|
||||
populateMapList();
|
||||
}
|
||||
|
||||
setStatusBarMessage(QString("Opened project %1").arg(dir));
|
||||
this->statusBar()->showMessage(QString("Opened project %1").arg(dir));
|
||||
}
|
||||
|
||||
QString MainWindow::getDefaultMap() {
|
||||
|
@ -156,7 +175,7 @@ void MainWindow::on_action_Open_Project_triggered()
|
|||
}
|
||||
}
|
||||
|
||||
void MainWindow::setMap(QString map_name) {
|
||||
void MainWindow::setMap(QString map_name, bool scrollTreeView) {
|
||||
qDebug() << QString("setMap(%1)").arg(map_name);
|
||||
if (map_name.isNull()) {
|
||||
return;
|
||||
|
@ -165,14 +184,19 @@ void MainWindow::setMap(QString map_name) {
|
|||
redrawMapScene();
|
||||
displayMapProperties();
|
||||
|
||||
setWindowTitle(map_name + " - " + editor->project->getProjectTitle() + " - porymap");
|
||||
if (scrollTreeView) {
|
||||
ui->mapList->setCurrentIndex(mapListIndexes.value(map_name));
|
||||
ui->mapList->scrollTo(ui->mapList->currentIndex(), QAbstractItemView::PositionAtCenter);
|
||||
}
|
||||
|
||||
setWindowTitle(map_name + " - " + editor->project->getProjectTitle());
|
||||
|
||||
connect(editor->map, SIGNAL(mapChanged(Map*)), this, SLOT(onMapChanged(Map *)));
|
||||
connect(editor->map, SIGNAL(mapNeedsRedrawing()), this, SLOT(onMapNeedsRedrawing()));
|
||||
connect(editor->map, SIGNAL(statusBarMessage(QString)), this, SLOT(setStatusBarMessage(QString)));
|
||||
|
||||
setRecentMap(map_name);
|
||||
updateMapList();
|
||||
updateTilesetEditor();
|
||||
}
|
||||
|
||||
void MainWindow::redrawMapScene()
|
||||
|
@ -180,22 +204,28 @@ void MainWindow::redrawMapScene()
|
|||
editor->displayMap();
|
||||
on_tabWidget_currentChanged(ui->tabWidget->currentIndex());
|
||||
|
||||
double base = editor->scale_base;
|
||||
double exp = editor->scale_exp;
|
||||
|
||||
int width = static_cast<int>(ceil((editor->scene->width()) * pow(base,exp))) + 2;
|
||||
int height = static_cast<int>(ceil((editor->scene->height()) * pow(base,exp))) + 2;
|
||||
|
||||
ui->graphicsView_Map->setScene(editor->scene);
|
||||
ui->graphicsView_Map->setSceneRect(editor->scene->sceneRect());
|
||||
ui->graphicsView_Map->setFixedSize(static_cast<int>(editor->scene->width()) + 2, static_cast<int>(editor->scene->height()) + 2);
|
||||
ui->graphicsView_Map->setFixedSize(width, height);
|
||||
|
||||
ui->graphicsView_Objects_Map->setScene(editor->scene);
|
||||
ui->graphicsView_Objects_Map->setSceneRect(editor->scene->sceneRect());
|
||||
ui->graphicsView_Objects_Map->setFixedSize(static_cast<int>(editor->scene->width()) + 2, static_cast<int>(editor->scene->height()) + 2);
|
||||
ui->graphicsView_Objects_Map->setFixedSize(width, height);
|
||||
ui->graphicsView_Objects_Map->editor = editor;
|
||||
|
||||
ui->graphicsView_Connections->setScene(editor->scene);
|
||||
ui->graphicsView_Connections->setSceneRect(editor->scene->sceneRect());
|
||||
ui->graphicsView_Connections->setFixedSize(static_cast<int>(editor->scene->width()) + 2, static_cast<int>(editor->scene->height()) + 2);
|
||||
ui->graphicsView_Connections->setFixedSize(width, height);
|
||||
|
||||
ui->graphicsView_Metatiles->setScene(editor->scene_metatiles);
|
||||
//ui->graphicsView_Metatiles->setSceneRect(editor->scene_metatiles->sceneRect());
|
||||
ui->graphicsView_Metatiles->setFixedSize(editor->metatiles_item->pixmap().width() + 2, editor->metatiles_item->pixmap().height() + 2);
|
||||
ui->graphicsView_Metatiles->setFixedSize(editor->metatile_selector_item->pixmap().width() + 2, editor->metatile_selector_item->pixmap().height() + 2);
|
||||
|
||||
ui->graphicsView_BorderMetatile->setScene(editor->scene_selected_border_metatiles);
|
||||
ui->graphicsView_BorderMetatile->setFixedSize(editor->selected_border_metatiles_item->pixmap().width() + 2, editor->selected_border_metatiles_item->pixmap().height() + 2);
|
||||
|
@ -205,7 +235,7 @@ void MainWindow::redrawMapScene()
|
|||
|
||||
ui->graphicsView_Collision->setScene(editor->scene_collision_metatiles);
|
||||
//ui->graphicsView_Collision->setSceneRect(editor->scene_collision_metatiles->sceneRect());
|
||||
ui->graphicsView_Collision->setFixedSize(editor->collision_metatiles_item->pixmap().width() + 2, editor->collision_metatiles_item->pixmap().height() + 2);
|
||||
ui->graphicsView_Collision->setFixedSize(editor->movement_permissions_selector_item->pixmap().width() + 2, editor->movement_permissions_selector_item->pixmap().height() + 2);
|
||||
}
|
||||
|
||||
void MainWindow::openWarpMap(QString map_name, QString warp_num) {
|
||||
|
@ -224,7 +254,7 @@ void MainWindow::openWarpMap(QString map_name, QString warp_num) {
|
|||
}
|
||||
|
||||
// Open the destination map, and select the target warp event.
|
||||
setMap(map_name);
|
||||
setMap(map_name, true);
|
||||
QList<Event*> warp_events = editor->map->events["warp_event_group"];
|
||||
if (warp_events.length() > warpNum) {
|
||||
Event *warp_event = warp_events.at(warpNum);
|
||||
|
@ -377,6 +407,7 @@ void MainWindow::loadDataStructures() {
|
|||
project->readSecretBaseIds();
|
||||
project->readBgEventFacingDirections();
|
||||
project->readMapsWithConnections();
|
||||
project->readMetatileBehaviors();
|
||||
project->readTilesetProperties();
|
||||
}
|
||||
|
||||
|
@ -426,6 +457,7 @@ void MainWindow::populateMapList() {
|
|||
QString map_name = names.value(j);
|
||||
QStandardItem *map = createMapItem(map_name, i, j);
|
||||
group->appendRow(map);
|
||||
mapListIndexes.insert(map_name, map->index());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -488,6 +520,7 @@ void MainWindow::onAddNewMapToGroupClick(QAction* triggeredAction)
|
|||
int numMapsInGroup = groupItem->rowCount();
|
||||
QStandardItem *newMapItem = createMapItem(newMapName, groupNum, numMapsInGroup);
|
||||
groupItem->appendRow(newMapItem);
|
||||
mapListIndexes.insert(newMapName, newMapItem->index());
|
||||
|
||||
setMap(newMapName);
|
||||
}
|
||||
|
@ -497,6 +530,12 @@ void MainWindow::onTilesetChanged(QString mapName)
|
|||
setMap(mapName);
|
||||
}
|
||||
|
||||
void MainWindow::updateTilesetEditor() {
|
||||
if (this->tilesetEditor) {
|
||||
this->tilesetEditor->setTilesets(editor->ui->comboBox_PrimaryTileset->currentText(), editor->ui->comboBox_SecondaryTileset->currentText());
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::currentMetatilesSelectionChanged()
|
||||
{
|
||||
ui->graphicsView_currentMetatileSelection->setFixedSize(editor->scene_current_metatile_selection_item->pixmap().width() + 2, editor->scene_current_metatile_selection_item->pixmap().height() + 2);
|
||||
|
@ -506,7 +545,7 @@ void MainWindow::currentMetatilesSelectionChanged()
|
|||
void MainWindow::on_mapList_activated(const QModelIndex &index)
|
||||
{
|
||||
QVariant data = index.data(Qt::UserRole);
|
||||
if (!data.isNull()) {
|
||||
if (index.data(MapListUserRoles::TypeRole) == "map_name" && !data.isNull()) {
|
||||
setMap(data.toString());
|
||||
}
|
||||
}
|
||||
|
@ -617,6 +656,7 @@ void MainWindow::on_actionZoom_Out_triggered() {
|
|||
void MainWindow::on_actionBetter_Cursors_triggered() {
|
||||
QSettings settings;
|
||||
settings.setValue("cursor_mode", QString::number(ui->actionBetter_Cursors->isChecked()));
|
||||
this->editor->settings->betterCursors = ui->actionBetter_Cursors->isChecked();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionPencil_triggered()
|
||||
|
@ -650,19 +690,33 @@ void MainWindow::on_actionMap_Shift_triggered()
|
|||
}
|
||||
|
||||
void MainWindow::scaleMapView(int s) {
|
||||
editor->map->scale_exp += s;
|
||||
if ((editor->scale_exp + s) <= 5 && (editor->scale_exp + s) >= -2) // sane limits
|
||||
{
|
||||
if (s == 0)
|
||||
{
|
||||
s = -editor->scale_exp;
|
||||
}
|
||||
|
||||
double base = editor->map->scale_base;
|
||||
double exp = editor->map->scale_exp;
|
||||
editor->scale_exp += s;
|
||||
|
||||
double base = editor->scale_base;
|
||||
double exp = editor->scale_exp;
|
||||
double sfactor = pow(base,s);
|
||||
|
||||
ui->graphicsView_Map->scale(sfactor,sfactor);
|
||||
ui->graphicsView_Objects_Map->scale(sfactor,sfactor);
|
||||
ui->graphicsView_Connections->scale(sfactor,sfactor);
|
||||
|
||||
int width = static_cast<int>((editor->scene->width() + 2) * pow(base,exp));
|
||||
int height = static_cast<int>((editor->scene->height() + 2) * pow(base,exp));
|
||||
int width = static_cast<int>(ceil((editor->scene->width()) * pow(base,exp))) + 2;
|
||||
int height = static_cast<int>(ceil((editor->scene->height()) * pow(base,exp))) + 2;
|
||||
ui->graphicsView_Map->setFixedSize(width, height);
|
||||
ui->graphicsView_Objects_Map->setFixedSize(width, height);
|
||||
ui->graphicsView_Connections->setFixedSize(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::resetMapViewScale() {
|
||||
scaleMapView(0);
|
||||
}
|
||||
|
||||
void MainWindow::addNewEvent(QString event_type)
|
||||
|
@ -695,10 +749,10 @@ void MainWindow::updateSelectedObjects() {
|
|||
|
||||
QMap<QString, int> event_obj_gfx_constants = editor->project->getEventObjGfxConstants();
|
||||
|
||||
QList<ObjectPropertiesFrame *> frames;
|
||||
QList<EventPropertiesFrame *> frames;
|
||||
|
||||
for (DraggablePixmapItem *item : *events) {
|
||||
ObjectPropertiesFrame *frame = new ObjectPropertiesFrame;
|
||||
EventPropertiesFrame *frame = new EventPropertiesFrame;
|
||||
// frame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
|
||||
QSpinBox *x = frame->ui->spinBox_x;
|
||||
|
@ -925,7 +979,7 @@ void MainWindow::updateSelectedObjects() {
|
|||
ui->scrollArea_4->setWidgetResizable(true);
|
||||
ui->scrollArea_4->setWidget(target);
|
||||
|
||||
for (ObjectPropertiesFrame *frame : frames) {
|
||||
for (EventPropertiesFrame *frame : frames) {
|
||||
layout->addWidget(frame);
|
||||
}
|
||||
|
||||
|
@ -965,7 +1019,7 @@ void MainWindow::on_toolButton_Open_Scripts_clicked()
|
|||
void MainWindow::on_toolButton_Paint_clicked()
|
||||
{
|
||||
editor->map_edit_mode = "paint";
|
||||
editor->cursor = QCursor(QPixmap(":/icons/pencil_cursor.ico"), 10, 10);
|
||||
editor->settings->mapCursor = QCursor(QPixmap(":/icons/pencil_cursor.ico"), 10, 10);
|
||||
|
||||
ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
|
@ -977,7 +1031,7 @@ void MainWindow::on_toolButton_Paint_clicked()
|
|||
void MainWindow::on_toolButton_Select_clicked()
|
||||
{
|
||||
editor->map_edit_mode = "select";
|
||||
editor->cursor = QCursor(QPixmap(":/icons/cursor.ico"), 0, 0);
|
||||
editor->settings->mapCursor = QCursor(QPixmap(":/icons/cursor.ico"), 0, 0);
|
||||
|
||||
ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
|
@ -989,7 +1043,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_cursor.ico"), 10, 10);
|
||||
editor->settings->mapCursor = QCursor(QPixmap(":/icons/fill_color_cursor.ico"), 10, 10);
|
||||
|
||||
ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
|
@ -1001,7 +1055,7 @@ void MainWindow::on_toolButton_Fill_clicked()
|
|||
void MainWindow::on_toolButton_Dropper_clicked()
|
||||
{
|
||||
editor->map_edit_mode = "pick";
|
||||
editor->cursor = QCursor(QPixmap(":/icons/pipette_cursor.ico"), 10, 10);
|
||||
editor->settings->mapCursor = QCursor(QPixmap(":/icons/pipette_cursor.ico"), 10, 10);
|
||||
|
||||
ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
|
@ -1013,7 +1067,7 @@ void MainWindow::on_toolButton_Dropper_clicked()
|
|||
void MainWindow::on_toolButton_Move_clicked()
|
||||
{
|
||||
editor->map_edit_mode = "move";
|
||||
editor->cursor = QCursor(QPixmap(":/icons/move.ico"), 7, 7);
|
||||
editor->settings->mapCursor = QCursor(QPixmap(":/icons/move.ico"), 7, 7);
|
||||
|
||||
ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
|
@ -1025,7 +1079,7 @@ 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);
|
||||
editor->settings->mapCursor = QCursor(QPixmap(":/icons/shift_cursor.ico"), 10, 10);
|
||||
|
||||
ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
ui->scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
|
@ -1044,7 +1098,7 @@ void MainWindow::checkToolButtons() {
|
|||
}
|
||||
|
||||
void MainWindow::onLoadMapRequested(QString mapName, QString fromMapName) {
|
||||
setMap(mapName);
|
||||
setMap(mapName, true);
|
||||
editor->setSelectedConnectionFromMap(fromMapName);
|
||||
}
|
||||
|
||||
|
@ -1057,6 +1111,11 @@ void MainWindow::onMapNeedsRedrawing() {
|
|||
redrawMapScene();
|
||||
}
|
||||
|
||||
void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryTilesetLabel) {
|
||||
this->editor->updatePrimaryTileset(primaryTilesetLabel, true);
|
||||
this->editor->updateSecondaryTileset(secondaryTilesetLabel, true);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Export_Map_Image_triggered()
|
||||
{
|
||||
QString defaultFilepath = QString("%1/%2.png").arg(editor->project->root).arg(editor->map->name);
|
||||
|
@ -1173,7 +1232,7 @@ void MainWindow::on_pushButton_clicked()
|
|||
|
||||
void MainWindow::on_checkBox_smartPaths_stateChanged(int selected)
|
||||
{
|
||||
editor->map->smart_paths_enabled = selected == Qt::Checked;
|
||||
editor->settings->smartPathsEnabled = selected == Qt::Checked;
|
||||
}
|
||||
|
||||
void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected)
|
||||
|
@ -1181,3 +1240,27 @@ void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected)
|
|||
bool visible = selected != 0;
|
||||
editor->toggleBorderVisibility(visible);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionTileset_Editor_triggered()
|
||||
{
|
||||
if (!this->tilesetEditor) {
|
||||
this->tilesetEditor = new TilesetEditor(this->editor->project, this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label, this);
|
||||
connect(this->tilesetEditor, SIGNAL(tilesetsSaved(QString, QString)), this, SLOT(onTilesetsSaved(QString, QString)));
|
||||
connect(this->tilesetEditor, SIGNAL(closed()), this, SLOT(onTilesetEditorClosed()));
|
||||
}
|
||||
|
||||
if (!this->tilesetEditor->isVisible()) {
|
||||
this->tilesetEditor->show();
|
||||
} else if (this->tilesetEditor->isMinimized()) {
|
||||
this->tilesetEditor->showNormal();
|
||||
} else {
|
||||
this->tilesetEditor->activateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onTilesetEditorClosed() {
|
||||
if (this->tilesetEditor) {
|
||||
delete this->tilesetEditor;
|
||||
this->tilesetEditor = nullptr;
|
||||
}
|
||||
}
|
254
project.cpp → src/project.cpp
Executable file → Normal file
|
@ -1,5 +1,7 @@
|
|||
#include "parseutil.h"
|
||||
#include "project.h"
|
||||
#include "history.h"
|
||||
#include "historyitem.h"
|
||||
#include "parseutil.h"
|
||||
#include "tile.h"
|
||||
#include "tileset.h"
|
||||
#include "event.h"
|
||||
|
@ -67,7 +69,7 @@ Map* Project::loadMap(QString map_name) {
|
|||
readMapEvents(map);
|
||||
loadMapConnections(map);
|
||||
map->commit();
|
||||
map->history.save();
|
||||
map->metatileHistory.save();
|
||||
|
||||
map_cache->insert(map_name, map);
|
||||
return map;
|
||||
|
@ -94,7 +96,7 @@ void Project::loadMapConnections(Map *map) {
|
|||
for (QStringList command : *connections) {
|
||||
QString macro = command.value(0);
|
||||
if (macro == "connection") {
|
||||
Connection *connection = new Connection;
|
||||
MapConnection *connection = new MapConnection;
|
||||
connection->direction = command.value(1);
|
||||
connection->offset = command.value(2);
|
||||
QString mapConstant = command.value(3);
|
||||
|
@ -238,7 +240,7 @@ void Project::saveMapConnections(Map *map) {
|
|||
QString connectionsListLabel = QString("%1_MapConnectionsList").arg(map->name);
|
||||
int numValidConnections = 0;
|
||||
text += QString("%1::\n").arg(connectionsListLabel);
|
||||
for (Connection* connection : map->connections) {
|
||||
for (MapConnection* connection : map->connections) {
|
||||
if (mapNamesToMapConstants->contains(connection->map_name)) {
|
||||
text += QString("\tconnection %1, %2, %3\n")
|
||||
.arg(connection->direction)
|
||||
|
@ -532,8 +534,8 @@ void Project::saveHealLocationStruct(Map *map) {
|
|||
|
||||
// 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();
|
||||
for (Event *healEvent : map->events["heal_event_group"]) {
|
||||
HealLocation hl = HealLocation::fromEvent(healEvent);
|
||||
flyableMaps[hl.index - 1] = hl;
|
||||
}
|
||||
}
|
||||
|
@ -574,6 +576,77 @@ void Project::saveHealLocationStruct(Map *map) {
|
|||
saveTextFile(root + "/include/constants/heal_locations.h", constants_text);
|
||||
}
|
||||
|
||||
void Project::saveTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
saveTilesetMetatileAttributes(primaryTileset);
|
||||
saveTilesetMetatileAttributes(secondaryTileset);
|
||||
saveTilesetMetatiles(primaryTileset);
|
||||
saveTilesetMetatiles(secondaryTileset);
|
||||
saveTilesetTilesImage(primaryTileset);
|
||||
saveTilesetTilesImage(secondaryTileset);
|
||||
saveTilesetPalettes(primaryTileset, true);
|
||||
saveTilesetPalettes(secondaryTileset, false);
|
||||
}
|
||||
|
||||
void Project::saveTilesetMetatileAttributes(Tileset *tileset) {
|
||||
QFile attrs_file(tileset->metatile_attrs_path);
|
||||
if (attrs_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
QByteArray data;
|
||||
for (Metatile *metatile : *tileset->metatiles) {
|
||||
data.append(static_cast<char>(metatile->behavior));
|
||||
data.append(static_cast<char>((metatile->layerType << 4) & 0xF0));
|
||||
}
|
||||
attrs_file.write(data);
|
||||
} else {
|
||||
qDebug() << QString("Could not save tileset metatile attributes file '%1'").arg(tileset->metatile_attrs_path);
|
||||
}
|
||||
}
|
||||
|
||||
void Project::saveTilesetMetatiles(Tileset *tileset) {
|
||||
QFile metatiles_file(tileset->metatiles_path);
|
||||
if (metatiles_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
QByteArray data;
|
||||
for (Metatile *metatile : *tileset->metatiles) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Tile tile = metatile->tiles->at(i);
|
||||
uint16_t value = static_cast<uint16_t>((tile.tile & 0x3ff)
|
||||
| ((tile.xflip & 1) << 10)
|
||||
| ((tile.yflip & 1) << 11)
|
||||
| ((tile.palette & 0xf) << 12));
|
||||
data.append(static_cast<char>(value & 0xff));
|
||||
data.append(static_cast<char>((value >> 8) & 0xff));
|
||||
}
|
||||
}
|
||||
metatiles_file.write(data);
|
||||
} else {
|
||||
tileset->metatiles = new QList<Metatile*>;
|
||||
qDebug() << QString("Could not open tileset metatiles file '%1'").arg(tileset->metatiles_path);
|
||||
}
|
||||
}
|
||||
|
||||
void Project::saveTilesetTilesImage(Tileset *tileset) {
|
||||
tileset->tilesImage.save(tileset->tilesImagePath);
|
||||
}
|
||||
|
||||
void Project::saveTilesetPalettes(Tileset *tileset, bool primary) {
|
||||
int startPaletteId = primary ? 0 : Project::getNumPalettesPrimary();
|
||||
int endPaletteId = primary ? Project::getNumPalettesPrimary() : Project::getNumPalettesTotal();
|
||||
for (int i = startPaletteId; i < endPaletteId; i++) {
|
||||
QString filepath = tileset->palettePaths.at(i);
|
||||
QString content = "JASC-PAL\r\n";
|
||||
content += "0100\r\n";
|
||||
content += "16\r\n";
|
||||
for (int j = 0; j < 16; j++) {
|
||||
QRgb color = tileset->palettes->at(i).at(j);
|
||||
content += QString("%1 %2 %3\r\n")
|
||||
.arg(qRed(color))
|
||||
.arg(qGreen(color))
|
||||
.arg(qBlue(color));
|
||||
}
|
||||
|
||||
saveTextFile(filepath, content);
|
||||
}
|
||||
}
|
||||
|
||||
void Project::loadMapTilesets(Map* map) {
|
||||
if (map->layout->has_unsaved_changes) {
|
||||
return;
|
||||
|
@ -583,12 +656,14 @@ void Project::loadMapTilesets(Map* map) {
|
|||
map->layout->tileset_secondary = getTileset(map->layout->tileset_secondary_label);
|
||||
}
|
||||
|
||||
Tileset* Project::loadTileset(QString label) {
|
||||
Tileset* Project::loadTileset(QString label, Tileset *tileset) {
|
||||
ParseUtil *parser = new ParseUtil;
|
||||
|
||||
QString headers_text = readTextFile(root + "/data/tilesets/headers.inc");
|
||||
QStringList *values = getLabelValues(parser->parseAsm(headers_text), label);
|
||||
Tileset *tileset = new Tileset;
|
||||
if (tileset == nullptr) {
|
||||
tileset = new Tileset;
|
||||
}
|
||||
tileset->name = label;
|
||||
tileset->is_compressed = values->value(0);
|
||||
tileset->is_secondary = values->value(1);
|
||||
|
@ -648,7 +723,7 @@ void Project::saveMapBorder(Map *map) {
|
|||
void Project::saveBlockdata(Map* map) {
|
||||
QString path = QString("%1/%2").arg(root).arg(map->layout->blockdata_path);
|
||||
writeBlockdata(path, map->layout->blockdata);
|
||||
map->history.save();
|
||||
map->metatileHistory.save();
|
||||
}
|
||||
|
||||
void Project::writeBlockdata(QString path, Blockdata *blockdata) {
|
||||
|
@ -748,7 +823,8 @@ void Project::loadTilesetAssets(Tileset* tileset) {
|
|||
if (tileset->name.isNull()) {
|
||||
return;
|
||||
}
|
||||
QString dir_path = root + "/data/tilesets/" + category + "/" + tileset->name.replace("gTileset_", "").toLower();
|
||||
QString tilesetName = tileset->name;
|
||||
QString dir_path = root + "/data/tilesets/" + category + "/" + tilesetName.replace("gTileset_", "").toLower();
|
||||
|
||||
QString graphics_text = readTextFile(root + "/data/tilesets/graphics.inc");
|
||||
QList<QStringList> *graphics = parser->parseAsm(graphics_text);
|
||||
|
@ -765,53 +841,94 @@ void Project::loadTilesetAssets(Tileset* tileset) {
|
|||
}
|
||||
}
|
||||
|
||||
QStringList *palette_paths = new QStringList;
|
||||
if (!palettes_values->isEmpty()) {
|
||||
for (int i = 0; i < palettes_values->length(); i++) {
|
||||
QString value = palettes_values->value(i);
|
||||
palette_paths->append(root + "/" + value.section('"', 1, 1));
|
||||
tileset->palettePaths.append(this->fixPalettePath(root + "/" + value.section('"', 1, 1)));
|
||||
}
|
||||
} else {
|
||||
QString palettes_dir_path = dir_path + "/palettes";
|
||||
for (int i = 0; i < 16; i++) {
|
||||
palette_paths->append(palettes_dir_path + "/" + QString("%1").arg(i, 2, 10, QLatin1Char('0')) + ".gbapal");
|
||||
tileset->palettePaths.append(palettes_dir_path + "/" + QString("%1").arg(i, 2, 10, QLatin1Char('0')) + ".pal");
|
||||
}
|
||||
}
|
||||
|
||||
QString metatiles_path;
|
||||
QString metatile_attrs_path;
|
||||
QString metatiles_text = readTextFile(root + "/data/tilesets/metatiles.inc");
|
||||
QList<QStringList> *metatiles_macros = parser->parseAsm(metatiles_text);
|
||||
QStringList *metatiles_values = getLabelValues(metatiles_macros, tileset->metatiles_label);
|
||||
if (!metatiles_values->isEmpty()) {
|
||||
metatiles_path = root + "/" + metatiles_values->value(0).section('"', 1, 1);
|
||||
tileset->metatiles_path = root + "/" + metatiles_values->value(0).section('"', 1, 1);
|
||||
} else {
|
||||
metatiles_path = dir_path + "/metatiles.bin";
|
||||
tileset->metatiles_path = dir_path + "/metatiles.bin";
|
||||
}
|
||||
QStringList *metatile_attrs_values = getLabelValues(metatiles_macros, tileset->metatile_attrs_label);
|
||||
if (!metatile_attrs_values->isEmpty()) {
|
||||
metatile_attrs_path = root + "/" + metatile_attrs_values->value(0).section('"', 1, 1);
|
||||
tileset->metatile_attrs_path = root + "/" + metatile_attrs_values->value(0).section('"', 1, 1);
|
||||
} else {
|
||||
metatile_attrs_path = dir_path + "/metatile_attributes.bin";
|
||||
tileset->metatile_attrs_path = dir_path + "/metatile_attributes.bin";
|
||||
}
|
||||
|
||||
// tiles
|
||||
tiles_path = fixGraphicPath(tiles_path);
|
||||
QImage *image = new QImage(tiles_path);
|
||||
//image->setColor(0, qRgb(0xff, 0, 0)); // debug
|
||||
tileset->tilesImagePath = tiles_path;
|
||||
QImage image = QImage(tileset->tilesImagePath);
|
||||
this->loadTilesetTiles(tileset, image);
|
||||
this->loadTilesetMetatiles(tileset);
|
||||
|
||||
// palettes
|
||||
QList<QList<QRgb>> *palettes = new QList<QList<QRgb>>;
|
||||
for (int i = 0; i < tileset->palettePaths.length(); i++) {
|
||||
QList<QRgb> palette;
|
||||
QString path = tileset->palettePaths.value(i);
|
||||
QString text = readTextFile(path);
|
||||
if (!text.isNull()) {
|
||||
QStringList lines = text.split(QRegExp("[\r\n]"),QString::SkipEmptyParts);
|
||||
if (lines.length() == 19 && lines[0] == "JASC-PAL" && lines[1] == "0100" && lines[2] == "16") {
|
||||
for (int j = 0; j < 16; j++) {
|
||||
QStringList rgb = lines[j + 3].split(QRegExp(" "), QString::SkipEmptyParts);
|
||||
if (rgb.length() != 3) {
|
||||
qDebug() << QString("Invalid tileset palette RGB value: '%1'").arg(lines[j + 3]);
|
||||
palette.append(qRgb((j - 3) * 16, (j - 3) * 16, (j - 3) * 16));
|
||||
} else {
|
||||
int red = rgb[0].toInt();
|
||||
int green = rgb[1].toInt();
|
||||
int blue = rgb[2].toInt();
|
||||
QRgb color = qRgb(red, green, blue);
|
||||
palette.append(color);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qDebug() << QString("Invalid JASC-PAL palette file for tileset.");
|
||||
for (int j = 0; j < 16; j++) {
|
||||
palette.append(qRgb(j * 16, j * 16, j * 16));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int j = 0; j < 16; j++) {
|
||||
palette.append(qRgb(j * 16, j * 16, j * 16));
|
||||
}
|
||||
qDebug() << QString("Could not open palette path '%1'").arg(path);
|
||||
}
|
||||
|
||||
palettes->append(palette);
|
||||
}
|
||||
tileset->palettes = palettes;
|
||||
}
|
||||
|
||||
void Project::loadTilesetTiles(Tileset *tileset, QImage image) {
|
||||
QList<QImage> *tiles = new QList<QImage>;
|
||||
int w = 8;
|
||||
int h = 8;
|
||||
for (int y = 0; y < image->height(); y += h)
|
||||
for (int x = 0; x < image->width(); x += w) {
|
||||
QImage tile = image->copy(x, y, w, h);
|
||||
for (int y = 0; y < image.height(); y += h)
|
||||
for (int x = 0; x < image.width(); x += w) {
|
||||
QImage tile = image.copy(x, y, w, h);
|
||||
tiles->append(tile);
|
||||
}
|
||||
tileset->tilesImage = image;
|
||||
tileset->tiles = tiles;
|
||||
}
|
||||
|
||||
// metatiles
|
||||
QFile metatiles_file(metatiles_path);
|
||||
void Project::loadTilesetMetatiles(Tileset* tileset) {
|
||||
QFile metatiles_file(tileset->metatiles_path);
|
||||
if (metatiles_file.open(QIODevice::ReadOnly)) {
|
||||
QByteArray data = metatiles_file.readAll();
|
||||
int num_metatiles = data.length() / 16;
|
||||
|
@ -835,11 +952,10 @@ void Project::loadTilesetAssets(Tileset* tileset) {
|
|||
tileset->metatiles = metatiles;
|
||||
} else {
|
||||
tileset->metatiles = new QList<Metatile*>;
|
||||
qDebug() << QString("Could not open '%1'").arg(metatiles_path);
|
||||
qDebug() << QString("Could not open tileset metatiles file '%1'").arg(tileset->metatiles_path);
|
||||
}
|
||||
|
||||
QFile attrs_file(metatile_attrs_path);
|
||||
//qDebug() << metatile_attrs_path;
|
||||
QFile attrs_file(tileset->metatile_attrs_path);
|
||||
if (attrs_file.open(QIODevice::ReadOnly)) {
|
||||
QByteArray data = attrs_file.readAll();
|
||||
int num_metatiles = tileset->metatiles->count();
|
||||
|
@ -849,46 +965,14 @@ void Project::loadTilesetAssets(Tileset* tileset) {
|
|||
if (num_metatiles > num_metatileAttrs)
|
||||
num_metatiles = num_metatileAttrs;
|
||||
}
|
||||
for (int i = 0; i < num_metatiles; i++) {
|
||||
uint16_t word = data[i*2] & 0xff;
|
||||
word += (data[i*2 + 1] & 0xff) << 8;
|
||||
tileset->metatiles->value(i)->attr = word;
|
||||
for (int i = 0; i < num_metatileAttrs; i++) {
|
||||
int value = (static_cast<unsigned char>(data.at(i * 2 + 1)) << 8) | static_cast<unsigned char>(data.at(i * 2));
|
||||
tileset->metatiles->at(i)->behavior = value & 0xFF;
|
||||
tileset->metatiles->at(i)->layerType = (value & 0xF000) >> 12;
|
||||
}
|
||||
} else {
|
||||
qDebug() << QString("Could not open '%1'").arg(metatile_attrs_path);
|
||||
qDebug() << QString("Could not open tileset metatile attributes file '%1'").arg(tileset->metatile_attrs_path);
|
||||
}
|
||||
|
||||
// palettes
|
||||
QList<QList<QRgb>> *palettes = new QList<QList<QRgb>>;
|
||||
for (int i = 0; i < palette_paths->length(); i++) {
|
||||
QString path = palette_paths->value(i);
|
||||
// the palettes are not compressed. this should never happen. it's only a precaution.
|
||||
path = path.replace(QRegExp("\\.lz$"), "");
|
||||
// TODO default to .pal (JASC-PAL)
|
||||
// just use .gbapal for now
|
||||
QFile file(path);
|
||||
QList<QRgb> palette;
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
QByteArray data = file.readAll();
|
||||
for (int j = 0; j < 16; j++) {
|
||||
uint16_t word = data[j*2] & 0xff;
|
||||
word += (data[j*2 + 1] & 0xff) << 8;
|
||||
int red = word & 0x1f;
|
||||
int green = (word >> 5) & 0x1f;
|
||||
int blue = (word >> 10) & 0x1f;
|
||||
QRgb color = qRgb(red * 8, green * 8, blue * 8);
|
||||
palette.append(color);
|
||||
}
|
||||
} else {
|
||||
for (int j = 0; j < 16; j++) {
|
||||
palette.append(qRgb(j * 16, j * 16, j * 16));
|
||||
}
|
||||
qDebug() << QString("Could not open palette path '%1'").arg(path);
|
||||
}
|
||||
|
||||
palettes->append(palette);
|
||||
}
|
||||
tileset->palettes = palettes;
|
||||
}
|
||||
|
||||
Blockdata* Project::readBlockdata(QString path) {
|
||||
|
@ -916,11 +1000,16 @@ Map* Project::getMap(QString map_name) {
|
|||
}
|
||||
}
|
||||
|
||||
Tileset* Project::getTileset(QString label) {
|
||||
Tileset* Project::getTileset(QString label, bool forceLoad) {
|
||||
Tileset *existingTileset = nullptr;
|
||||
if (tileset_cache->contains(label)) {
|
||||
existingTileset = tileset_cache->value(label);
|
||||
}
|
||||
|
||||
if (existingTileset && !forceLoad) {
|
||||
return tileset_cache->value(label);
|
||||
} else {
|
||||
Tileset *tileset = loadTileset(label);
|
||||
Tileset *tileset = loadTileset(label, existingTileset);
|
||||
return tileset;
|
||||
}
|
||||
}
|
||||
|
@ -1056,7 +1145,7 @@ Map* Project::addNewMapToGroup(QString mapName, int groupNum) {
|
|||
setNewMapEvents(map);
|
||||
setNewMapConnections(map);
|
||||
map->commit();
|
||||
map->history.save();
|
||||
map->metatileHistory.save();
|
||||
map_cache->insert(mapName, map);
|
||||
|
||||
return map;
|
||||
|
@ -1252,6 +1341,22 @@ void Project::readBgEventFacingDirections() {
|
|||
readCDefinesSorted(filepath, prefixes, bgEventFacingDirections);
|
||||
}
|
||||
|
||||
void Project::readMetatileBehaviors() {
|
||||
this->metatileBehaviorMap.clear();
|
||||
this->metatileBehaviorMapInverse.clear();
|
||||
QString filepath = root + "/include/constants/metatile_behaviors.h";
|
||||
QString text = readTextFile(filepath);
|
||||
if (!text.isNull()) {
|
||||
QStringList prefixes = (QStringList() << "MB_");
|
||||
this->metatileBehaviorMap = readCDefines(text, prefixes);
|
||||
for (QString defineName : this->metatileBehaviorMap.keys()) {
|
||||
this->metatileBehaviorMapInverse.insert(this->metatileBehaviorMap[defineName], defineName);
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Failed to read C defines file: " << filepath;
|
||||
}
|
||||
}
|
||||
|
||||
void Project::readCDefinesSorted(QString filepath, QStringList prefixes, QStringList* definesToSet) {
|
||||
QString text = readTextFile(filepath);
|
||||
if (!text.isNull()) {
|
||||
|
@ -1327,6 +1432,11 @@ QMap<QString, int> Project::getEventObjGfxConstants() {
|
|||
return constants;
|
||||
}
|
||||
|
||||
QString Project::fixPalettePath(QString path) {
|
||||
path = path.replace(QRegExp("\\.gbapal$"), ".pal");
|
||||
return path;
|
||||
}
|
||||
|
||||
QString Project::fixGraphicPath(QString path) {
|
||||
path = path.replace(QRegExp("\\.lz$"), "");
|
||||
path = path.replace(QRegExp("\\.[1248]bpp$"), ".png");
|
||||
|
@ -1478,8 +1588,8 @@ void Project::saveMapEvents(Map *map) {
|
|||
|
||||
// save heal event changes
|
||||
if (map->events["heal_event_group"].length() > 0) {
|
||||
for (Event *heal : map->events["heal_event_group"]) {
|
||||
HealLocation hl = heal->buildHealLocation();
|
||||
for (Event *healEvent : map->events["heal_event_group"]) {
|
||||
HealLocation hl = HealLocation::fromEvent(healEvent);
|
||||
flyableMaps[hl.index - 1] = hl;
|
||||
}
|
||||
}
|
6
src/settings.cpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#include "settings.h"
|
||||
|
||||
Settings::Settings()
|
||||
{
|
||||
|
||||
}
|
42
src/ui/bordermetatilespixmapitem.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include "bordermetatilespixmapitem.h"
|
||||
#include "imageproviders.h"
|
||||
#include <QPainter>
|
||||
|
||||
void BorderMetatilesPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles();
|
||||
QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions();
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
|
||||
for (int i = 0; i < selectionDimensions.x() && (i + x) < 2; i++) {
|
||||
for (int j = 0; j < selectionDimensions.y() && (j + y) < 2; j++) {
|
||||
int blockIndex = (j + y) * 2 + (i + x);
|
||||
uint16_t tile = selectedMetatiles->at(j * selectionDimensions.x() + i);
|
||||
(*map->layout->border->blocks)[blockIndex].tile = tile;
|
||||
}
|
||||
}
|
||||
|
||||
draw();
|
||||
emit borderMetatilesChanged();
|
||||
}
|
||||
|
||||
void BorderMetatilesPixmapItem::draw() {
|
||||
QImage image(32, 32, QImage::Format_RGBA8888);
|
||||
QPainter painter(&image);
|
||||
QList<Block> *blocks = map->layout->border->blocks;
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int j = 0; j < 2; j++) {
|
||||
int x = i * 16;
|
||||
int y = j * 16;
|
||||
int index = j * 2 + i;
|
||||
QImage metatile_image = getMetatileImage(blocks->value(index).tile, map->layout->tileset_primary, map->layout->tileset_secondary);
|
||||
QPoint metatile_origin = QPoint(x, y);
|
||||
painter.drawImage(metatile_origin, metatile_image);
|
||||
}
|
||||
}
|
||||
|
||||
painter.end();
|
||||
this->setPixmap(QPixmap::fromImage(image));
|
||||
}
|
86
src/ui/collisionpixmapitem.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
#include "collisionpixmapitem.h"
|
||||
|
||||
void CollisionPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||
int x = static_cast<int>(event->pos().x()) / 16;
|
||||
int y = static_cast<int>(event->pos().y()) / 16;
|
||||
emit this->hoveredMapMovementPermissionChanged(x, y);
|
||||
if (this->settings->betterCursors){
|
||||
setCursor(this->settings->mapCursor);
|
||||
}
|
||||
}
|
||||
void CollisionPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
|
||||
emit this->hoveredMapMovementPermissionCleared();
|
||||
if (this->settings->betterCursors){
|
||||
unsetCursor();
|
||||
}
|
||||
}
|
||||
void CollisionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
emit mouseEvent(event, this);
|
||||
}
|
||||
void CollisionPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||
emit mouseEvent(event, this);
|
||||
}
|
||||
void CollisionPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||
emit mouseEvent(event, this);
|
||||
}
|
||||
|
||||
void CollisionPixmapItem::draw(bool ignoreCache) {
|
||||
if (map) {
|
||||
setPixmap(map->renderCollision(ignoreCache));
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
|
||||
if (map) {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
Block *block = map->getBlock(x, y);
|
||||
if (block) {
|
||||
block->collision = this->movementPermissionsSelector->getSelectedCollision();
|
||||
block->elevation = this->movementPermissionsSelector->getSelectedElevation();
|
||||
map->_setBlock(x, y, *block);
|
||||
}
|
||||
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
|
||||
map->commit();
|
||||
}
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
|
||||
if (map) {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
uint16_t collision = this->movementPermissionsSelector->getSelectedCollision();
|
||||
uint16_t elevation = this->movementPermissionsSelector->getSelectedElevation();
|
||||
map->floodFillCollisionElevation(x, y, collision, elevation);
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionPixmapItem::pick(QGraphicsSceneMouseEvent *event) {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
Block *block = map->getBlock(x, y);
|
||||
if (block) {
|
||||
this->movementPermissionsSelector->select(block->collision, block->elevation);
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionPixmapItem::updateMovementPermissionSelection(QGraphicsSceneMouseEvent *event) {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
|
||||
// Snap point to within map bounds.
|
||||
if (x < 0) x = 0;
|
||||
if (x >= map->getWidth()) x = map->getWidth() - 1;
|
||||
if (y < 0) y = 0;
|
||||
if (y >= map->getHeight()) y = map->getHeight() - 1;
|
||||
|
||||
Block *block = map->getBlock(x, y);
|
||||
this->movementPermissionsSelector->select(block->collision, block->elevation);
|
||||
}
|
72
src/ui/connectionpixmapitem.cpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
#include "connectionpixmapitem.h"
|
||||
|
||||
void ConnectionPixmapItem::render(qreal opacity) {
|
||||
QPixmap newPixmap = this->basePixmap.copy(0, 0, this->basePixmap.width(), this->basePixmap.height());
|
||||
if (opacity < 1) {
|
||||
QPainter painter(&newPixmap);
|
||||
int alpha = static_cast<int>(255 * (1 - opacity));
|
||||
painter.fillRect(0, 0, newPixmap.width(), newPixmap.height(), QColor(0, 0, 0, alpha));
|
||||
painter.end();
|
||||
}
|
||||
this->setPixmap(newPixmap);
|
||||
}
|
||||
|
||||
int ConnectionPixmapItem::getMinOffset() {
|
||||
if (this->connection->direction == "up" || this->connection->direction == "down")
|
||||
return 1 - (this->pixmap().width() / 16);
|
||||
else
|
||||
return 1 - (this->pixmap().height() / 16);
|
||||
}
|
||||
|
||||
int ConnectionPixmapItem::getMaxOffset() {
|
||||
if (this->connection->direction == "up" || this->connection->direction == "down")
|
||||
return this->baseMapWidth - 1;
|
||||
else
|
||||
return this->baseMapHeight - 1;
|
||||
}
|
||||
|
||||
QVariant ConnectionPixmapItem::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
{
|
||||
if (change == ItemPositionChange) {
|
||||
QPointF newPos = value.toPointF();
|
||||
|
||||
qreal x, y;
|
||||
int newOffset = this->initialOffset;
|
||||
if (this->connection->direction == "up" || this->connection->direction == "down") {
|
||||
x = round(newPos.x() / 16) * 16;
|
||||
newOffset += (x - initialX) / 16;
|
||||
newOffset = qMin(newOffset, this->getMaxOffset());
|
||||
newOffset = qMax(newOffset, this->getMinOffset());
|
||||
x = newOffset * 16;
|
||||
}
|
||||
else {
|
||||
x = this->initialX;
|
||||
}
|
||||
|
||||
if (this->connection->direction == "right" || this->connection->direction == "left") {
|
||||
y = round(newPos.y() / 16) * 16;
|
||||
newOffset += (y - this->initialY) / 16;
|
||||
newOffset = qMin(newOffset, this->getMaxOffset());
|
||||
newOffset = qMax(newOffset, this->getMinOffset());
|
||||
y = newOffset * 16;
|
||||
}
|
||||
else {
|
||||
y = this->initialY;
|
||||
}
|
||||
|
||||
this->connection->offset = QString::number(newOffset);
|
||||
emit connectionMoved(this->connection);
|
||||
return QPointF(x, y);
|
||||
}
|
||||
else {
|
||||
return QGraphicsItem::itemChange(change, value);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectionPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *) {
|
||||
emit connectionItemSelected(this);
|
||||
}
|
||||
|
||||
void ConnectionPixmapItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *) {
|
||||
emit connectionItemDoubleClicked(this);
|
||||
}
|
26
src/ui/currentselectedmetatilespixmapitem.cpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include "currentselectedmetatilespixmapitem.h"
|
||||
#include "imageproviders.h"
|
||||
#include <QPainter>
|
||||
|
||||
void CurrentSelectedMetatilesPixmapItem::draw() {
|
||||
QList<uint16_t> *selectedMetatiles = metatileSelector->getSelectedMetatiles();
|
||||
QPoint selectionDimensions = metatileSelector->getSelectionDimensions();
|
||||
int width = selectionDimensions.x() * 16;
|
||||
int height = selectionDimensions.y() * 16;
|
||||
QImage image(width, height, QImage::Format_RGBA8888);
|
||||
QPainter painter(&image);
|
||||
|
||||
for (int i = 0; i < selectionDimensions.x(); i++) {
|
||||
for (int j = 0; j < selectionDimensions.y(); j++) {
|
||||
int x = i * 16;
|
||||
int y = j * 16;
|
||||
int index = j * selectionDimensions.x() + i;
|
||||
QImage metatile_image = getMetatileImage(selectedMetatiles->at(index), map->layout->tileset_primary, map->layout->tileset_secondary);
|
||||
QPoint metatile_origin = QPoint(x, y);
|
||||
painter.drawImage(metatile_origin, metatile_image);
|
||||
}
|
||||
}
|
||||
|
||||
painter.end();
|
||||
setPixmap(QPixmap::fromImage(image));
|
||||
}
|
14
src/ui/eventpropertiesframe.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "eventpropertiesframe.h"
|
||||
#include "ui_eventpropertiesframe.h"
|
||||
|
||||
EventPropertiesFrame::EventPropertiesFrame(QWidget *parent) :
|
||||
QFrame(parent),
|
||||
ui(new Ui::EventPropertiesFrame)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
EventPropertiesFrame::~EventPropertiesFrame()
|
||||
{
|
||||
delete ui;
|
||||
}
|
0
graphicsview.cpp → src/ui/graphicsview.cpp
Executable file → Normal file
97
src/ui/imageproviders.cpp
Normal file
|
@ -0,0 +1,97 @@
|
|||
#include "imageproviders.h"
|
||||
#include <QPainter>
|
||||
#include <QDebug>
|
||||
|
||||
QImage getCollisionMetatileImage(Block block) {
|
||||
return getCollisionMetatileImage(block.collision, block.elevation);
|
||||
}
|
||||
|
||||
QImage getCollisionMetatileImage(int collision, int elevation) {
|
||||
int x = collision * 16;
|
||||
int y = elevation * 16;
|
||||
QPixmap collisionImage = QPixmap(":/images/collisions.png").copy(x, y, 16, 16);
|
||||
return collisionImage.toImage();
|
||||
}
|
||||
|
||||
QImage getMetatileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
QImage metatile_image(16, 16, QImage::Format_RGBA8888);
|
||||
|
||||
Metatile* metatile = Tileset::getMetatile(tile, primaryTileset, secondaryTileset);
|
||||
if (!metatile || !metatile->tiles) {
|
||||
metatile_image.fill(0xffffffff);
|
||||
return metatile_image;
|
||||
}
|
||||
|
||||
Tileset* blockTileset = Tileset::getBlockTileset(tile, primaryTileset, secondaryTileset);
|
||||
if (!blockTileset) {
|
||||
metatile_image.fill(0xffffffff);
|
||||
return metatile_image;
|
||||
}
|
||||
QList<QList<QRgb>> palettes = Tileset::getBlockPalettes(primaryTileset, secondaryTileset);
|
||||
|
||||
QPainter metatile_painter(&metatile_image);
|
||||
for (int layer = 0; layer < 2; layer++)
|
||||
for (int y = 0; y < 2; y++)
|
||||
for (int x = 0; x < 2; x++) {
|
||||
Tile tile_ = metatile->tiles->value((y * 2) + x + (layer * 4));
|
||||
QImage tile_image = getTileImage(tile_.tile, primaryTileset, secondaryTileset);
|
||||
if (tile_image.isNull()) {
|
||||
// Some metatiles specify tiles that are outside the valid range.
|
||||
// These are treated as completely transparent, so they can be skipped without
|
||||
// being drawn unless they're on the bottom layer, in which case we need
|
||||
// a placeholder because garbage will be drawn otherwise.
|
||||
if (layer == 0) {
|
||||
metatile_painter.fillRect(x * 8, y * 8, 8, 8, palettes.value(0).value(0));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Colorize the metatile tiles with its palette.
|
||||
if (tile_.palette < palettes.length()) {
|
||||
QList<QRgb> palette = palettes.value(tile_.palette);
|
||||
for (int j = 0; j < palette.length(); j++) {
|
||||
tile_image.setColor(j, palette.value(j));
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Tile is referring to invalid palette number: " << tile_.palette;
|
||||
}
|
||||
|
||||
// The top layer of the metatile has its first color displayed at transparent.
|
||||
if (layer > 0) {
|
||||
QColor color(tile_image.color(0));
|
||||
color.setAlpha(0);
|
||||
tile_image.setColor(0, color.rgba());
|
||||
}
|
||||
|
||||
QPoint origin = QPoint(x*8, y*8);
|
||||
metatile_painter.drawImage(origin, tile_image.mirrored(tile_.xflip == 1, tile_.yflip == 1));
|
||||
}
|
||||
metatile_painter.end();
|
||||
|
||||
return metatile_image;
|
||||
}
|
||||
|
||||
QImage getTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
Tileset *tileset = Tileset::getBlockTileset(tile, primaryTileset, secondaryTileset);
|
||||
int local_index = Metatile::getBlockIndex(tile);
|
||||
if (!tileset || !tileset->tiles) {
|
||||
return QImage();
|
||||
}
|
||||
return tileset->tiles->value(local_index, QImage());
|
||||
}
|
||||
|
||||
QImage getColoredTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset, int paletteId) {
|
||||
QList<QRgb> palette = Tileset::getPalette(paletteId, primaryTileset, secondaryTileset);
|
||||
QImage tileImage = getTileImage(tile, primaryTileset, secondaryTileset);
|
||||
if (tileImage.isNull()) {
|
||||
tileImage = QImage(16, 16, QImage::Format_RGBA8888);
|
||||
QPainter painter(&tileImage);
|
||||
painter.fillRect(0, 0, 16, 16, palette.at(0));
|
||||
} else {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
tileImage.setColor(i, palette.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
return tileImage;
|
||||
}
|
480
src/ui/mappixmapitem.cpp
Normal file
|
@ -0,0 +1,480 @@
|
|||
#include "mappixmapitem.h"
|
||||
|
||||
#define SWAP(a, b) do { if (a != b) { a ^= b; b ^= a; a ^= b; } } while (0)
|
||||
|
||||
void MapPixmapItem::paint(QGraphicsSceneMouseEvent *event) {
|
||||
if (map) {
|
||||
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
|
||||
map->commit();
|
||||
} else {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
|
||||
// Paint onto the map.
|
||||
bool smartPathsEnabled = event->modifiers() & Qt::ShiftModifier;
|
||||
QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions();
|
||||
if ((this->settings->smartPathsEnabled || smartPathsEnabled) && selectionDimensions.x() == 3 && selectionDimensions.y() == 3) {
|
||||
paintSmartPath(x, y);
|
||||
} else {
|
||||
paintNormal(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
void MapPixmapItem::shift(QGraphicsSceneMouseEvent *event) {
|
||||
if (map) {
|
||||
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
|
||||
map->commit();
|
||||
} else {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<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 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) {
|
||||
QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions();
|
||||
QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles();
|
||||
|
||||
// Snap the selected position to the top-left of the block boundary.
|
||||
// This allows painting via dragging the mouse to tile the painted region.
|
||||
int xDiff = x - this->paint_tile_initial_x;
|
||||
int yDiff = y - this->paint_tile_initial_y;
|
||||
if (xDiff < 0 && xDiff % selectionDimensions.x() != 0) xDiff -= selectionDimensions.x();
|
||||
if (yDiff < 0 && yDiff % selectionDimensions.y() != 0) yDiff -= selectionDimensions.y();
|
||||
|
||||
x = this->paint_tile_initial_x + (xDiff / selectionDimensions.x()) * selectionDimensions.x();
|
||||
y = this->paint_tile_initial_y + (yDiff / selectionDimensions.y()) * selectionDimensions.y();
|
||||
|
||||
for (int i = 0; i < selectionDimensions.x() && i + x < map->getWidth(); i++)
|
||||
for (int j = 0; j < selectionDimensions.y() && j + y < map->getHeight(); j++) {
|
||||
int actualX = i + x;
|
||||
int actualY = j + y;
|
||||
Block *block = map->getBlock(actualX, actualY);
|
||||
if (block) {
|
||||
block->tile = selectedMetatiles->at(j * selectionDimensions.x() + i);
|
||||
map->_setBlock(actualX, actualY, *block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// These are tile offsets from the top-left tile in the 3x3 smart path selection.
|
||||
// Each entry is for one possibility from the marching squares value for a tile.
|
||||
// (Marching Squares: https://en.wikipedia.org/wiki/Marching_squares)
|
||||
QList<int> MapPixmapItem::smartPathTable = QList<int>({
|
||||
4, // 0000
|
||||
4, // 0001
|
||||
4, // 0010
|
||||
6, // 0011
|
||||
4, // 0100
|
||||
4, // 0101
|
||||
0, // 0110
|
||||
3, // 0111
|
||||
4, // 1000
|
||||
8, // 1001
|
||||
4, // 1010
|
||||
7, // 1011
|
||||
2, // 1100
|
||||
5, // 1101
|
||||
1, // 1110
|
||||
4, // 1111
|
||||
});
|
||||
|
||||
#define IS_SMART_PATH_TILE(block) (selectedMetatiles->contains(block->tile))
|
||||
|
||||
void MapPixmapItem::paintSmartPath(int x, int y) {
|
||||
QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions();
|
||||
QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles();
|
||||
|
||||
// Smart path should never be enabled without a 3x3 block selection.
|
||||
if (selectionDimensions.x() != 3 || selectionDimensions.y() != 3) return;
|
||||
|
||||
// Shift to the middle tile of the smart path selection.
|
||||
uint16_t openTile = selectedMetatiles->at(4);
|
||||
|
||||
// Fill the region with the open tile.
|
||||
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;
|
||||
int actualX = i + x;
|
||||
int actualY = j + y;
|
||||
Block *block = map->getBlock(actualX, actualY);
|
||||
if (block) {
|
||||
block->tile = openTile;
|
||||
map->_setBlock(actualX, actualY, *block);
|
||||
}
|
||||
}
|
||||
|
||||
// Go back and resolve the edge tiles
|
||||
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 == -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.
|
||||
int actualX = i + x;
|
||||
int actualY = j + y;
|
||||
Block *block = map->getBlock(actualX, actualY);
|
||||
if (!block || !IS_SMART_PATH_TILE(block)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int id = 0;
|
||||
Block *top = map->getBlock(actualX, actualY - 1);
|
||||
Block *right = map->getBlock(actualX + 1, actualY);
|
||||
Block *bottom = map->getBlock(actualX, actualY + 1);
|
||||
Block *left = map->getBlock(actualX - 1, actualY);
|
||||
|
||||
// Get marching squares value, to determine which tile to use.
|
||||
if (top && IS_SMART_PATH_TILE(top))
|
||||
id += 1;
|
||||
if (right && IS_SMART_PATH_TILE(right))
|
||||
id += 2;
|
||||
if (bottom && IS_SMART_PATH_TILE(bottom))
|
||||
id += 4;
|
||||
if (left && IS_SMART_PATH_TILE(left))
|
||||
id += 8;
|
||||
|
||||
block->tile = selectedMetatiles->at(smartPathTable[id]);
|
||||
map->_setBlock(actualX, actualY, *block);
|
||||
}
|
||||
}
|
||||
|
||||
void MapPixmapItem::updateMetatileSelection(QGraphicsSceneMouseEvent *event) {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
|
||||
// Snap point to within map bounds.
|
||||
if (x < 0) x = 0;
|
||||
if (x >= map->getWidth()) x = map->getWidth() - 1;
|
||||
if (y < 0) y = 0;
|
||||
if (y >= map->getHeight()) y = map->getHeight() - 1;
|
||||
|
||||
// Update/apply copied metatiles.
|
||||
if (event->type() == QEvent::GraphicsSceneMousePress) {
|
||||
selection_origin = QPoint(x, y);
|
||||
selection.clear();
|
||||
selection.append(QPoint(x, y));
|
||||
uint16_t metatileId = map->getBlock(x, y)->tile;
|
||||
this->metatileSelector->select(metatileId);
|
||||
} else if (event->type() == QEvent::GraphicsSceneMouseMove) {
|
||||
QPoint pos = QPoint(x, y);
|
||||
int x1 = selection_origin.x();
|
||||
int y1 = selection_origin.y();
|
||||
int x2 = pos.x();
|
||||
int y2 = pos.y();
|
||||
if (x1 > x2) SWAP(x1, x2);
|
||||
if (y1 > y2) SWAP(y1, y2);
|
||||
selection.clear();
|
||||
for (int y = y1; y <= y2; y++) {
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
selection.append(QPoint(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
QList<uint16_t> metatiles;
|
||||
for (QPoint point : selection) {
|
||||
metatiles.append(map->getBlock(point.x(), point.y())->tile);
|
||||
}
|
||||
|
||||
this->metatileSelector->setExternalSelection(x2 - x1 + 1, y2 - y1 + 1, &metatiles);
|
||||
}
|
||||
}
|
||||
|
||||
void MapPixmapItem::floodFill(QGraphicsSceneMouseEvent *event) {
|
||||
if (map) {
|
||||
if (event->type() == QEvent::GraphicsSceneMouseRelease) {
|
||||
map->commit();
|
||||
} else {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
Block *block = map->getBlock(x, y);
|
||||
QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles();
|
||||
QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions();
|
||||
int tile = selectedMetatiles->first();
|
||||
if (block && block->tile != tile) {
|
||||
bool smartPathsEnabled = event->modifiers() & Qt::ShiftModifier;
|
||||
if ((this->settings->smartPathsEnabled || smartPathsEnabled) && selectionDimensions.x() == 3 && selectionDimensions.y() == 3)
|
||||
this->_floodFillSmartPath(x, y);
|
||||
else
|
||||
this->_floodFill(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
draw();
|
||||
}
|
||||
}
|
||||
|
||||
void MapPixmapItem::_floodFill(int initialX, int initialY) {
|
||||
QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions();
|
||||
QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles();
|
||||
|
||||
QList<QPoint> todo;
|
||||
todo.append(QPoint(initialX, initialY));
|
||||
while (todo.length()) {
|
||||
QPoint point = todo.takeAt(0);
|
||||
int x = point.x();
|
||||
int y = point.y();
|
||||
|
||||
Block *block = map->getBlock(x, y);
|
||||
if (!block) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int xDiff = x - initialX;
|
||||
int yDiff = y - initialY;
|
||||
int i = xDiff % selectionDimensions.x();
|
||||
int j = yDiff % selectionDimensions.y();
|
||||
if (i < 0) i = selectionDimensions.x() + i;
|
||||
if (j < 0) j = selectionDimensions.y() + j;
|
||||
uint16_t tile = selectedMetatiles->at(j * selectionDimensions.x() + i);
|
||||
uint16_t old_tile = block->tile;
|
||||
if (old_tile == tile) {
|
||||
continue;
|
||||
}
|
||||
|
||||
block->tile = tile;
|
||||
map->_setBlock(x, y, *block);
|
||||
if ((block = map->getBlock(x + 1, y)) && block->tile == old_tile) {
|
||||
todo.append(QPoint(x + 1, y));
|
||||
}
|
||||
if ((block = map->getBlock(x - 1, y)) && block->tile == old_tile) {
|
||||
todo.append(QPoint(x - 1, y));
|
||||
}
|
||||
if ((block = map->getBlock(x, y + 1)) && block->tile == old_tile) {
|
||||
todo.append(QPoint(x, y + 1));
|
||||
}
|
||||
if ((block = map->getBlock(x, y - 1)) && block->tile == old_tile) {
|
||||
todo.append(QPoint(x, y - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapPixmapItem::_floodFillSmartPath(int initialX, int initialY) {
|
||||
QPoint selectionDimensions = this->metatileSelector->getSelectionDimensions();
|
||||
QList<uint16_t> *selectedMetatiles = this->metatileSelector->getSelectedMetatiles();
|
||||
|
||||
// Smart path should never be enabled without a 3x3 block selection.
|
||||
if (selectionDimensions.x() != 3 || selectionDimensions.y() != 3) return;
|
||||
|
||||
// Shift to the middle tile of the smart path selection.
|
||||
uint16_t openTile = selectedMetatiles->at(4);
|
||||
|
||||
// Flood fill the region with the open tile.
|
||||
QList<QPoint> todo;
|
||||
todo.append(QPoint(initialX, initialY));
|
||||
while (todo.length()) {
|
||||
QPoint point = todo.takeAt(0);
|
||||
int x = point.x();
|
||||
int y = point.y();
|
||||
|
||||
Block *block = map->getBlock(x, y);
|
||||
if (!block) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint16_t old_tile = block->tile;
|
||||
if (old_tile == openTile) {
|
||||
continue;
|
||||
}
|
||||
|
||||
block->tile = openTile;
|
||||
map->_setBlock(x, y, *block);
|
||||
if ((block = map->getBlock(x + 1, y)) && block->tile == old_tile) {
|
||||
todo.append(QPoint(x + 1, y));
|
||||
}
|
||||
if ((block = map->getBlock(x - 1, y)) && block->tile == old_tile) {
|
||||
todo.append(QPoint(x - 1, y));
|
||||
}
|
||||
if ((block = map->getBlock(x, y + 1)) && block->tile == old_tile) {
|
||||
todo.append(QPoint(x, y + 1));
|
||||
}
|
||||
if ((block = map->getBlock(x, y - 1)) && block->tile == old_tile) {
|
||||
todo.append(QPoint(x, y - 1));
|
||||
}
|
||||
}
|
||||
|
||||
// Go back and resolve the flood-filled edge tiles.
|
||||
// Mark tiles as visited while we go.
|
||||
int numMetatiles = map->getWidth() * map->getHeight();
|
||||
bool *visited = new bool[numMetatiles];
|
||||
for (int i = 0; i < numMetatiles; i++)
|
||||
visited[i] = false;
|
||||
|
||||
todo.append(QPoint(initialX, initialY));
|
||||
while (todo.length()) {
|
||||
QPoint point = todo.takeAt(0);
|
||||
int x = point.x();
|
||||
int y = point.y();
|
||||
visited[x + y * map->getWidth()] = true;
|
||||
|
||||
Block *block = map->getBlock(x, y);
|
||||
if (!block) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int id = 0;
|
||||
Block *top = map->getBlock(x, y - 1);
|
||||
Block *right = map->getBlock(x + 1, y);
|
||||
Block *bottom = map->getBlock(x, y + 1);
|
||||
Block *left = map->getBlock(x - 1, y);
|
||||
|
||||
// Get marching squares value, to determine which tile to use.
|
||||
if (top && IS_SMART_PATH_TILE(top))
|
||||
id += 1;
|
||||
if (right && IS_SMART_PATH_TILE(right))
|
||||
id += 2;
|
||||
if (bottom && IS_SMART_PATH_TILE(bottom))
|
||||
id += 4;
|
||||
if (left && IS_SMART_PATH_TILE(left))
|
||||
id += 8;
|
||||
|
||||
block->tile = selectedMetatiles->at(smartPathTable[id]);
|
||||
map->_setBlock(x, y, *block);
|
||||
|
||||
// Visit neighbors if they are smart-path tiles, and don't revisit any.
|
||||
if (!visited[x + 1 + y * map->getWidth()] && (block = map->getBlock(x + 1, y)) && IS_SMART_PATH_TILE(block)) {
|
||||
todo.append(QPoint(x + 1, y));
|
||||
visited[x + 1 + y * map->getWidth()] = true;
|
||||
}
|
||||
if (!visited[x - 1 + y * map->getWidth()] && (block = map->getBlock(x - 1, y)) && IS_SMART_PATH_TILE(block)) {
|
||||
todo.append(QPoint(x - 1, y));
|
||||
visited[x - 1 + y * map->getWidth()] = true;
|
||||
}
|
||||
if (!visited[x + (y + 1) * map->getWidth()] && (block = map->getBlock(x, y + 1)) && IS_SMART_PATH_TILE(block)) {
|
||||
todo.append(QPoint(x, y + 1));
|
||||
visited[x + (y + 1) * map->getWidth()] = true;
|
||||
}
|
||||
if (!visited[x + (y - 1) * map->getWidth()] && (block = map->getBlock(x, y - 1)) && IS_SMART_PATH_TILE(block)) {
|
||||
todo.append(QPoint(x, y - 1));
|
||||
visited[x + (y - 1) * map->getWidth()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] visited;
|
||||
}
|
||||
|
||||
void MapPixmapItem::pick(QGraphicsSceneMouseEvent *event) {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
Block *block = map->getBlock(x, y);
|
||||
if (block) {
|
||||
this->metatileSelector->select(block->tile);
|
||||
}
|
||||
}
|
||||
|
||||
void MapPixmapItem::select(QGraphicsSceneMouseEvent *event) {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
if (event->type() == QEvent::GraphicsSceneMousePress) {
|
||||
selection_origin = QPoint(x, y);
|
||||
selection.clear();
|
||||
} else if (event->type() == QEvent::GraphicsSceneMouseMove) {
|
||||
if (event->buttons() & Qt::LeftButton) {
|
||||
selection.clear();
|
||||
selection.append(QPoint(x, y));
|
||||
}
|
||||
} else if (event->type() == QEvent::GraphicsSceneMouseRelease) {
|
||||
if (!selection.isEmpty()) {
|
||||
QPoint pos = selection.last();
|
||||
int x1 = selection_origin.x();
|
||||
int y1 = selection_origin.y();
|
||||
int x2 = pos.x();
|
||||
int y2 = pos.y();
|
||||
if (x1 > x2) SWAP(x1, x2);
|
||||
if (y1 > y2) SWAP(y1, y2);
|
||||
selection.clear();
|
||||
for (int y = y1; y <= y2; y++) {
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
selection.append(QPoint(x, y));
|
||||
}
|
||||
}
|
||||
qDebug() << QString("selected (%1, %2) -> (%3, %4)").arg(x1).arg(y1).arg(x2).arg(y2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MapPixmapItem::draw(bool ignoreCache) {
|
||||
if (map) {
|
||||
setPixmap(map->render(ignoreCache));
|
||||
}
|
||||
}
|
||||
|
||||
void MapPixmapItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||
int x = static_cast<int>(event->pos().x()) / 16;
|
||||
int y = static_cast<int>(event->pos().y()) / 16;
|
||||
emit this->hoveredMapMetatileChanged(x, y);
|
||||
if (this->settings->betterCursors){
|
||||
setCursor(this->settings->mapCursor);
|
||||
}
|
||||
}
|
||||
void MapPixmapItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
|
||||
emit this->hoveredMapMetatileCleared();
|
||||
if (this->settings->betterCursors){
|
||||
unsetCursor();
|
||||
}
|
||||
}
|
||||
void MapPixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
this->paint_tile_initial_x = x;
|
||||
this->paint_tile_initial_y = y;
|
||||
emit mouseEvent(event, this);
|
||||
}
|
||||
void MapPixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||
int x = static_cast<int>(event->pos().x()) / 16;
|
||||
int y = static_cast<int>(event->pos().y()) / 16;
|
||||
emit this->hoveredMapMetatileChanged(x, y);
|
||||
emit mouseEvent(event, this);
|
||||
}
|
||||
void MapPixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||
emit mouseEvent(event, this);
|
||||
}
|
23
src/ui/mapsceneeventfilter.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include "mapsceneeventfilter.h"
|
||||
#include <QEvent>
|
||||
#include <QGraphicsSceneWheelEvent>
|
||||
|
||||
MapSceneEventFilter::MapSceneEventFilter(QObject *parent) : QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool MapSceneEventFilter::eventFilter(QObject*, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::GraphicsSceneWheel)
|
||||
{
|
||||
QGraphicsSceneWheelEvent *wheelEvent = static_cast<QGraphicsSceneWheelEvent *>(event);
|
||||
if (wheelEvent->modifiers() & Qt::ControlModifier)
|
||||
{
|
||||
emit wheelZoom(wheelEvent->delta() > 0 ? 1 : -1);
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
45
src/ui/metatilelayersitem.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#include "metatilelayersitem.h"
|
||||
#include "imageproviders.h"
|
||||
#include <QPainter>
|
||||
|
||||
void MetatileLayersItem::draw() {
|
||||
const QList<QPoint> tileCoords = QList<QPoint>{
|
||||
QPoint(0, 0),
|
||||
QPoint(16, 0),
|
||||
QPoint(0, 16),
|
||||
QPoint(16, 16),
|
||||
QPoint(32, 0),
|
||||
QPoint(48, 0),
|
||||
QPoint(32, 16),
|
||||
QPoint(48, 16),
|
||||
};
|
||||
|
||||
QPixmap pixmap(64, 32);
|
||||
QPainter painter(&pixmap);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Tile tile = this->metatile->tiles->at(i);
|
||||
QImage tileImage = getColoredTileImage(tile.tile, this->primaryTileset, this->secondaryTileset, tile.palette)
|
||||
.mirrored(tile.xflip, tile.yflip)
|
||||
.scaled(16, 16);
|
||||
painter.drawImage(tileCoords.at(i), tileImage);
|
||||
}
|
||||
|
||||
this->setPixmap(pixmap);
|
||||
}
|
||||
|
||||
void MetatileLayersItem::setMetatile(Metatile *metatile) {
|
||||
this->metatile = metatile;
|
||||
}
|
||||
|
||||
void MetatileLayersItem::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
this->draw();
|
||||
}
|
||||
|
||||
void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
QPointF pos = event->pos();
|
||||
int x = static_cast<int>(pos.x()) / 16;
|
||||
int y = static_cast<int>(pos.y()) / 16;
|
||||
emit this->tileChanged(x, y);
|
||||
}
|
147
src/ui/metatileselector.cpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
#include "imageproviders.h"
|
||||
#include "metatileselector.h"
|
||||
#include "project.h"
|
||||
#include <QPainter>
|
||||
|
||||
QPoint MetatileSelector::getSelectionDimensions() {
|
||||
if (this->externalSelection) {
|
||||
return QPoint(this->externalSelectionWidth, this->externalSelectionHeight);
|
||||
} else {
|
||||
return SelectablePixmapItem::getSelectionDimensions();
|
||||
}
|
||||
}
|
||||
|
||||
void MetatileSelector::draw() {
|
||||
if (!this->primaryTileset || !this->primaryTileset->metatiles
|
||||
|| !this->secondaryTileset || !this->secondaryTileset->metatiles) {
|
||||
this->setPixmap(QPixmap());
|
||||
}
|
||||
|
||||
int primaryLength = this->primaryTileset->metatiles->length();
|
||||
int length_ = primaryLength + this->secondaryTileset->metatiles->length();
|
||||
int height_ = length_ / this->numMetatilesWide;
|
||||
QImage image(this->numMetatilesWide * 16, height_ * 16, QImage::Format_RGBA8888);
|
||||
QPainter painter(&image);
|
||||
for (int i = 0; i < length_; i++) {
|
||||
int tile = i;
|
||||
if (i >= primaryLength) {
|
||||
tile += Project::getNumMetatilesPrimary() - primaryLength;
|
||||
}
|
||||
QImage metatile_image = getMetatileImage(tile, this->primaryTileset, this->secondaryTileset);
|
||||
int map_y = i / this->numMetatilesWide;
|
||||
int map_x = i % this->numMetatilesWide;
|
||||
QPoint metatile_origin = QPoint(map_x * 16, map_y * 16);
|
||||
painter.drawImage(metatile_origin, metatile_image);
|
||||
}
|
||||
|
||||
painter.end();
|
||||
this->setPixmap(QPixmap::fromImage(image));
|
||||
|
||||
if (!this->externalSelection) {
|
||||
this->drawSelection();
|
||||
}
|
||||
}
|
||||
|
||||
void MetatileSelector::select(uint16_t metatileId) {
|
||||
this->externalSelection = false;
|
||||
QPoint coords = this->getMetatileIdCoords(metatileId);
|
||||
SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0);
|
||||
this->updateSelectedMetatiles();
|
||||
emit selectedMetatilesChanged();
|
||||
}
|
||||
|
||||
void MetatileSelector::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
this->draw();
|
||||
}
|
||||
|
||||
QList<uint16_t>* MetatileSelector::getSelectedMetatiles() {
|
||||
if (this->externalSelection) {
|
||||
return this->externalSelectedMetatiles;
|
||||
} else {
|
||||
return this->selectedMetatiles;
|
||||
}
|
||||
}
|
||||
|
||||
void MetatileSelector::setExternalSelection(int width, int height, QList<uint16_t> *metatiles) {
|
||||
this->externalSelection = true;
|
||||
this->externalSelectionWidth = width;
|
||||
this->externalSelectionHeight = height;
|
||||
this->externalSelectedMetatiles->clear();
|
||||
for (int i = 0; i < metatiles->length(); i++) {
|
||||
this->externalSelectedMetatiles->append(metatiles->at(i));
|
||||
}
|
||||
|
||||
this->draw();
|
||||
emit selectedMetatilesChanged();
|
||||
}
|
||||
|
||||
void MetatileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
SelectablePixmapItem::mousePressEvent(event);
|
||||
this->updateSelectedMetatiles();
|
||||
emit selectedMetatilesChanged();
|
||||
}
|
||||
|
||||
void MetatileSelector::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||
SelectablePixmapItem::mouseMoveEvent(event);
|
||||
this->updateSelectedMetatiles();
|
||||
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
uint16_t metatileId = this->getMetatileId(pos.x(), pos.y());
|
||||
emit this->hoveredMetatileSelectionChanged(metatileId);
|
||||
emit selectedMetatilesChanged();
|
||||
}
|
||||
|
||||
void MetatileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||
SelectablePixmapItem::mouseReleaseEvent(event);
|
||||
this->updateSelectedMetatiles();
|
||||
emit selectedMetatilesChanged();
|
||||
}
|
||||
|
||||
void MetatileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
uint16_t metatileId = this->getMetatileId(pos.x(), pos.y());
|
||||
emit this->hoveredMetatileSelectionChanged(metatileId);
|
||||
}
|
||||
|
||||
void MetatileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) {
|
||||
emit this->hoveredMetatileSelectionCleared();
|
||||
}
|
||||
|
||||
void MetatileSelector::updateSelectedMetatiles() {
|
||||
this->externalSelection = false;
|
||||
this->selectedMetatiles->clear();
|
||||
QPoint origin = this->getSelectionStart();
|
||||
QPoint dimensions = this->getSelectionDimensions();
|
||||
for (int j = 0; j < dimensions.y(); j++) {
|
||||
for (int i = 0; i < dimensions.x(); i++) {
|
||||
uint16_t metatileId = this->getMetatileId(origin.x() + i, origin.y() + j);
|
||||
this->selectedMetatiles->append(metatileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t MetatileSelector::getMetatileId(int x, int y) {
|
||||
int index = y * this->numMetatilesWide + x;
|
||||
if (index < this->primaryTileset->metatiles->length()) {
|
||||
return static_cast<uint16_t>(index);
|
||||
} else {
|
||||
return static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - this->primaryTileset->metatiles->length());
|
||||
}
|
||||
}
|
||||
|
||||
QPoint MetatileSelector::getMetatileIdCoords(uint16_t metatileId) {
|
||||
if (metatileId >= Project::getNumMetatilesTotal()
|
||||
|| (metatileId < Project::getNumMetatilesPrimary() && metatileId >= this->primaryTileset->metatiles->length())
|
||||
|| (metatileId < Project::getNumMetatilesTotal() && metatileId >= Project::getNumMetatilesPrimary() + this->secondaryTileset->metatiles->length()))
|
||||
{
|
||||
// Invalid metatile id.
|
||||
return QPoint(0, 0);
|
||||
}
|
||||
|
||||
int index = metatileId < Project::getNumMetatilesPrimary()
|
||||
? metatileId
|
||||
: metatileId - Project::getNumMetatilesPrimary() + this->primaryTileset->metatiles->length();
|
||||
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);
|
||||
}
|
31
src/ui/movementpermissionsselector.cpp
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "movementpermissionsselector.h"
|
||||
#include <QPainter>
|
||||
|
||||
void MovementPermissionsSelector::draw() {
|
||||
QPixmap pixmap(":/images/collisions.png");
|
||||
this->setPixmap(pixmap.scaled(64, 512));
|
||||
this->drawSelection();
|
||||
}
|
||||
|
||||
uint16_t MovementPermissionsSelector::getSelectedCollision() {
|
||||
return static_cast<uint16_t>(this->selectionInitialX);
|
||||
}
|
||||
|
||||
uint16_t MovementPermissionsSelector::getSelectedElevation() {
|
||||
return static_cast<uint16_t>(this->selectionInitialY);
|
||||
}
|
||||
|
||||
void MovementPermissionsSelector::select(uint16_t collision, uint16_t elevation) {
|
||||
SelectablePixmapItem::select(collision, elevation, 0, 0);
|
||||
}
|
||||
|
||||
void MovementPermissionsSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
uint16_t collision = static_cast<uint16_t>(pos.x());
|
||||
uint16_t elevation = static_cast<uint16_t>(pos.y());
|
||||
emit this->hoveredMovementPermissionChanged(collision, elevation);
|
||||
}
|
||||
|
||||
void MovementPermissionsSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent *) {
|
||||
emit this->hoveredMovementPermissionCleared();
|
||||
}
|
|
@ -10,9 +10,10 @@ NewEventToolButton::NewEventToolButton(QWidget *parent) :
|
|||
setPopupMode(QToolButton::MenuButtonPopup);
|
||||
QObject::connect(this, SIGNAL(triggered(QAction*)),
|
||||
this, SLOT(setDefaultAction(QAction*)));
|
||||
this->init();
|
||||
}
|
||||
|
||||
void NewEventToolButton::initButton()
|
||||
void NewEventToolButton::init()
|
||||
{
|
||||
// Add a context menu to select different types of map events.
|
||||
this->newObjectAction = new QAction("New Object", this);
|
176
src/ui/paletteeditor.cpp
Normal file
|
@ -0,0 +1,176 @@
|
|||
#include "paletteeditor.h"
|
||||
#include "ui_paletteeditor.h"
|
||||
|
||||
PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset *secondaryTileset, QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::PaletteEditor)
|
||||
{
|
||||
this->project = project;
|
||||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
this->ui->setupUi(this);
|
||||
this->ui->spinBox_PaletteId->setMinimum(0);
|
||||
this->ui->spinBox_PaletteId->setMaximum(Project::getNumPalettesTotal() - 1);
|
||||
this->sliders.clear();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
this->sliders.append(QList<QSlider*>());
|
||||
}
|
||||
this->sliders[0].append(this->ui->horizontalSlider);
|
||||
this->sliders[0].append(this->ui->horizontalSlider_2);
|
||||
this->sliders[0].append(this->ui->horizontalSlider_3);
|
||||
this->sliders[1].append(this->ui->horizontalSlider_4);
|
||||
this->sliders[1].append(this->ui->horizontalSlider_5);
|
||||
this->sliders[1].append(this->ui->horizontalSlider_6);
|
||||
this->sliders[2].append(this->ui->horizontalSlider_7);
|
||||
this->sliders[2].append(this->ui->horizontalSlider_8);
|
||||
this->sliders[2].append(this->ui->horizontalSlider_9);
|
||||
this->sliders[3].append(this->ui->horizontalSlider_10);
|
||||
this->sliders[3].append(this->ui->horizontalSlider_11);
|
||||
this->sliders[3].append(this->ui->horizontalSlider_12);
|
||||
this->sliders[4].append(this->ui->horizontalSlider_13);
|
||||
this->sliders[4].append(this->ui->horizontalSlider_14);
|
||||
this->sliders[4].append(this->ui->horizontalSlider_15);
|
||||
this->sliders[5].append(this->ui->horizontalSlider_16);
|
||||
this->sliders[5].append(this->ui->horizontalSlider_17);
|
||||
this->sliders[5].append(this->ui->horizontalSlider_18);
|
||||
this->sliders[6].append(this->ui->horizontalSlider_19);
|
||||
this->sliders[6].append(this->ui->horizontalSlider_20);
|
||||
this->sliders[6].append(this->ui->horizontalSlider_21);
|
||||
this->sliders[7].append(this->ui->horizontalSlider_22);
|
||||
this->sliders[7].append(this->ui->horizontalSlider_23);
|
||||
this->sliders[7].append(this->ui->horizontalSlider_24);
|
||||
this->sliders[8].append(this->ui->horizontalSlider_25);
|
||||
this->sliders[8].append(this->ui->horizontalSlider_26);
|
||||
this->sliders[8].append(this->ui->horizontalSlider_27);
|
||||
this->sliders[9].append(this->ui->horizontalSlider_28);
|
||||
this->sliders[9].append(this->ui->horizontalSlider_29);
|
||||
this->sliders[9].append(this->ui->horizontalSlider_30);
|
||||
this->sliders[10].append(this->ui->horizontalSlider_31);
|
||||
this->sliders[10].append(this->ui->horizontalSlider_32);
|
||||
this->sliders[10].append(this->ui->horizontalSlider_33);
|
||||
this->sliders[11].append(this->ui->horizontalSlider_34);
|
||||
this->sliders[11].append(this->ui->horizontalSlider_35);
|
||||
this->sliders[11].append(this->ui->horizontalSlider_36);
|
||||
this->sliders[12].append(this->ui->horizontalSlider_37);
|
||||
this->sliders[12].append(this->ui->horizontalSlider_38);
|
||||
this->sliders[12].append(this->ui->horizontalSlider_39);
|
||||
this->sliders[13].append(this->ui->horizontalSlider_40);
|
||||
this->sliders[13].append(this->ui->horizontalSlider_41);
|
||||
this->sliders[13].append(this->ui->horizontalSlider_42);
|
||||
this->sliders[14].append(this->ui->horizontalSlider_43);
|
||||
this->sliders[14].append(this->ui->horizontalSlider_44);
|
||||
this->sliders[14].append(this->ui->horizontalSlider_45);
|
||||
this->sliders[15].append(this->ui->horizontalSlider_46);
|
||||
this->sliders[15].append(this->ui->horizontalSlider_47);
|
||||
this->sliders[15].append(this->ui->horizontalSlider_48);
|
||||
|
||||
this->frames.clear();
|
||||
this->frames.append(this->ui->frame);
|
||||
this->frames.append(this->ui->frame_2);
|
||||
this->frames.append(this->ui->frame_3);
|
||||
this->frames.append(this->ui->frame_4);
|
||||
this->frames.append(this->ui->frame_5);
|
||||
this->frames.append(this->ui->frame_6);
|
||||
this->frames.append(this->ui->frame_7);
|
||||
this->frames.append(this->ui->frame_8);
|
||||
this->frames.append(this->ui->frame_9);
|
||||
this->frames.append(this->ui->frame_10);
|
||||
this->frames.append(this->ui->frame_11);
|
||||
this->frames.append(this->ui->frame_12);
|
||||
this->frames.append(this->ui->frame_13);
|
||||
this->frames.append(this->ui->frame_14);
|
||||
this->frames.append(this->ui->frame_15);
|
||||
this->frames.append(this->ui->frame_16);
|
||||
|
||||
this->initColorSliders();
|
||||
this->refreshColorSliders();
|
||||
this->refreshColors();
|
||||
}
|
||||
|
||||
PaletteEditor::~PaletteEditor()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void PaletteEditor::disableSliderSignals() {
|
||||
for (int i = 0; i < this->sliders.length(); i++) {
|
||||
this->sliders.at(i).at(0)->blockSignals(true);
|
||||
this->sliders.at(i).at(1)->blockSignals(true);
|
||||
this->sliders.at(i).at(2)->blockSignals(true);
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditor::enableSliderSignals() {
|
||||
for (int i = 0; i < this->sliders.length(); i++) {
|
||||
this->sliders.at(i).at(0)->blockSignals(false);
|
||||
this->sliders.at(i).at(1)->blockSignals(false);
|
||||
this->sliders.at(i).at(2)->blockSignals(false);
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditor::initColorSliders() {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
connect(this->sliders[i][0], &QSlider::valueChanged, [=](int) { this->setColor(i); });
|
||||
connect(this->sliders[i][1], &QSlider::valueChanged, [=](int) { this->setColor(i); });
|
||||
connect(this->sliders[i][2], &QSlider::valueChanged, [=](int) { this->setColor(i); });
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditor::refreshColorSliders() {
|
||||
disableSliderSignals();
|
||||
int paletteNum = this->ui->spinBox_PaletteId->value();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
QRgb color;
|
||||
if (paletteNum < Project::getNumPalettesPrimary()) {
|
||||
color = this->primaryTileset->palettes->at(paletteNum).at(i);
|
||||
} else {
|
||||
color = this->secondaryTileset->palettes->at(paletteNum).at(i);
|
||||
}
|
||||
|
||||
this->sliders[i][0]->setValue(qRed(color) / 8);
|
||||
this->sliders[i][1]->setValue(qGreen(color) / 8);
|
||||
this->sliders[i][2]->setValue(qBlue(color) / 8);
|
||||
}
|
||||
enableSliderSignals();
|
||||
}
|
||||
|
||||
void PaletteEditor::refreshColors() {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
this->refreshColor(i);
|
||||
}
|
||||
}
|
||||
|
||||
void PaletteEditor::refreshColor(int colorIndex) {
|
||||
QString stylesheet = QString("background-color: rgb(%1, %2, %3);")
|
||||
.arg(this->sliders[colorIndex][0]->value() * 8)
|
||||
.arg(this->sliders[colorIndex][1]->value() * 8)
|
||||
.arg(this->sliders[colorIndex][2]->value() * 8);
|
||||
this->frames[colorIndex]->setStyleSheet(stylesheet);
|
||||
}
|
||||
|
||||
void PaletteEditor::setPaletteId(int paletteId) {
|
||||
this->ui->spinBox_PaletteId->blockSignals(true);
|
||||
this->ui->spinBox_PaletteId->setValue(paletteId);
|
||||
this->refreshColorSliders();
|
||||
this->refreshColors();
|
||||
this->ui->spinBox_PaletteId->blockSignals(false);
|
||||
}
|
||||
|
||||
void PaletteEditor::setColor(int colorIndex) {
|
||||
int paletteNum = this->ui->spinBox_PaletteId->value();
|
||||
int red = this->sliders[colorIndex][0]->value() * 8;
|
||||
int green = this->sliders[colorIndex][1]->value() * 8;
|
||||
int blue = this->sliders[colorIndex][2]->value() * 8;
|
||||
Tileset *tileset = paletteNum < Project::getNumPalettesPrimary()
|
||||
? this->primaryTileset
|
||||
: this->secondaryTileset;
|
||||
(*tileset->palettes)[paletteNum][colorIndex] = qRgb(red, green, blue);
|
||||
this->refreshColor(colorIndex);
|
||||
emit this->changedPaletteColor();
|
||||
}
|
||||
|
||||
void PaletteEditor::on_spinBox_PaletteId_valueChanged(int paletteId) {
|
||||
this->refreshColorSliders();
|
||||
this->refreshColors();
|
||||
emit this->changedPalette(paletteId);
|
||||
}
|
108
src/ui/selectablepixmapitem.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
#include "selectablepixmapitem.h"
|
||||
#include <QPainter>
|
||||
|
||||
QPoint SelectablePixmapItem::getSelectionDimensions()
|
||||
{
|
||||
return QPoint(abs(this->selectionOffsetX) + 1, abs(this->selectionOffsetY) + 1);
|
||||
}
|
||||
|
||||
QPoint SelectablePixmapItem::getSelectionStart()
|
||||
{
|
||||
int x = this->selectionInitialX;
|
||||
int y = this->selectionInitialY;
|
||||
if (this->selectionOffsetX < 0) x += this->selectionOffsetX;
|
||||
if (this->selectionOffsetY < 0) y += this->selectionOffsetY;
|
||||
return QPoint(x, y);
|
||||
}
|
||||
|
||||
void SelectablePixmapItem::select(int x, int y, int width, int height)
|
||||
{
|
||||
this->selectionInitialX = x;
|
||||
this->selectionInitialY = y;
|
||||
this->selectionOffsetX = qMax(0, qMin(width, this->maxSelectionWidth));
|
||||
this->selectionOffsetY = qMax(0, qMin(height, this->maxSelectionHeight));
|
||||
this->draw();
|
||||
}
|
||||
|
||||
void SelectablePixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
this->selectionInitialX = pos.x();
|
||||
this->selectionInitialY = pos.y();
|
||||
this->selectionOffsetX = 0;
|
||||
this->selectionOffsetY = 0;
|
||||
this->updateSelection(pos.x(), pos.y());
|
||||
}
|
||||
|
||||
void SelectablePixmapItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
this->updateSelection(pos.x(), pos.y());
|
||||
}
|
||||
|
||||
void SelectablePixmapItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
this->updateSelection(pos.x(), pos.y());
|
||||
}
|
||||
|
||||
void SelectablePixmapItem::updateSelection(int x, int y)
|
||||
{
|
||||
// Snap to a valid position inside the selection area.
|
||||
int width = pixmap().width() / this->cellWidth;
|
||||
int height = pixmap().height() / this->cellHeight;
|
||||
if (x < 0) x = 0;
|
||||
if (x >= width) x = width - 1;
|
||||
if (y < 0) y = 0;
|
||||
if (y >= height) y = height - 1;
|
||||
|
||||
this->selectionOffsetX = x - this->selectionInitialX;
|
||||
this->selectionOffsetY = y - this->selectionInitialY;
|
||||
|
||||
// Respect max selection dimensions by moving the selection's origin.
|
||||
if (this->selectionOffsetX >= this->maxSelectionWidth) {
|
||||
this->selectionInitialX += this->selectionOffsetX - this->maxSelectionWidth + 1;
|
||||
this->selectionOffsetX = this->maxSelectionWidth - 1;
|
||||
} else if (this->selectionOffsetX <= -this->maxSelectionWidth) {
|
||||
this->selectionInitialX += this->selectionOffsetX + this->maxSelectionWidth - 1;
|
||||
this->selectionOffsetX = -this->maxSelectionWidth + 1;
|
||||
}
|
||||
if (this->selectionOffsetY >= this->maxSelectionHeight) {
|
||||
this->selectionInitialY += this->selectionOffsetY - this->maxSelectionHeight + 1;
|
||||
this->selectionOffsetY = this->maxSelectionHeight - 1;
|
||||
} else if (this->selectionOffsetY <= -this->maxSelectionHeight) {
|
||||
this->selectionInitialY += this->selectionOffsetY + this->maxSelectionHeight - 1;
|
||||
this->selectionOffsetY = -this->maxSelectionHeight + 1;
|
||||
}
|
||||
|
||||
this->draw();
|
||||
}
|
||||
|
||||
QPoint SelectablePixmapItem::getCellPos(QPointF pos)
|
||||
{
|
||||
if (pos.x() < 0) pos.setX(0);
|
||||
if (pos.y() < 0) pos.setY(0);
|
||||
if (pos.x() >= this->pixmap().width()) pos.setX(this->pixmap().width() - 1);
|
||||
if (pos.y() >= this->pixmap().height()) pos.setY(this->pixmap().height() - 1);
|
||||
return QPoint(static_cast<int>(pos.x()) / this->cellWidth,
|
||||
static_cast<int>(pos.y()) / this->cellHeight);
|
||||
}
|
||||
|
||||
void SelectablePixmapItem::drawSelection()
|
||||
{
|
||||
QPixmap pixmap = this->pixmap();
|
||||
QPainter painter(&pixmap);
|
||||
QPoint origin = this->getSelectionStart();
|
||||
QPoint dimensions = this->getSelectionDimensions();
|
||||
|
||||
int rectWidth = dimensions.x() * this->cellWidth;
|
||||
int rectHeight = dimensions.y() * this->cellHeight;
|
||||
|
||||
painter.setPen(QColor(0xff, 0xff, 0xff));
|
||||
painter.drawRect(origin.x() * this->cellWidth, origin.y() * this->cellHeight, rectWidth - 1, rectHeight -1);
|
||||
painter.setPen(QColor(0, 0, 0));
|
||||
painter.drawRect(origin.x() * this->cellWidth - 1, origin.y() * this->cellHeight - 1, rectWidth + 1, rectHeight + 1);
|
||||
painter.drawRect(origin.x() * this->cellWidth + 1, origin.y() * this->cellHeight + 1, rectWidth - 3, rectHeight - 3);
|
||||
|
||||
this->setPixmap(pixmap);
|
||||
}
|
460
src/ui/tileseteditor.cpp
Normal file
|
@ -0,0 +1,460 @@
|
|||
#include "tileseteditor.h"
|
||||
#include "ui_tileseteditor.h"
|
||||
#include "imageproviders.h"
|
||||
#include <QFileDialog>
|
||||
#include <QDebug>
|
||||
#include <QMessageBox>
|
||||
#include <QDialogButtonBox>
|
||||
|
||||
TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QString secondaryTilesetLabel, QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::TilesetEditor)
|
||||
{
|
||||
this->init(project, primaryTilesetLabel, secondaryTilesetLabel);
|
||||
}
|
||||
|
||||
TilesetEditor::~TilesetEditor()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void TilesetEditor::init(Project *project, QString primaryTilesetLabel, QString secondaryTilesetLabel) {
|
||||
ui->setupUi(this);
|
||||
this->project = project;
|
||||
|
||||
this->hasUnsavedChanges = false;
|
||||
this->tileXFlip = ui->checkBox_xFlip->isChecked();
|
||||
this->tileYFlip = ui->checkBox_yFlip->isChecked();
|
||||
this->paletteId = ui->spinBox_paletteSelector->value();
|
||||
|
||||
Tileset *primaryTileset = project->getTileset(primaryTilesetLabel);
|
||||
Tileset *secondaryTileset = project->getTileset(secondaryTilesetLabel);
|
||||
if (this->primaryTileset) delete this->primaryTileset;
|
||||
if (this->secondaryTileset) delete this->secondaryTileset;
|
||||
this->primaryTileset = primaryTileset->copy();
|
||||
this->secondaryTileset = secondaryTileset->copy();
|
||||
|
||||
QList<QString> sortedBehaviors;
|
||||
for (int num : project->metatileBehaviorMapInverse.keys()) {
|
||||
this->ui->comboBox_metatileBehaviors->addItem(project->metatileBehaviorMapInverse[num], num);
|
||||
}
|
||||
this->ui->comboBox_layerType->addItem("Normal - Middle/Top", 0);
|
||||
this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", 1);
|
||||
this->ui->comboBox_layerType->addItem("Split - Bottom/Top", 2);
|
||||
this->ui->spinBox_paletteSelector->setMinimum(0);
|
||||
this->ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1);
|
||||
|
||||
this->initMetatileSelector();
|
||||
this->initMetatileLayersItem();
|
||||
this->initTileSelector();
|
||||
this->initSelectedTileItem();
|
||||
this->metatileSelector->select(0);
|
||||
}
|
||||
|
||||
void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel) {
|
||||
delete this->primaryTileset;
|
||||
delete this->secondaryTileset;
|
||||
Tileset *primaryTileset = project->getTileset(primaryTilesetLabel);
|
||||
Tileset *secondaryTileset = project->getTileset(secondaryTilesetLabel);
|
||||
this->primaryTileset = primaryTileset->copy();
|
||||
this->secondaryTileset = secondaryTileset->copy();
|
||||
this->refresh();
|
||||
}
|
||||
|
||||
void TilesetEditor::refresh() {
|
||||
this->metatileSelector->setTilesets(this->primaryTileset, this->secondaryTileset);
|
||||
this->tileSelector->setTilesets(this->primaryTileset, this->secondaryTileset);
|
||||
this->metatileLayersItem->setTilesets(this->primaryTileset, this->secondaryTileset);
|
||||
this->metatileSelector->select(this->metatileSelector->getSelectedMetatile());
|
||||
this->drawSelectedTiles();
|
||||
|
||||
this->ui->graphicsView_Tiles->setSceneRect(0, 0, this->tileSelector->pixmap().width() + 2, this->tileSelector->pixmap().height() + 2);
|
||||
this->ui->graphicsView_Tiles->setFixedSize(this->tileSelector->pixmap().width() + 2, this->tileSelector->pixmap().height() + 2);
|
||||
this->ui->graphicsView_Metatiles->setSceneRect(0, 0, this->metatileSelector->pixmap().width() + 2, this->metatileSelector->pixmap().height() + 2);
|
||||
this->ui->graphicsView_Metatiles->setFixedSize(this->metatileSelector->pixmap().width() + 2, this->metatileSelector->pixmap().height() + 2);
|
||||
this->ui->graphicsView_selectedTile->setFixedSize(this->selectedTilePixmapItem->pixmap().width(), this->selectedTilePixmapItem->pixmap().height());
|
||||
}
|
||||
|
||||
void TilesetEditor::initMetatileSelector()
|
||||
{
|
||||
this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset);
|
||||
connect(this->metatileSelector, SIGNAL(hoveredMetatileChanged(uint16_t)),
|
||||
this, SLOT(onHoveredMetatileChanged(uint16_t)));
|
||||
connect(this->metatileSelector, SIGNAL(hoveredMetatileCleared()),
|
||||
this, SLOT(onHoveredMetatileCleared()));
|
||||
connect(this->metatileSelector, SIGNAL(selectedMetatileChanged(uint16_t)),
|
||||
this, SLOT(onSelectedMetatileChanged(uint16_t)));
|
||||
|
||||
this->metatilesScene = new QGraphicsScene;
|
||||
this->metatilesScene->addItem(this->metatileSelector);
|
||||
this->metatileSelector->draw();
|
||||
|
||||
this->ui->graphicsView_Metatiles->setScene(this->metatilesScene);
|
||||
this->ui->graphicsView_Metatiles->setFixedSize(this->metatileSelector->pixmap().width() + 2, this->metatileSelector->pixmap().height() + 2);
|
||||
}
|
||||
|
||||
void TilesetEditor::initTileSelector()
|
||||
{
|
||||
this->tileSelector = new TilesetEditorTileSelector(this->primaryTileset, this->secondaryTileset);
|
||||
connect(this->tileSelector, SIGNAL(hoveredTileChanged(uint16_t)),
|
||||
this, SLOT(onHoveredTileChanged(uint16_t)));
|
||||
connect(this->tileSelector, SIGNAL(hoveredTileCleared()),
|
||||
this, SLOT(onHoveredTileCleared()));
|
||||
connect(this->tileSelector, SIGNAL(selectedTilesChanged()),
|
||||
this, SLOT(onSelectedTilesChanged()));
|
||||
|
||||
this->tilesScene = new QGraphicsScene;
|
||||
this->tilesScene->addItem(this->tileSelector);
|
||||
this->tileSelector->select(0);
|
||||
this->tileSelector->draw();
|
||||
|
||||
this->ui->graphicsView_Tiles->setScene(this->tilesScene);
|
||||
this->ui->graphicsView_Tiles->setFixedSize(this->tileSelector->pixmap().width() + 2, this->tileSelector->pixmap().height() + 2);
|
||||
}
|
||||
|
||||
void TilesetEditor::initSelectedTileItem() {
|
||||
this->selectedTileScene = new QGraphicsScene;
|
||||
this->drawSelectedTiles();
|
||||
this->ui->graphicsView_selectedTile->setScene(this->selectedTileScene);
|
||||
this->ui->graphicsView_selectedTile->setFixedSize(this->selectedTilePixmapItem->pixmap().width(), this->selectedTilePixmapItem->pixmap().height());
|
||||
}
|
||||
|
||||
void TilesetEditor::drawSelectedTiles() {
|
||||
if (!this->selectedTileScene) {
|
||||
return;
|
||||
}
|
||||
|
||||
this->selectedTileScene->clear();
|
||||
QList<uint16_t> tiles = this->tileSelector->getSelectedTiles();
|
||||
QPoint dimensions = this->tileSelector->getSelectionDimensions();
|
||||
QImage selectionImage(16 * dimensions.x(), 16 * dimensions.y(), QImage::Format_RGBA8888);
|
||||
QPainter painter(&selectionImage);
|
||||
int tileIndex = 0;
|
||||
for (int j = 0; j < dimensions.y(); j++) {
|
||||
for (int i = 0; i < dimensions.x(); i++) {
|
||||
QImage tileImage = getColoredTileImage(tiles.at(tileIndex), this->primaryTileset, this->secondaryTileset, this->paletteId)
|
||||
.mirrored(this->tileXFlip, this->tileYFlip)
|
||||
.scaled(16, 16);
|
||||
tileIndex++;
|
||||
painter.drawImage(i * 16, j * 16, tileImage);
|
||||
}
|
||||
}
|
||||
|
||||
this->selectedTilePixmapItem = new QGraphicsPixmapItem(QPixmap::fromImage(selectionImage));
|
||||
this->selectedTileScene->addItem(this->selectedTilePixmapItem);
|
||||
this->ui->graphicsView_selectedTile->setFixedSize(this->selectedTilePixmapItem->pixmap().width(), this->selectedTilePixmapItem->pixmap().height());
|
||||
}
|
||||
|
||||
void TilesetEditor::initMetatileLayersItem() {
|
||||
Metatile *metatile = Tileset::getMetatile(this->metatileSelector->getSelectedMetatile(), this->primaryTileset, this->secondaryTileset);
|
||||
this->metatileLayersItem = new MetatileLayersItem(metatile, this->primaryTileset, this->secondaryTileset);
|
||||
connect(this->metatileLayersItem, SIGNAL(tileChanged(int, int)),
|
||||
this, SLOT(onMetatileLayerTileChanged(int, int)));
|
||||
|
||||
this->metatileLayersScene = new QGraphicsScene;
|
||||
this->metatileLayersScene->addItem(this->metatileLayersItem);
|
||||
this->ui->graphicsView_metatileLayers->setScene(this->metatileLayersScene);
|
||||
}
|
||||
|
||||
void TilesetEditor::onHoveredMetatileChanged(uint16_t metatileId) {
|
||||
QString message = QString("Metatile: 0x%1")
|
||||
.arg(QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper());
|
||||
this->ui->statusbar->showMessage(message);
|
||||
}
|
||||
|
||||
void TilesetEditor::onHoveredMetatileCleared() {
|
||||
this->ui->statusbar->clearMessage();
|
||||
}
|
||||
|
||||
void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) {
|
||||
this->metatile = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset);
|
||||
this->metatileLayersItem->setMetatile(metatile);
|
||||
this->metatileLayersItem->draw();
|
||||
this->ui->comboBox_metatileBehaviors->setCurrentIndex(this->ui->comboBox_metatileBehaviors->findData(this->metatile->behavior));
|
||||
this->ui->comboBox_layerType->setCurrentIndex(this->ui->comboBox_layerType->findData(this->metatile->layerType));
|
||||
}
|
||||
|
||||
void TilesetEditor::onHoveredTileChanged(uint16_t tile) {
|
||||
QString message = QString("Tile: 0x%1")
|
||||
.arg(QString("%1").arg(tile, 3, 16, QChar('0')).toUpper());
|
||||
this->ui->statusbar->showMessage(message);
|
||||
}
|
||||
|
||||
void TilesetEditor::onHoveredTileCleared() {
|
||||
this->ui->statusbar->clearMessage();
|
||||
}
|
||||
|
||||
void TilesetEditor::onSelectedTilesChanged() {
|
||||
this->drawSelectedTiles();
|
||||
}
|
||||
|
||||
void TilesetEditor::onMetatileLayerTileChanged(int x, int y) {
|
||||
int maxTileIndex = x < 2 ? 3 : 7;
|
||||
QPoint dimensions = this->tileSelector->getSelectionDimensions();
|
||||
QList<uint16_t> tiles = this->tileSelector->getSelectedTiles();
|
||||
int selectedTileIndex = 0;
|
||||
for (int j = 0; j < dimensions.y(); j++) {
|
||||
for (int i = 0; i < dimensions.x(); i++) {
|
||||
int tileIndex = ((x + i) / 2 * 4) + ((y + j) * 2) + ((x + i) % 2);
|
||||
if (tileIndex <= maxTileIndex) {
|
||||
Tile tile = this->metatile->tiles->at(tileIndex);
|
||||
tile.tile = tiles.at(selectedTileIndex);
|
||||
tile.xflip = this->tileXFlip;
|
||||
tile.yflip = this->tileYFlip;
|
||||
tile.palette = this->paletteId;
|
||||
(*this->metatile->tiles)[tileIndex] = tile;
|
||||
}
|
||||
selectedTileIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
this->metatileSelector->draw();
|
||||
this->metatileLayersItem->draw();
|
||||
this->hasUnsavedChanges = true;
|
||||
}
|
||||
|
||||
void TilesetEditor::on_spinBox_paletteSelector_valueChanged(int paletteId)
|
||||
{
|
||||
this->ui->spinBox_paletteSelector->blockSignals(true);
|
||||
this->ui->spinBox_paletteSelector->setValue(paletteId);
|
||||
this->ui->spinBox_paletteSelector->blockSignals(false);
|
||||
this->paletteId = paletteId;
|
||||
this->tileSelector->setPaletteId(paletteId);
|
||||
this->drawSelectedTiles();
|
||||
if (this->paletteEditor) {
|
||||
this->paletteEditor->setPaletteId(paletteId);
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::on_checkBox_xFlip_stateChanged(int checked)
|
||||
{
|
||||
this->tileXFlip = checked;
|
||||
this->tileSelector->setTileFlips(this->tileXFlip, this->tileYFlip);
|
||||
this->drawSelectedTiles();
|
||||
}
|
||||
|
||||
void TilesetEditor::on_checkBox_yFlip_stateChanged(int checked)
|
||||
{
|
||||
this->tileYFlip = checked;
|
||||
this->tileSelector->setTileFlips(this->tileXFlip, this->tileYFlip);
|
||||
this->drawSelectedTiles();
|
||||
}
|
||||
|
||||
void TilesetEditor::on_comboBox_metatileBehaviors_currentIndexChanged(const QString &metatileBehavior)
|
||||
{
|
||||
if (this->metatile) {
|
||||
this->metatile->behavior = static_cast<uint8_t>(project->metatileBehaviorMap[metatileBehavior]);
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::on_comboBox_layerType_currentIndexChanged(int layerType)
|
||||
{
|
||||
if (this->metatile) {
|
||||
this->metatile->layerType = static_cast<uint8_t>(layerType);
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionSave_Tileset_triggered()
|
||||
{
|
||||
this->project->saveTilesets(this->primaryTileset, this->secondaryTileset);
|
||||
emit this->tilesetsSaved(this->primaryTileset->name, this->secondaryTileset->name);
|
||||
this->ui->statusbar->showMessage(QString("Saved primary and secondary Tilesets!"), 5000);
|
||||
this->hasUnsavedChanges = false;
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionImport_Primary_Tiles_triggered()
|
||||
{
|
||||
this->importTilesetTiles(this->primaryTileset, true);
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionImport_Secondary_Tiles_triggered()
|
||||
{
|
||||
this->importTilesetTiles(this->secondaryTileset, false);
|
||||
}
|
||||
|
||||
void TilesetEditor::importTilesetTiles(Tileset *tileset, bool primary) {
|
||||
QString descriptor = primary ? "primary" : "secondary";
|
||||
QString descriptorCaps = primary ? "Primary" : "Secondary";
|
||||
|
||||
QString filepath = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
QString("Import %1 Tileset Tiles Image").arg(descriptorCaps),
|
||||
this->project->root,
|
||||
"Image Files (*.png)");
|
||||
if (filepath.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << QString("Importing %1 tileset tiles '%2'").arg(descriptor).arg(filepath);
|
||||
|
||||
// Validate image dimensions.
|
||||
QImage image = QImage(filepath);
|
||||
if (image.width() == 0 || image.height() == 0 || image.width() % 8 != 0 || image.height() % 8 != 0) {
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setText("Failed to import tiles.");
|
||||
msgBox.setInformativeText(QString("The image dimensions (%1 x %2) are invalid. Width and height must be multiples of 8 pixels.")
|
||||
.arg(image.width())
|
||||
.arg(image.height()));
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
msgBox.setIcon(QMessageBox::Icon::Critical);
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate image is properly indexed to 16 colors.
|
||||
if (image.colorCount() != 16) {
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setText("Failed to import tiles.");
|
||||
msgBox.setInformativeText(QString("The image must be indexed and contain 16 total colors. The provided image has %1 indexed colors.")
|
||||
.arg(image.colorCount()));
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
msgBox.setIcon(QMessageBox::Icon::Critical);
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate total number of tiles in image.
|
||||
int numTilesWide = image.width() / 16;
|
||||
int numTilesHigh = image.height() / 16;
|
||||
int totalTiles = numTilesHigh * numTilesWide;
|
||||
int maxAllowedTiles = primary ? Project::getNumTilesPrimary() : Project::getNumTilesTotal() - Project::getNumTilesPrimary();
|
||||
if (totalTiles > maxAllowedTiles) {
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setText("Failed to import tiles.");
|
||||
msgBox.setInformativeText(QString("The maximum number of tiles allowed in the %1 tileset is %2, but the provided image contains %3 total tiles.")
|
||||
.arg(descriptor)
|
||||
.arg(maxAllowedTiles)
|
||||
.arg(totalTiles));
|
||||
msgBox.setDefaultButton(QMessageBox::Ok);
|
||||
msgBox.setIcon(QMessageBox::Icon::Critical);
|
||||
msgBox.exec();
|
||||
return;
|
||||
}
|
||||
|
||||
this->project->loadTilesetTiles(tileset, image);
|
||||
this->project->loadTilesetMetatiles(tileset);
|
||||
this->refresh();
|
||||
this->hasUnsavedChanges = true;
|
||||
}
|
||||
|
||||
void TilesetEditor::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
bool close = true;
|
||||
if (this->hasUnsavedChanges) {
|
||||
QMessageBox::StandardButton result = QMessageBox::question(this, "porymap",
|
||||
"Discard unsaved Tileset changes?",
|
||||
QMessageBox::No | QMessageBox::Yes,
|
||||
QMessageBox::Yes);
|
||||
close = result == QMessageBox::Yes;
|
||||
}
|
||||
|
||||
if (close) {
|
||||
event->accept();
|
||||
emit closed();
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionChange_Metatiles_Count_triggered()
|
||||
{
|
||||
QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
|
||||
dialog.setWindowTitle("Change Number of Metatiles");
|
||||
dialog.setWindowModality(Qt::NonModal);
|
||||
|
||||
QFormLayout form(&dialog);
|
||||
|
||||
QSpinBox *primarySpinBox = new QSpinBox();
|
||||
QSpinBox *secondarySpinBox = new QSpinBox();
|
||||
primarySpinBox->setMinimum(1);
|
||||
secondarySpinBox->setMinimum(1);
|
||||
primarySpinBox->setMaximum(Project::getNumMetatilesPrimary());
|
||||
secondarySpinBox->setMaximum(Project::getNumMetatilesTotal() - Project::getNumMetatilesPrimary());
|
||||
primarySpinBox->setValue(this->primaryTileset->metatiles->length());
|
||||
secondarySpinBox->setValue(this->secondaryTileset->metatiles->length());
|
||||
form.addRow(new QLabel("Primary Tileset"), primarySpinBox);
|
||||
form.addRow(new QLabel("Secondary Tileset"), secondarySpinBox);
|
||||
|
||||
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
|
||||
connect(&buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
|
||||
connect(&buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
|
||||
form.addRow(&buttonBox);
|
||||
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
int numPrimaryMetatiles = primarySpinBox->value();
|
||||
int numSecondaryMetatiles = secondarySpinBox->value();
|
||||
while (this->primaryTileset->metatiles->length() > numPrimaryMetatiles) {
|
||||
Metatile *metatile = this->primaryTileset->metatiles->takeLast();
|
||||
delete metatile;
|
||||
}
|
||||
while (this->primaryTileset->metatiles->length() < numPrimaryMetatiles) {
|
||||
Tile tile;
|
||||
tile.palette = 0;
|
||||
tile.tile = 0;
|
||||
tile.xflip = 0;
|
||||
tile.yflip = 0;
|
||||
Metatile *metatile = new Metatile;
|
||||
metatile->behavior = 0;
|
||||
metatile->layerType = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
metatile->tiles->append(tile);
|
||||
}
|
||||
this->primaryTileset->metatiles->append(metatile);
|
||||
}
|
||||
while (this->secondaryTileset->metatiles->length() > numSecondaryMetatiles) {
|
||||
Metatile *metatile = this->secondaryTileset->metatiles->takeLast();
|
||||
delete metatile;
|
||||
}
|
||||
while (this->secondaryTileset->metatiles->length() < numSecondaryMetatiles) {
|
||||
Tile tile;
|
||||
tile.palette = 0;
|
||||
tile.tile = 0;
|
||||
tile.xflip = 0;
|
||||
tile.yflip = 0;
|
||||
Metatile *metatile = new Metatile;
|
||||
metatile->behavior = 0;
|
||||
metatile->layerType = 0;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
metatile->tiles->append(tile);
|
||||
}
|
||||
this->secondaryTileset->metatiles->append(metatile);
|
||||
}
|
||||
|
||||
this->refresh();
|
||||
this->hasUnsavedChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::onPaletteEditorClosed() {
|
||||
if (this->paletteEditor) {
|
||||
delete this->paletteEditor;
|
||||
this->paletteEditor = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::on_actionChange_Palettes_triggered()
|
||||
{
|
||||
if (!this->paletteEditor) {
|
||||
this->paletteEditor = new PaletteEditor(this->project, this->primaryTileset, this->secondaryTileset, this);
|
||||
connect(this->paletteEditor, SIGNAL(closed()), this, SLOT(onPaletteEditorClosed()));
|
||||
connect(this->paletteEditor, SIGNAL(changedPaletteColor()), this, SLOT(onPaletteEditorChangedPaletteColor()));
|
||||
connect(this->paletteEditor, SIGNAL(changedPalette(int)), this, SLOT(onPaletteEditorChangedPalette(int)));
|
||||
}
|
||||
|
||||
if (!this->paletteEditor->isVisible()) {
|
||||
this->paletteEditor->show();
|
||||
} else if (this->paletteEditor->isMinimized()) {
|
||||
this->paletteEditor->showNormal();
|
||||
} else {
|
||||
this->paletteEditor->activateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditor::onPaletteEditorChangedPaletteColor() {
|
||||
this->refresh();
|
||||
this->hasUnsavedChanges = true;
|
||||
}
|
||||
|
||||
void TilesetEditor::onPaletteEditorChangedPalette(int paletteId) {
|
||||
this->on_spinBox_paletteSelector_valueChanged(paletteId);
|
||||
}
|
114
src/ui/tileseteditormetatileselector.cpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
#include "tileseteditormetatileselector.h"
|
||||
#include "imageproviders.h"
|
||||
#include "project.h"
|
||||
#include <QPainter>
|
||||
|
||||
void TilesetEditorMetatileSelector::draw() {
|
||||
if (!this->primaryTileset || !this->primaryTileset->metatiles
|
||||
|| !this->secondaryTileset || !this->secondaryTileset->metatiles) {
|
||||
this->setPixmap(QPixmap());
|
||||
}
|
||||
|
||||
int primaryLength = this->primaryTileset->metatiles->length();
|
||||
int length_ = primaryLength + this->secondaryTileset->metatiles->length();
|
||||
int height_ = length_ / this->numMetatilesWide;
|
||||
QImage image(this->numMetatilesWide * 32, height_ * 32, QImage::Format_RGBA8888);
|
||||
QPainter painter(&image);
|
||||
for (int i = 0; i < length_; i++) {
|
||||
int tile = i;
|
||||
if (i >= primaryLength) {
|
||||
tile += Project::getNumMetatilesPrimary() - primaryLength;
|
||||
}
|
||||
QImage metatile_image = getMetatileImage(tile, this->primaryTileset, this->secondaryTileset).scaled(32, 32);
|
||||
int map_y = i / this->numMetatilesWide;
|
||||
int map_x = i % this->numMetatilesWide;
|
||||
QPoint metatile_origin = QPoint(map_x * 32, map_y * 32);
|
||||
painter.drawImage(metatile_origin, metatile_image);
|
||||
}
|
||||
|
||||
painter.end();
|
||||
this->setPixmap(QPixmap::fromImage(image));
|
||||
this->drawSelection();
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::select(uint16_t metatileId) {
|
||||
metatileId = this->getValidMetatileId(metatileId);
|
||||
QPoint coords = this->getMetatileIdCoords(metatileId);
|
||||
SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0);
|
||||
this->selectedMetatile = metatileId;
|
||||
emit selectedMetatileChanged(metatileId);
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
this->draw();
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::updateSelectedMetatile() {
|
||||
QPoint origin = this->getSelectionStart();
|
||||
this->selectedMetatile = this->getMetatileId(origin.x(), origin.y());
|
||||
}
|
||||
|
||||
uint16_t TilesetEditorMetatileSelector::getSelectedMetatile() {
|
||||
return this->selectedMetatile;
|
||||
}
|
||||
|
||||
uint16_t TilesetEditorMetatileSelector::getMetatileId(int x, int y) {
|
||||
int index = y * this->numMetatilesWide + x;
|
||||
if (index < this->primaryTileset->metatiles->length()) {
|
||||
return static_cast<uint16_t>(index);
|
||||
} else {
|
||||
return static_cast<uint16_t>(Project::getNumMetatilesPrimary() + index - this->primaryTileset->metatiles->length());
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
SelectablePixmapItem::mousePressEvent(event);
|
||||
this->updateSelectedMetatile();
|
||||
emit selectedMetatileChanged(this->selectedMetatile);
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||
SelectablePixmapItem::mouseMoveEvent(event);
|
||||
this->updateSelectedMetatile();
|
||||
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
uint16_t metatileId = this->getMetatileId(pos.x(), pos.y());
|
||||
emit hoveredMetatileChanged(metatileId);
|
||||
emit selectedMetatileChanged(metatileId);
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||
SelectablePixmapItem::mouseReleaseEvent(event);
|
||||
this->updateSelectedMetatile();
|
||||
emit selectedMetatileChanged(this->selectedMetatile);
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
uint16_t metatileId = this->getMetatileId(pos.x(), pos.y());
|
||||
emit this->hoveredMetatileChanged(metatileId);
|
||||
}
|
||||
|
||||
void TilesetEditorMetatileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) {
|
||||
emit this->hoveredMetatileCleared();
|
||||
}
|
||||
|
||||
QPoint TilesetEditorMetatileSelector::getMetatileIdCoords(uint16_t metatileId) {
|
||||
int index = metatileId < Project::getNumMetatilesPrimary()
|
||||
? metatileId
|
||||
: metatileId - Project::getNumMetatilesPrimary() + this->primaryTileset->metatiles->length();
|
||||
return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide);
|
||||
}
|
||||
|
||||
uint16_t TilesetEditorMetatileSelector::getValidMetatileId(uint16_t metatileId) {
|
||||
if (metatileId >= Project::getNumMetatilesTotal()
|
||||
|| (metatileId < Project::getNumMetatilesPrimary() && metatileId >= this->primaryTileset->metatiles->length())
|
||||
|| (metatileId < Project::getNumMetatilesTotal() && metatileId >= Project::getNumMetatilesPrimary() + this->secondaryTileset->metatiles->length()))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return metatileId;
|
||||
}
|
||||
|
130
src/ui/tileseteditortileselector.cpp
Normal file
|
@ -0,0 +1,130 @@
|
|||
#include "tileseteditortileselector.h"
|
||||
#include "imageproviders.h"
|
||||
#include "project.h"
|
||||
#include <QPainter>
|
||||
|
||||
void TilesetEditorTileSelector::draw() {
|
||||
if (!this->primaryTileset || !this->primaryTileset->tiles
|
||||
|| !this->secondaryTileset || !this->secondaryTileset->tiles) {
|
||||
this->setPixmap(QPixmap());
|
||||
}
|
||||
|
||||
int totalTiles = Project::getNumTilesTotal();
|
||||
int primaryLength = this->primaryTileset->tiles->length();
|
||||
int secondaryLength = this->secondaryTileset->tiles->length();
|
||||
int height = totalTiles / this->numTilesWide;
|
||||
QList<QRgb> palette = Tileset::getPalette(this->paletteId, this->primaryTileset, this->secondaryTileset);
|
||||
QImage image(this->numTilesWide * 16, height * 16, QImage::Format_RGBA8888);
|
||||
|
||||
QPainter painter(&image);
|
||||
for (uint16_t tile = 0; tile < totalTiles; tile++) {
|
||||
QImage tileImage;
|
||||
if (tile < primaryLength) {
|
||||
tileImage = getColoredTileImage(tile, this->primaryTileset, this->secondaryTileset, this->paletteId).scaled(16, 16);
|
||||
} else if (tile < Project::getNumTilesPrimary()) {
|
||||
tileImage = QImage(16, 16, QImage::Format_RGBA8888);
|
||||
tileImage.fill(palette.at(0));
|
||||
} else if (tile < Project::getNumTilesPrimary() + secondaryLength) {
|
||||
tileImage = getColoredTileImage(tile, this->primaryTileset, this->secondaryTileset, this->paletteId).scaled(16, 16);
|
||||
} else {
|
||||
tileImage = QImage(16, 16, QImage::Format_RGBA8888);
|
||||
QPainter painter(&tileImage);
|
||||
painter.fillRect(0, 0, 16, 16, palette.at(0));
|
||||
}
|
||||
|
||||
int y = tile / this->numTilesWide;
|
||||
int x = tile % this->numTilesWide;
|
||||
QPoint origin = QPoint(x * 16, y * 16);
|
||||
painter.drawImage(origin, tileImage.mirrored(this->xFlip, this->yFlip));
|
||||
}
|
||||
|
||||
painter.end();
|
||||
this->setPixmap(QPixmap::fromImage(image));
|
||||
this->drawSelection();
|
||||
}
|
||||
|
||||
void TilesetEditorTileSelector::select(uint16_t tile) {
|
||||
QPoint coords = this->getTileCoords(tile);
|
||||
SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0);
|
||||
this->updateSelectedTiles();
|
||||
emit selectedTilesChanged();
|
||||
}
|
||||
|
||||
void TilesetEditorTileSelector::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
this->primaryTileset = primaryTileset;
|
||||
this->secondaryTileset = secondaryTileset;
|
||||
this->draw();
|
||||
}
|
||||
|
||||
void TilesetEditorTileSelector::setPaletteId(int paletteId) {
|
||||
this->paletteId = paletteId;
|
||||
this->draw();
|
||||
}
|
||||
|
||||
void TilesetEditorTileSelector::setTileFlips(bool xFlip, bool yFlip) {
|
||||
this->xFlip = xFlip;
|
||||
this->yFlip = yFlip;
|
||||
this->draw();
|
||||
}
|
||||
|
||||
void TilesetEditorTileSelector::updateSelectedTiles() {
|
||||
this->selectedTiles.clear();
|
||||
QPoint origin = this->getSelectionStart();
|
||||
QPoint dimensions = this->getSelectionDimensions();
|
||||
for (int j = 0; j < dimensions.y(); j++) {
|
||||
for (int i = 0; i < dimensions.x(); i++) {
|
||||
uint16_t metatileId = this->getTileId(origin.x() + i, origin.y() + j);
|
||||
this->selectedTiles.append(metatileId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<uint16_t> TilesetEditorTileSelector::getSelectedTiles() {
|
||||
return this->selectedTiles;
|
||||
}
|
||||
|
||||
uint16_t TilesetEditorTileSelector::getTileId(int x, int y) {
|
||||
return static_cast<uint16_t>(y * this->numTilesWide + x);
|
||||
}
|
||||
|
||||
void TilesetEditorTileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) {
|
||||
SelectablePixmapItem::mousePressEvent(event);
|
||||
this->updateSelectedTiles();
|
||||
emit selectedTilesChanged();
|
||||
}
|
||||
|
||||
void TilesetEditorTileSelector::mouseMoveEvent(QGraphicsSceneMouseEvent *event) {
|
||||
SelectablePixmapItem::mouseMoveEvent(event);
|
||||
this->updateSelectedTiles();
|
||||
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
uint16_t tile = this->getTileId(pos.x(), pos.y());
|
||||
emit hoveredTileChanged(tile);
|
||||
emit selectedTilesChanged();
|
||||
}
|
||||
|
||||
void TilesetEditorTileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) {
|
||||
SelectablePixmapItem::mouseReleaseEvent(event);
|
||||
this->updateSelectedTiles();
|
||||
emit selectedTilesChanged();
|
||||
}
|
||||
|
||||
void TilesetEditorTileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) {
|
||||
QPoint pos = this->getCellPos(event->pos());
|
||||
uint16_t tile = this->getTileId(pos.x(), pos.y());
|
||||
emit this->hoveredTileChanged(tile);
|
||||
}
|
||||
|
||||
void TilesetEditorTileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) {
|
||||
emit this->hoveredTileCleared();
|
||||
}
|
||||
|
||||
QPoint TilesetEditorTileSelector::getTileCoords(uint16_t tile) {
|
||||
if (tile >= Project::getNumTilesTotal())
|
||||
{
|
||||
// Invalid tile.
|
||||
return QPoint(0, 0);
|
||||
}
|
||||
|
||||
return QPoint(tile % this->numTilesWide, tile / this->numTilesWide);
|
||||
}
|
116
tileset.cpp
|
@ -1,116 +0,0 @@
|
|||
#include "tileset.h"
|
||||
#include "project.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QImage>
|
||||
#include <QDebug>
|
||||
|
||||
Tileset::Tileset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Metatile::Metatile()
|
||||
{
|
||||
tiles = new QList<Tile>;
|
||||
}
|
||||
|
||||
QImage Metatile::getMetatileImage(int tile, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
QImage metatile_image(16, 16, QImage::Format_RGBA8888);
|
||||
|
||||
Metatile* metatile = Metatile::getMetatile(tile, primaryTileset, secondaryTileset);
|
||||
if (!metatile || !metatile->tiles) {
|
||||
metatile_image.fill(0xffffffff);
|
||||
return metatile_image;
|
||||
}
|
||||
|
||||
Tileset* blockTileset = Metatile::getBlockTileset(tile, primaryTileset, secondaryTileset);
|
||||
if (!blockTileset) {
|
||||
metatile_image.fill(0xffffffff);
|
||||
return metatile_image;
|
||||
}
|
||||
QList<QList<QRgb>> palettes = Metatile::getBlockPalettes(primaryTileset, secondaryTileset);
|
||||
|
||||
QPainter metatile_painter(&metatile_image);
|
||||
for (int layer = 0; layer < 2; layer++)
|
||||
for (int y = 0; y < 2; y++)
|
||||
for (int x = 0; x < 2; x++) {
|
||||
Tile tile_ = metatile->tiles->value((y * 2) + x + (layer * 4));
|
||||
QImage tile_image = Metatile::getMetatileTile(tile_.tile, primaryTileset, secondaryTileset);
|
||||
if (tile_image.isNull()) {
|
||||
// Some metatiles specify tiles that are outside the valid range.
|
||||
// These are treated as completely transparent, so they can be skipped without
|
||||
// being drawn.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Colorize the metatile tiles with its palette.
|
||||
if (tile_.palette < palettes.length()) {
|
||||
QList<QRgb> palette = palettes.value(tile_.palette);
|
||||
for (int j = 0; j < palette.length(); j++) {
|
||||
tile_image.setColor(j, palette.value(j));
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Tile is referring to invalid palette number: " << tile_.palette;
|
||||
}
|
||||
|
||||
// The top layer of the metatile has its first color displayed at transparent.
|
||||
if (layer > 0) {
|
||||
QColor color(tile_image.color(0));
|
||||
color.setAlpha(0);
|
||||
tile_image.setColor(0, color.rgba());
|
||||
}
|
||||
|
||||
QPoint origin = QPoint(x*8, y*8);
|
||||
metatile_painter.drawImage(origin, tile_image.mirrored(tile_.xflip == 1, tile_.yflip == 1));
|
||||
}
|
||||
metatile_painter.end();
|
||||
|
||||
return metatile_image;
|
||||
}
|
||||
|
||||
Metatile* Metatile::getMetatile(int index, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
Tileset *tileset = Metatile::getBlockTileset(index, primaryTileset, secondaryTileset);
|
||||
int local_index = Metatile::getBlockIndex(index);
|
||||
if (!tileset || !tileset->metatiles) {
|
||||
return nullptr;
|
||||
}
|
||||
Metatile *metatile = tileset->metatiles->value(local_index, nullptr);
|
||||
return metatile;
|
||||
}
|
||||
|
||||
QImage Metatile::getMetatileTile(int tile, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
Tileset *tileset = Metatile::getBlockTileset(tile, primaryTileset, secondaryTileset);
|
||||
int local_index = Metatile::getBlockIndex(tile);
|
||||
if (!tileset || !tileset->tiles) {
|
||||
return QImage();
|
||||
}
|
||||
return tileset->tiles->value(local_index, QImage());
|
||||
}
|
||||
|
||||
Tileset* Metatile::getBlockTileset(int metatile_index, Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
if (metatile_index < Project::getNumMetatilesPrimary()) {
|
||||
return primaryTileset;
|
||||
} else {
|
||||
return secondaryTileset;
|
||||
}
|
||||
}
|
||||
|
||||
int Metatile::getBlockIndex(int index) {
|
||||
if (index < Project::getNumMetatilesPrimary()) {
|
||||
return index;
|
||||
} else {
|
||||
return index - Project::getNumMetatilesPrimary();
|
||||
}
|
||||
}
|
||||
|
||||
QList<QList<QRgb>> Metatile::getBlockPalettes(Tileset *primaryTileset, Tileset *secondaryTileset) {
|
||||
QList<QList<QRgb>> palettes;
|
||||
for (int i = 0; i < Project::getNumPalettesPrimary(); i++) {
|
||||
palettes.append(primaryTileset->palettes->at(i));
|
||||
}
|
||||
for (int i = Project::getNumPalettesPrimary(); i < Project::getNumPalettesTotal(); i++) {
|
||||
palettes.append(secondaryTileset->palettes->at(i));
|
||||
}
|
||||
return palettes;
|
||||
}
|