Merge branch 'master' into handle-collision
This commit is contained in:
commit
e9ac799ed2
9 changed files with 153 additions and 14 deletions
|
@ -12,7 +12,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
|||
|
||||
### Added
|
||||
- Add Copy/Paste for metatiles in the Tileset Editor.
|
||||
- Add new features to the scripting API, including the ability to set overlay opacity, get/set map header properties, read tile pixel data, and set blocks or metatile attributes using a raw value.
|
||||
- Add new features to the scripting API, including the ability to display message boxes and user input windows, set overlay opacity, get/set map header properties, read tile pixel data, and set blocks or metatile attributes using a raw value.
|
||||
- Add button to copy the full metatile label to the clipboard in the Tileset Editor.
|
||||
- Add option to not open the most recent project on launch.
|
||||
- Add color picker to palette editor for taking colors from the screen.
|
||||
|
@ -25,6 +25,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
|||
- The wild encounter editor is automatically disabled if the encounter JSON data cannot be read
|
||||
- Metatiles are always rendered accurately with 3 layers, and the unused layer is not assumed to be transparent.
|
||||
- `object_event_graphics_info.h` can now be parsed correctly if it uses structs with attributes.
|
||||
- The selection is no longer reset when pasting events. The newly pasted events are selected instead.
|
||||
- Palette editor ui is updated a bit to allow hex and rgb value input.
|
||||
|
||||
### Fixed
|
||||
|
@ -34,6 +35,7 @@ The **"Breaking Changes"** listed below are changes that have been made in the d
|
|||
- Fix selected space not updating while painting in Collision view.
|
||||
- Fix collision values of 2 or 3 not rendering properly.
|
||||
- Fix the map music dropdown being empty when importing a map from Advance Map.
|
||||
- Fix object events added by pasting ignoring the map event limit.
|
||||
- Fixed a bug where saving the tileset editor would reselect the main editor's first selected metatile.
|
||||
- Fix crashes / unexpected behavior if certain scripting API functions are given invalid palette or tile numbers.
|
||||
|
||||
|
|
|
@ -1255,9 +1255,74 @@ These are some miscellaneous functions that can be very useful when building cus
|
|||
|
||||
:param string message: the message to log
|
||||
|
||||
|
||||
.. js:function:: map.error(message)
|
||||
|
||||
Logs a message to the Porymap log file with the prefix ``[ERROR]``.
|
||||
|
||||
:param string message: the message to log
|
||||
|
||||
.. js:function:: map.showMessage(text, informativeText, detailedText)
|
||||
|
||||
Displays a message box with an "Information" icon and an ``OK`` button. Execution stops while the window is open.
|
||||
|
||||
:param string text: the main message text
|
||||
:param string informativeText: smaller text below the main message. Defaults to ``""``
|
||||
:param string detailedText: text hidden behind a "Show Details" box. Defaults to ``""``
|
||||
|
||||
.. js:function:: map.showWarning(text, informativeText, detailedText)
|
||||
|
||||
Displays a message box with a "Warning" icon and an ``OK`` button. Execution stops while the window is open.
|
||||
|
||||
:param string text: the main message text
|
||||
:param string informativeText: smaller text below the main message. Defaults to ``""``
|
||||
:param string detailedText: text hidden behind a "Show Details" box. Defaults to ``""``
|
||||
|
||||
.. js:function:: map.showError(text, informativeText, detailedText)
|
||||
|
||||
Displays a message box with a "Critical" icon and an ``OK`` button. Execution stops while the window is open.
|
||||
|
||||
:param string text: the main message text
|
||||
:param string informativeText: smaller text below the main message. Defaults to ``""``
|
||||
:param string detailedText: text hidden behind a "Show Details" box. Defaults to ``""``
|
||||
|
||||
.. js:function:: map.showQuestion(text, informativeText, detailedText)
|
||||
|
||||
Displays a message box with a "Question" icon and a ``Yes`` and a ``No`` button. Execution stops while the window is open.
|
||||
|
||||
:param string text: the main message text
|
||||
:param string informativeText: smaller text below the main message. Defaults to ``""``
|
||||
:param string detailedText: text hidden behind a "Show Details" box. Defaults to ``""``
|
||||
:returns boolean: ``true`` if ``Yes`` was selected, ``false`` if ``No`` was selected or if the window was closed without selection
|
||||
|
||||
.. js:function:: map.getInputText(title, label, default)
|
||||
|
||||
Displays a text input dialog with an ``OK`` and a ``Cancel`` button. Execution stops while the window is open.
|
||||
|
||||
:param string title: the text in the window title bar
|
||||
:param string label: the text adjacent to the input entry area
|
||||
:param string default: the text in the input entry area when the window is opened. Defaults to ``""``
|
||||
:returns {input, ok}: ``input`` will be the input text and ``ok`` will be ``true`` if ``OK`` was selected. ``input`` will be ``""`` and ``ok`` will be ``false`` if ``Cancel`` was selected or if the window was closed without selection.
|
||||
|
||||
.. js:function:: map.getInputNumber(title, label, default, min, max, decimals, step)
|
||||
|
||||
Displays a number input dialog with an ``OK`` and a ``Cancel`` button. Execution stops while the window is open.
|
||||
|
||||
:param string title: the text in the window title bar
|
||||
:param string label: the text adjacent to the input entry area
|
||||
:param number default: the number in the input entry area when the window is opened. Defaults to ``0``
|
||||
:param number min: the minimum allowable input value. Defaults to ``-2147483648``
|
||||
:param number max: the maximum allowable input value. Defaults to ``2147483647``
|
||||
:param number decimals: the number of decimals used for the input number. Defaults to ``0``
|
||||
:param number step: the increment by which the input number will change when the spinner is used. Defaults to ``1``
|
||||
:returns {input, ok}: ``input`` will be the input number and ``ok`` will be ``true`` if ``OK`` was selected. ``input`` will be ``default`` and ``ok`` will be ``false`` if ``Cancel`` was selected or if the window was closed without selection.
|
||||
|
||||
.. js:function:: map.getInputItem(title, label, items, default, editable)
|
||||
|
||||
Displays a text input dialog with an items dropdown and an ``OK`` and a ``Cancel`` button. Execution stops while the window is open.
|
||||
|
||||
:param string title: the text in the window title bar
|
||||
:param string label: the text adjacent to the input entry area
|
||||
:param array items: an array of text items that will populate the dropdown
|
||||
:param number default: the index of the item to select by default. Defaults to ``0``
|
||||
:param boolean editable: whether the user is allowed to enter their own text instead. Defaults to ``false``
|
||||
:returns {input, ok}: ``input`` will be the input text and ``ok`` will be ``true`` if ``OK`` was selected. ``input`` will be the text of the item at ``default`` and ``ok`` will be ``false`` if ``Cancel`` was selected or if the window was closed without selection.
|
||||
|
|
|
@ -151,6 +151,7 @@ public:
|
|||
void shouldReselectEvents();
|
||||
void scaleMapView(int);
|
||||
void openInTextEditor(const QString &path, int lineNum = 0) const;
|
||||
bool eventLimitReached(QString event_type);
|
||||
|
||||
public slots:
|
||||
void openMapScripts() const;
|
||||
|
@ -176,7 +177,6 @@ private:
|
|||
void updateEncounterFields(EncounterFields newFields);
|
||||
QString getMovementPermissionText(uint16_t collision, uint16_t elevation);
|
||||
QString getMetatileDisplayMessage(uint16_t metatileId);
|
||||
bool eventLimitReached(Map *, QString);
|
||||
bool startDetachedProcess(const QString &command,
|
||||
const QString &workingDirectory = QString(),
|
||||
qint64 *pid = nullptr) const;
|
||||
|
|
|
@ -150,6 +150,14 @@ public:
|
|||
Q_INVOKABLE void log(QString message);
|
||||
Q_INVOKABLE void warn(QString message);
|
||||
Q_INVOKABLE void error(QString message);
|
||||
void runMessageBox(QString text, QString informativeText, QString detailedText, QMessageBox::Icon icon);
|
||||
Q_INVOKABLE void showMessage(QString text, QString informativeText = "", QString detailedText = "");
|
||||
Q_INVOKABLE void showWarning(QString text, QString informativeText = "", QString detailedText = "");
|
||||
Q_INVOKABLE void showError(QString text, QString informativeText = "", QString detailedText = "");
|
||||
Q_INVOKABLE bool showQuestion(QString text, QString informativeText = "", QString detailedText = "");
|
||||
Q_INVOKABLE QJSValue getInputText(QString title, QString label, QString defaultValue = "");
|
||||
Q_INVOKABLE QJSValue getInputNumber(QString title, QString label, double defaultValue = 0, double min = INT_MIN, double max = INT_MAX, int decimals = 0, double step = 1);
|
||||
Q_INVOKABLE QJSValue getInputItem(QString title, QString label, QStringList items, int defaultValue = 0, bool editable = false);
|
||||
Q_INVOKABLE QList<int> getMetatileLayerOrder();
|
||||
Q_INVOKABLE void setMetatileLayerOrder(QList<int> order);
|
||||
Q_INVOKABLE QList<float> getMetatileLayerOpacity();
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
static QJSValue position(int x, int y);
|
||||
static QJSEngine *getEngine();
|
||||
static QImage getImage(QString filepath);
|
||||
static QJSValue dialogInput(QJSValue input, bool selectedOk);
|
||||
static void init(MainWindow *mainWindow);
|
||||
static void registerAction(QString functionName, QString actionName);
|
||||
static int numRegisteredActions();
|
||||
|
|
|
@ -2031,7 +2031,7 @@ void Editor::duplicateSelectedEvents() {
|
|||
for (int i = 0; i < selected_events->length(); i++) {
|
||||
Event *original = selected_events->at(i)->event;
|
||||
QString eventType = original->get("event_type");
|
||||
if (eventLimitReached(map, eventType)) {
|
||||
if (eventLimitReached(eventType)) {
|
||||
logWarn(QString("Skipping duplication, the map limit for events of type '%1' has been reached.").arg(eventType));
|
||||
continue;
|
||||
}
|
||||
|
@ -2045,7 +2045,7 @@ void Editor::duplicateSelectedEvents() {
|
|||
}
|
||||
|
||||
DraggablePixmapItem* Editor::addNewEvent(QString event_type) {
|
||||
if (project && map && !event_type.isEmpty() && !eventLimitReached(map, event_type)) {
|
||||
if (project && map && !event_type.isEmpty() && !eventLimitReached(event_type)) {
|
||||
Event *event = Event::createNewEvent(event_type, map->name, project);
|
||||
event->put("map_name", map->name);
|
||||
if (event_type == EventType::HealLocation) {
|
||||
|
@ -2061,7 +2061,7 @@ DraggablePixmapItem* Editor::addNewEvent(QString event_type) {
|
|||
}
|
||||
|
||||
// Currently only object events have an explicit limit
|
||||
bool Editor::eventLimitReached(Map *map, QString event_type)
|
||||
bool Editor::eventLimitReached(QString event_type)
|
||||
{
|
||||
if (project && map && !event_type.isEmpty()) {
|
||||
if (Event::typeToGroup(event_type) == EventGroup::Object)
|
||||
|
|
|
@ -1520,6 +1520,7 @@ void MainWindow::copy() {
|
|||
|
||||
if (type == EventType::HealLocation) {
|
||||
// no copy on heal locations
|
||||
logWarn(QString("Copying events of type '%1' is not allowed.").arg(type));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1531,11 +1532,11 @@ void MainWindow::copy() {
|
|||
|
||||
eventsArray.append(eventJson);
|
||||
}
|
||||
|
||||
copyObject["events"] = eventsArray;
|
||||
setClipboardData(copyObject);
|
||||
logInfo("Copied currently selected events to clipboard");
|
||||
|
||||
if (!eventsArray.isEmpty()) {
|
||||
copyObject["events"] = eventsArray;
|
||||
setClipboardData(copyObject);
|
||||
logInfo("Copied currently selected events to clipboard");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1620,6 +1621,11 @@ void MainWindow::paste() {
|
|||
// paste the event to the map
|
||||
QString type = event["event_type"].toString();
|
||||
|
||||
if (editor->eventLimitReached(type)) {
|
||||
logWarn(QString("Skipping paste, the map limit for events of type '%1' has been reached.").arg(type));
|
||||
continue;
|
||||
}
|
||||
|
||||
Event *pasteEvent = Event::createNewEvent(type, editor->map->name, editor->project);
|
||||
|
||||
for (auto key : event.toObject().keys())
|
||||
|
@ -1651,9 +1657,10 @@ void MainWindow::paste() {
|
|||
newEvents.append(pasteEvent);
|
||||
}
|
||||
|
||||
editor->map->editHistory.push(new EventPaste(this->editor, editor->map, newEvents));
|
||||
updateObjects();
|
||||
|
||||
if (!newEvents.isEmpty()) {
|
||||
updateObjects();
|
||||
editor->map->editHistory.push(new EventPaste(this->editor, editor->map, newEvents));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -793,6 +793,55 @@ void MainWindow::error(QString message) {
|
|||
logError(message);
|
||||
}
|
||||
|
||||
void MainWindow::runMessageBox(QString text, QString informativeText, QString detailedText, QMessageBox::Icon icon) {
|
||||
QMessageBox messageBox(this);
|
||||
messageBox.setText(text);
|
||||
messageBox.setInformativeText(informativeText);
|
||||
messageBox.setDetailedText(detailedText);
|
||||
messageBox.setIcon(icon);
|
||||
messageBox.exec();
|
||||
}
|
||||
|
||||
void MainWindow::showMessage(QString text, QString informativeText, QString detailedText) {
|
||||
this->runMessageBox(text, informativeText, detailedText, QMessageBox::Information);
|
||||
}
|
||||
|
||||
void MainWindow::showWarning(QString text, QString informativeText, QString detailedText) {
|
||||
this->runMessageBox(text, informativeText, detailedText, QMessageBox::Warning);
|
||||
}
|
||||
|
||||
void MainWindow::showError(QString text, QString informativeText, QString detailedText) {
|
||||
this->runMessageBox(text, informativeText, detailedText, QMessageBox::Critical);
|
||||
}
|
||||
|
||||
bool MainWindow::showQuestion(QString text, QString informativeText, QString detailedText) {
|
||||
QMessageBox messageBox(this);
|
||||
messageBox.setText(text);
|
||||
messageBox.setInformativeText(informativeText);
|
||||
messageBox.setDetailedText(detailedText);
|
||||
messageBox.setIcon(QMessageBox::Question);
|
||||
messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
return messageBox.exec() == QMessageBox::Yes;
|
||||
}
|
||||
|
||||
QJSValue MainWindow::getInputText(QString title, QString label, QString defaultValue) {
|
||||
bool ok;
|
||||
QString input = QInputDialog::getText(this, title, label, QLineEdit::Normal, defaultValue, &ok);
|
||||
return Scripting::dialogInput(input, ok);
|
||||
}
|
||||
|
||||
QJSValue MainWindow::getInputNumber(QString title, QString label, double defaultValue, double min, double max, int decimals, double step) {
|
||||
bool ok;
|
||||
double input = QInputDialog::getDouble(this, title, label, defaultValue, min, max, decimals, &ok, Qt::WindowFlags(), step);
|
||||
return Scripting::dialogInput(input, ok);
|
||||
}
|
||||
|
||||
QJSValue MainWindow::getInputItem(QString title, QString label, QStringList items, int defaultValue, bool editable) {
|
||||
bool ok;
|
||||
QString input = QInputDialog::getItem(this, title, label, items, defaultValue, editable, &ok);
|
||||
return Scripting::dialogInput(input, ok);
|
||||
}
|
||||
|
||||
QList<int> MainWindow::getMetatileLayerOrder() {
|
||||
if (!this->editor || !this->editor->map)
|
||||
return QList<int>();
|
||||
|
|
|
@ -262,6 +262,13 @@ QJSValue Scripting::fromTile(Tile tile) {
|
|||
return obj;
|
||||
}
|
||||
|
||||
QJSValue Scripting::dialogInput(QJSValue input, bool selectedOk) {
|
||||
QJSValue obj = instance->engine->newObject();
|
||||
obj.setProperty("input", input);
|
||||
obj.setProperty("ok", selectedOk);
|
||||
return obj;
|
||||
}
|
||||
|
||||
QJSEngine *Scripting::getEngine() {
|
||||
return instance->engine;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue