Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Object Editor Events #153

Merged
merged 34 commits into from
Sep 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f042b1b
idk wtf im doing
Aug 17, 2020
1774a9f
fix events tree parents n stuffs
RobertBColton Aug 18, 2020
2735ed5
oopsie
RobertBColton Aug 18, 2020
ff34f35
clean up events other icon
RobertBColton Aug 18, 2020
75d464f
rename key press/release icons to match events.ey event name
RobertBColton Aug 18, 2020
c2f898f
new ui
Aug 18, 2020
4d0f95d
gut roberts code
Aug 19, 2020
95ed18e
still fuxed
Aug 19, 2020
fba3d34
robert quit hidin pls
Aug 20, 2020
84646f0
start stacked code editor
Aug 21, 2020
8a3af4e
why menu no work?
Aug 21, 2020
5db8454
ugh
Aug 21, 2020
d281e40
correct indexes
Aug 22, 2020
461d7a1
wip
Aug 23, 2020
6f94ae8
Update Dialogs/EventArgumentsDialog.cpp
RobertBColton Aug 23, 2020
3d6f2d5
Merge branch 'master' of https://github.com/enigma-dev/RadialGM into …
RobertBColton Aug 25, 2020
844d83f
fix the done code
RobertBColton Aug 25, 2020
9bc186e
ugh
Aug 26, 2020
36b3722
fix all that shit with identity proxy model
RobertBColton Aug 26, 2020
4cf51a8
WIP
Aug 28, 2020
afb3951
Merge branch 'master' of https://github.com/enigma-dev/RadialGM into …
RobertBColton Aug 28, 2020
bb87a2a
fix code editor embedding and auto slot connections
RobertBColton Aug 28, 2020
daed453
done but buggy
Aug 31, 2020
fe98a69
done but buggy
Aug 31, 2020
0e8efc3
readd splitter
RobertBColton Aug 31, 2020
f10d3be
Merge branch 'master' of https://github.com/enigma-dev/RadialGM into …
RobertBColton Aug 31, 2020
69bbd4e
return explicit invalid model index
RobertBColton Aug 31, 2020
3722673
Simplify event argument dialog done
RobertBColton Aug 31, 2020
42ca589
fundies wants fail safe in case arg is invalid so correct number of args
RobertBColton Aug 31, 2020
0d7c65c
Update Models/EventTypesListModel.h
RobertBColton Aug 31, 2020
a7d0438
Update EventTypesListModel.h
RobertBColton Aug 31, 2020
01fe6ac
Update Models/EventTypesListSortFilterProxyModel.cpp
RobertBColton Aug 31, 2020
bf78359
Merge branch 'master' of https://github.com/enigma-dev/RadialGM into …
RobertBColton Sep 1, 2020
27d2691
add event args dialog to cmakelists
RobertBColton Sep 1, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ set(RGM_SOURCES
Plugins/RGMPlugin.cpp
main.cpp
MainWindow.cpp
Dialogs/EventArgumentsDialog.cpp
Dialogs/PreferencesDialog.cpp
Dialogs/TimelineChangeMoment.cpp
Components/ArtManager.cpp
Expand All @@ -68,6 +69,9 @@ set(RGM_SOURCES
Models/ImmediateMapper.cpp
Models/ResourceModelMap.cpp
Models/TreeModel.cpp
Models/EventsListModel.cpp
Models/EventTypesListModel.cpp
Models/EventTypesListSortFilterProxyModel.cpp
Editors/ObjectEditor.cpp
Editors/PathEditor.cpp
Editors/CodeEditor.cpp
Expand Down Expand Up @@ -98,6 +102,7 @@ set(RGM_HEADERS
Plugins/RGMPlugin.h
MainWindow.h
main.h
Dialogs/EventArgumentsDialog.h
Dialogs/PreferencesDialog.h
Dialogs/PreferencesKeys.h
Dialogs/TimelineChangeMoment.h
Expand All @@ -118,6 +123,9 @@ set(RGM_HEADERS
Models/RepeatedMessageModel.h
Models/ProtoModel.h
Models/RepeatedModel.h
Models/EventsListModel.h
Models/EventTypesListModel.h
Models/EventTypesListSortFilterProxyModel.h
Editors/FontEditor.h
Editors/PathEditor.h
Editors/SpriteEditor.h
Expand Down Expand Up @@ -206,7 +214,7 @@ set(CompilerFlags
CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_RELWITHDEBINFO
)

foreach(CompilerFlag ${CompilerFlags})
message(STATUS " '${CompilerFlag}': ${${CompilerFlag}}")
endforeach()
Expand Down Expand Up @@ -319,7 +327,7 @@ file(TO_CMAKE_PATH ${VCPKG_ROOT} VCPKG_ROOT)
set(SEARCH_PATHS "${VCPKG_ROOT}/installed/x64-windows/bin/")
endif()
else()
set(LIBS "${CMAKE_INSTALL_PREFIX}/${CMAKE_SHARED_LIBRARY_PREFIX}EGM${CMAKE_SHARED_LIBRARY_SUFFIX}"
set(LIBS "${CMAKE_INSTALL_PREFIX}/${CMAKE_SHARED_LIBRARY_PREFIX}EGM${CMAKE_SHARED_LIBRARY_SUFFIX}"
"${CMAKE_INSTALL_PREFIX}/${CMAKE_SHARED_LIBRARY_PREFIX}Protocols${CMAKE_SHARED_LIBRARY_SUFFIX}"
"${CMAKE_INSTALL_PREFIX}/${CMAKE_SHARED_LIBRARY_PREFIX}ENIGMAShared${CMAKE_SHARED_LIBRARY_SUFFIX}")
endif()
Expand Down
105 changes: 105 additions & 0 deletions Dialogs/EventArgumentsDialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include "EventArgumentsDialog.h"
#include "Components/QMenuView.h"
#include "MainWindow.h"
#include "Models/TreeSortFilterProxyModel.h"

#include <QComboBox>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMetaProperty>
#include <QPushButton>
#include <QSpinBox>
#include <QToolButton>

EventArgumentsDialog::EventArgumentsDialog(QWidget *parent, const QStringList &arguments) : QDialog(parent) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are the arguments string and not QVariant or something. Why aren't we using real reflection over the event proto here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because they're strings... Arguments are "object", "integer" or "string"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what's in event data? Strings is what the shared event stuff gives you to work with? I don't know why Josh would do it that way and not give an enum or some other typed way of doing it.

QGridLayout *layout = new QGridLayout(this);

int row = 0;
for (const auto &arg : arguments) {
QLabel *name = new QLabel(this);
name->setText(arg);

QWidget *value;

if (arg == "integer") {
QSpinBox *integer = new QSpinBox(this);
integer->setMinimum(0);
value = integer;
layout->addWidget(value, row, 1);
} else if (arg == "string") {
QLineEdit *lineEdit = new QLineEdit(this);
lineEdit->setText(tr("MyCustomEvent"));
value = lineEdit;
layout->addWidget(value, row, 1);
} else if (arg == "object") {
QHBoxLayout *objLayout = new QHBoxLayout();
QToolButton *objButton = new QToolButton(this);

QMenuView *objMenu = new QMenuView(this);
TreeSortFilterProxyModel *treeProxy = new TreeSortFilterProxyModel(this);
treeProxy->SetFilterType(TreeNode::TypeCase::kObject);
treeProxy->setSourceModel(MainWindow::treeModel.get());
objMenu->setModel(treeProxy);
objButton->setMenu(objMenu);
objButton->setPopupMode(QToolButton::MenuButtonPopup);

QLineEdit *lineEdit = new QLineEdit(this);
lineEdit->setReadOnly(true);
QModelIndex firstObjIdx = treeProxy
->match(treeProxy->index(0, 0), TreeModel::UserRoles::TypeCaseRole,
TypeCase::kObject, 1, Qt::MatchRecursive)
.first();
QString firstObj = firstObjIdx.data(Qt::DisplayRole).toString();
objButton->setIcon(firstObjIdx.data(Qt::DecorationRole).value<QIcon>());
lineEdit->setText(firstObj);

connect(objMenu, &QMenuView::triggered, [=](const QModelIndex &index) {
lineEdit->setText(treeProxy->data(index, Qt::DisplayRole).toString());
objButton->setIcon(treeProxy->data(index, Qt::DecorationRole).value<QIcon>());
});

objLayout->addWidget(lineEdit);
objLayout->addWidget(objButton);

layout->addItem(objLayout, row, 1);

value = lineEdit;
} else {
QComboBox *combo = new QComboBox(this);
auto argList = MainWindow::GetEventData()->value_names_for_type(name->text().toStdString());
for (auto a : argList) {
combo->addItem(QString::fromStdString(a.first));
}
value = combo;
layout->addWidget(value, row, 1);
}

widgets_.append(value);

layout->addWidget(name, row, 0);
row++;
}

QDialogButtonBox *btn = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
layout->addWidget(btn, row, 1);
connect(btn, SIGNAL(accepted()), this, SLOT(accept()));
connect(btn, SIGNAL(rejected()), this, SLOT(reject()));

setWindowTitle(tr("Event arguments"));
}

const QStringList &EventArgumentsDialog::GetArguments() const { return arguments_; }

void EventArgumentsDialog::done(int r) {
for (const QWidget *w : widgets_) {
QVariant argument = w->metaObject()->userProperty().read(w);
QString argstr = "";
if (argument.isValid())
argstr = argument.toString();
arguments_.append(argstr);
}

QDialog::done(r);
}
21 changes: 21 additions & 0 deletions Dialogs/EventArgumentsDialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#ifndef EVENTARGUMENTSDIALOG_H
#define EVENTARGUMENTSDIALOG_H

#include "event_reader/event_parser.h"

#include <QDialog>

class EventArgumentsDialog : public QDialog
{
Q_OBJECT
public:
EventArgumentsDialog(QWidget* parent, const QStringList& arguments);
const QStringList& GetArguments() const;
void done(int r) override;

private:
QStringList arguments_;
QVector<QWidget*> widgets_;
};

#endif // EVENTARGUMENTSDIALOG_H
186 changes: 185 additions & 1 deletion Editors/ObjectEditor.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,194 @@
#include "ObjectEditor.h"
#include "Components/QMenuView.h"
#include "Dialogs/EventArgumentsDialog.h"
#include "MainWindow.h"
#include "Models/EventTypesListModel.h"
#include "Models/RepeatedMessageModel.h"
#include "Models/RepeatedStringModel.h"

#include "ui_ObjectEditor.h"

ObjectEditor::ObjectEditor(MessageModel* model, QWidget* parent) : BaseEditor(model, parent), _ui(new Ui::ObjectEditor) {
#include <QSplitter>

void ObjectEditor::BindEventMenu(QToolButton *btn, bool add) {
QMenuView *eventsMenu = new QMenuView(this);
eventsMenu->setModel(_eventsTypesModel);
eventsMenu->setToolTipsVisible(true);
btn->setMenu(eventsMenu);
connect(eventsMenu, &QMenuView::triggered, [=](const QModelIndex &index) { AddChangeFromMenuEvent(index, add); });
}

ObjectEditor::ObjectEditor(MessageModel *model, QWidget *parent)
: BaseEditor(model, parent), _ui(new Ui::ObjectEditor) {
_ui->setupUi(this);

_nodeMapper->addMapping(_ui->nameEdit, TreeNode::kNameFieldNumber);

connect(_ui->saveButton, &QAbstractButton::pressed, this, &BaseEditor::OnSave);

_eventsModel = new EventsListModel(MainWindow::GetEventData(), this);

EventTypesListModel *m = new EventTypesListModel(MainWindow::GetEventData(), this);
_eventsTypesModel = new EventTypesListSortFilterProxyModel(m);
_eventsTypesModel->setSourceModel(m);
_eventsTypesModel->sort(0);

BindEventMenu(_ui->addEventButton, true);
BindEventMenu(_ui->changeEventButton, false);

RebindSubModels();
}

ObjectEditor::~ObjectEditor() { delete _ui; }

void ObjectEditor::AddChangeEventHelper(const Object::EgmEvent &event, bool add) {
if (add) {
AddEvent(event);
} else {
int existingIdx = MapRowFrom(IndexOf(event));
int selectedIdx = MapRowTo(_ui->eventsList->selectionModel()->currentIndex().row());
if (existingIdx == -1 && selectedIdx != -1) {
ChangeEvent(selectedIdx, event, false);
} else
qDebug() << "Change event failed";
}
}

void ObjectEditor::AddChangeFromMenuEvent(const QModelIndex &index, bool add) {
QStringList args = _eventsTypesModel->data(index, EventTypesListModel::UserRoles::EventArgumentsRole).toStringList();
EventArgumentsDialog *dialog = nullptr;
if (args.size() > 0) {
dialog = new EventArgumentsDialog(this, args);
dialog->open();

connect(dialog, &QDialog::accepted, [=]() {
if (dialog->result() == QDialog::Accepted) {
Object::EgmEvent event;
event.set_id(
_eventsTypesModel->data(index, EventTypesListModel::UserRoles::EventBareIDRole).toString().toStdString());
for (const QString &arg : dialog->GetArguments()) {
std::string *s = event.add_arguments();
s->assign(arg.toStdString());
}

AddChangeEventHelper(event, add);
}
});
} else {
Object::EgmEvent event;
event.set_id(
_eventsTypesModel->data(index, EventTypesListModel::UserRoles::EventBareIDRole).toString().toStdString());
AddChangeEventHelper(event, add);
}
}

void ObjectEditor::RebindSubModels() {
_objectModel = _model->GetSubModel<MessageModel *>(TreeNode::kObjectFieldNumber);
_eventsModel->setSourceModel(_objectModel->GetSubModel<RepeatedMessageModel *>(Object::kEgmEventsFieldNumber));

_sortedEvents = new QSortFilterProxyModel(_eventsModel);
_sortedEvents->setSourceModel(_eventsModel);
_sortedEvents->sort(0);
_sortedEvents->setDynamicSortFilter(true);
_ui->eventsList->setModel(_sortedEvents);

connect(_ui->eventsList, &QAbstractItemView::clicked,
[=](const QModelIndex &index) { SetCurrentEditor(MapRowTo(index.row())); });

connect(_ui->deleteEventButton, &QToolButton::pressed, [=]() {
QModelIndex selection = _ui->eventsList->selectionModel()->currentIndex();
if (selection.row() != -1) RemoveEvent(MapRowTo(selection.row()));
});

for (int event = 0; event < _eventsModel->rowCount(); ++event) {
BindEventEditor(event);
}

SetCurrentEditor(MapRowFrom(0));
CheckDisableButtons();

BaseEditor::RebindSubModels();
}

void ObjectEditor::CheckDisableButtons() {
bool hasEvents = _sortedEvents->rowCount() > 0;
_ui->changeEventButton->setDisabled(!hasEvents);
_ui->deleteEventButton->setDisabled(!hasEvents);
_ui->codeEditor->setDisabled(!hasEvents);
if (!hasEvents) _ui->eventLineEdit->setText("");
}

void ObjectEditor::AddEvent(Object::EgmEvent event) {
RepeatedMessageModel *eventsModel = _objectModel->GetSubModel<RepeatedMessageModel *>(Object::kEgmEventsFieldNumber);
int idx = eventsModel->rowCount();

if (IndexOf(event) == -1) {
bool insert = eventsModel->insertRow(idx);
if (insert) {
BindEventEditor(idx);
ChangeEvent(idx, event);
}
} else
qDebug() << "Event already exists";
}

void ObjectEditor::ChangeEvent(int idx, Object::EgmEvent event, bool changeCode) {
RepeatedMessageModel *eventsModel = _objectModel->GetSubModel<RepeatedMessageModel *>(Object::kEgmEventsFieldNumber);

eventsModel->SetData(QString::fromStdString(event.id()), idx, Object::EgmEvent::kIdFieldNumber);

if (changeCode) eventsModel->SetData(QString::fromStdString(event.code()), idx, Object::EgmEvent::kCodeFieldNumber);

RepeatedStringModel *argsModel = eventsModel->GetSubModel<MessageModel *>(idx)->GetSubModel<RepeatedStringModel *>(
Object::EgmEvent::kArgumentsFieldNumber);

size_t argc = 0;
argsModel->removeRows(0, argsModel->rowCount()); // clear old arguments
if (event.arguments_size() > 0) {
argsModel->insertRows(argsModel->rowCount(), event.arguments_size());
for (const auto &arg : event.arguments()) {
argsModel->SetData(QString::fromStdString(arg), argc++);
}
}

SetCurrentEditor(idx);
CheckDisableButtons();
}

void ObjectEditor::RemoveEvent(int idx) {
RepeatedMessageModel *eventsModel = _objectModel->GetSubModel<RepeatedMessageModel *>(Object::kEgmEventsFieldNumber);
eventsModel->removeRow(idx);
_ui->codeEditor->RemoveCodeWidget(idx);
SetCurrentEditor(MapRowFrom(0));
CheckDisableButtons();
}

int ObjectEditor::IndexOf(Object::EgmEvent event) {
std::vector<std::string> args(event.arguments().begin(), event.arguments().end());
Event e = MainWindow::GetEventData()->get_event(event.id(), args);
for (int i = 0; i < _eventsModel->rowCount(); ++i) {
if (_eventsModel->data(_eventsModel->index(i, 0)).toString() == QString::fromStdString(e.HumanName())) return i;
}
return -1;
}

void ObjectEditor::BindEventEditor(int idx) {
RepeatedMessageModel *eventsModel = _objectModel->GetSubModel<RepeatedMessageModel *>(Object::kEgmEventsFieldNumber);
CodeWidget *codeWidget = _ui->codeEditor->AddCodeWidget();
ModelMapper *mapper(new ModelMapper(eventsModel->GetSubModel<MessageModel *>(idx), this));
mapper->addMapping(codeWidget, Object::EgmEvent::kCodeFieldNumber);
mapper->toFirst();
}

void ObjectEditor::SetCurrentEditor(int idx) {
if (idx < _sortedEvents->rowCount()) {
_ui->codeEditor->SetCurrentIndex(idx);
_ui->eventLineEdit->setText(_eventsModel->data(_eventsModel->index(idx, 0)).toString());
_ui->eventsList->selectionModel()->select(_sortedEvents->index(MapRowFrom(idx), 0),
QItemSelectionModel::QItemSelectionModel::ClearAndSelect);
}
}

int ObjectEditor::MapRowTo(int row) { return _sortedEvents->mapToSource(_sortedEvents->index(row, 0)).row(); }

int ObjectEditor::MapRowFrom(int row) { return _sortedEvents->mapFromSource(_eventsModel->index(row, 0)).row(); }
Loading