From ef49b46c37c3d1922db7afcbfd7a715a250a5b4c Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Sat, 23 Jul 2022 18:18:54 +0300 Subject: [PATCH] Add Emote preview (#774) * Add an emote preview which pops up from right click context menu * rename action names to "preanim/idle/talk" * Improve emote preview window * Preview no longer ignores offsets No longer override stylesheets Add "Preview Selected" option to the dropdown * bruh * Fix "set play once" being ignored when a (c) emote is loaded * Remove useless comments * Implement Salanto suggestions Co-authored-by: stonedDiscord --- include/aoemotepreview.h | 32 +++++++++++++++ include/courtroom.h | 9 +++++ src/aoemotepreview.cpp | 44 ++++++++++++++++++++ src/courtroom.cpp | 3 +- src/emotes.cpp | 86 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 171 insertions(+), 3 deletions(-) create mode 100644 include/aoemotepreview.h create mode 100644 src/aoemotepreview.cpp diff --git a/include/aoemotepreview.h b/include/aoemotepreview.h new file mode 100644 index 0000000..315371b --- /dev/null +++ b/include/aoemotepreview.h @@ -0,0 +1,32 @@ +#ifndef AOEMOTEPREVIEW_H +#define AOEMOTEPREVIEW_H + +#include "aolayer.h" +#include + +class AOEmotePreview : public QWidget +{ + Q_OBJECT +public: + AOEmotePreview(QWidget *parent = nullptr, + AOApplication *p_ao_app = nullptr); + + void set_widgets(); + void play(QString emote, QString char_name, bool flipped = false, int self_offset = 0, int self_offset_v = 0); +private: + AOApplication *ao_app; + QWidget *ui_viewport; + BackgroundLayer *ui_vp_background; + SplashLayer *ui_vp_speedlines; + CharLayer *ui_vp_player_char; + BackgroundLayer *ui_vp_desk; + + QLabel *ui_size_label; + + QString m_emote = ""; + QString m_char = ""; +protected: + void resizeEvent(QResizeEvent *); +}; + +#endif // AOEMOTEPREVIEW_H diff --git a/include/courtroom.h b/include/courtroom.h index 43cecf3..eee84a6 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -24,6 +24,7 @@ #include "lobby.h" #include "scrolltext.h" #include "eventfilters.h" +#include "aoemotepreview.h" #include #include @@ -690,6 +691,9 @@ private: AOButton *ui_emote_left; AOButton *ui_emote_right; + QMenu *emote_menu; + AOEmotePreview *emote_preview; + QComboBox *ui_emote_dropdown; QComboBox *ui_pos_dropdown; AOButton *ui_pos_remove; @@ -920,6 +924,8 @@ private slots: void on_custom_objection_clicked(); void show_custom_objection_menu(const QPoint &pos); + void show_emote_menu(const QPoint &pos); + void on_realization_clicked(); void on_screenshake_clicked(); @@ -999,6 +1005,9 @@ private slots: // Proceed to parse the oldest chatmessage and remove it from the stack void chatmessage_dequeue(); + + void preview_emote(QString emote); + void update_emote_preview(); }; #endif // COURTROOM_H diff --git a/src/aoemotepreview.cpp b/src/aoemotepreview.cpp new file mode 100644 index 0000000..5afeebd --- /dev/null +++ b/src/aoemotepreview.cpp @@ -0,0 +1,44 @@ +#include "aoemotepreview.h" + +AOEmotePreview::AOEmotePreview(QWidget *parent, AOApplication *p_ao_app) : QWidget(parent) +{ + ao_app = p_ao_app; + + ui_viewport = new QWidget(this); + ui_vp_player_char = new CharLayer(ui_viewport, ao_app); + ui_vp_player_char->setObjectName("ui_vp_player_char"); + ui_vp_player_char->masked = false; + ui_size_label = new QLabel(this); + ui_size_label->setObjectName("ui_size_label"); + setWindowFlag(Qt::WindowMinMaxButtonsHint, false); + setWindowFlag(Qt::Tool); + this->resize(256, 192); +} + +void AOEmotePreview::set_widgets() +{ + ui_viewport->resize(this->width(), this->height()); + + ui_vp_player_char->move_and_center(0, 0); + ui_vp_player_char->combo_resize(ui_viewport->width(), ui_viewport->height()); + + ui_size_label->setText(QString::number(this->width()) + "x" + QString::number(this->height())); +} + +void AOEmotePreview::play(QString emote, QString char_name, bool flipped, int self_offset, int self_offset_v) +{ + ui_vp_player_char->stop(); + ui_vp_player_char->set_flipped(flipped); + ui_vp_player_char->move_and_center(ui_viewport->width() * self_offset / 100, ui_viewport->height() * self_offset_v / 100); + ui_vp_player_char->load_image(emote, char_name, 0, false); + ui_vp_player_char->set_play_once(false); + m_emote = emote; + m_char = char_name; + setWindowTitle(char_name + ": " + emote); +} + +void AOEmotePreview::resizeEvent(QResizeEvent *) +{ + set_widgets(); + ui_vp_player_char->load_image(m_emote, m_char, 0, false); +} diff --git a/src/courtroom.cpp b/src/courtroom.cpp index e76ba41..60d2948 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -209,8 +209,6 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_music_search->setPlaceholderText(tr("Search")); ui_music_search->setObjectName("ui_music_search"); - initialize_emotes(); - ui_pos_dropdown = new QComboBox(this); ui_pos_dropdown->view()->setTextElideMode(Qt::ElideLeft); ui_pos_dropdown->setObjectName("ui_pos_dropdown"); @@ -404,6 +402,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_evidence_button = new AOButton(this, ao_app); ui_evidence_button->setObjectName("ui_evidence_button"); + initialize_emotes(); initialize_evidence(); construct_char_select(); diff --git a/src/emotes.cpp b/src/emotes.cpp index 669aa17..69d1185 100644 --- a/src/emotes.cpp +++ b/src/emotes.cpp @@ -13,8 +13,15 @@ void Courtroom::initialize_emotes() ui_emote_right->setObjectName("ui_emote_right"); ui_emote_dropdown = new QComboBox(this); + ui_emote_dropdown->setContextMenuPolicy(Qt::CustomContextMenu); ui_emote_dropdown->setObjectName("ui_emote_dropdown"); + emote_menu = new QMenu(this); + emote_menu->setObjectName("ui_emote_menu"); + + emote_preview = new AOEmotePreview(this, ao_app); + emote_preview->setObjectName("ui_emote_preview"); + connect(ui_emote_left, &AOButton::clicked, this, &Courtroom::on_emote_left_clicked); connect(ui_emote_right, &AOButton::clicked, this, @@ -22,6 +29,16 @@ void Courtroom::initialize_emotes() connect(ui_emote_dropdown, QOverload::of(&QComboBox::activated), this, &Courtroom::on_emote_dropdown_changed); + connect(ui_emote_dropdown, + &AOEmoteButton::customContextMenuRequested, this, + &Courtroom::show_emote_menu); + + connect(ui_pre, QOverload::of(&QCheckBox::stateChanged), this, &Courtroom::update_emote_preview); + connect(ui_flip, &AOButton::clicked, this, &Courtroom::update_emote_preview); + connect(ui_pair_offset_spinbox, QOverload::of(&QSpinBox::valueChanged), this, + &Courtroom::update_emote_preview); + connect(ui_pair_vert_offset_spinbox, QOverload::of(&QSpinBox::valueChanged), this, + &Courtroom::update_emote_preview); } void Courtroom::refresh_emotes() @@ -76,9 +93,14 @@ void Courtroom::refresh_emotes() f_emote->set_id(n); + f_emote->setContextMenuPolicy(Qt::CustomContextMenu); connect(f_emote, &AOEmoteButton::emote_clicked, this, &Courtroom::on_emote_clicked); + connect(f_emote, + &AOEmoteButton::customContextMenuRequested, this, + &Courtroom::show_emote_menu); + ++x_mod_count; if (x_mod_count == emote_columns) { @@ -185,15 +207,77 @@ void Courtroom::select_emote(int p_id) } ui_emote_dropdown->setCurrentIndex(current_emote); - + update_emote_preview(); ui_ic_chat_message->setFocus(); } +void Courtroom::update_emote_preview() { + if (!emote_preview->isVisible()) { + return; + } + QString emote; + QString pre = ao_app->get_pre_emote(current_char, current_emote); + if (ui_pre->isChecked() && !pre.isEmpty() && pre != "-") { + emote = pre; + } + else { + emote = "(b)" + ao_app->get_emote(current_char, current_emote); + } + preview_emote(emote); +} + void Courtroom::on_emote_clicked(int p_id) { select_emote(p_id + max_emotes_on_page * current_emote_page); } +void Courtroom::show_emote_menu(const QPoint &pos) +{ + QWidget* button = qobject_cast(sender()); + int id = current_emote; + if (qobject_cast(button)) { + AOEmoteButton* emote_button = qobject_cast(sender()); + id = emote_button->get_id(); + } + int emote_num = id + max_emotes_on_page * current_emote_page; + emote_menu->clear(); + emote_menu->setDefaultAction(emote_menu->addAction("Preview Selected", this, [=]{ + emote_preview->show(); + emote_preview->raise(); + emote_preview->set_widgets(); + update_emote_preview(); + } + )); + QString prefix = ""; + QString f_pre = ao_app->get_pre_emote(current_char, emote_num); + if (!f_pre.isEmpty() && f_pre != "-") { + emote_menu->addAction("Preview pre: " + f_pre, this, [=]{ preview_emote(f_pre); }); + } + + QString f_emote = ao_app->get_emote(current_char, emote_num); + if (!f_emote.isEmpty()) { + emote_menu->addAction("Preview idle: " + f_emote, this, [=]{ preview_emote("(a)" + f_emote); }); + emote_menu->addAction("Preview talk: " + f_emote, this, [=]{ preview_emote("(b)" + f_emote); }); + QStringList c_paths = { + ao_app->get_image_suffix(ao_app->get_character_path(current_char, "(c)" + f_emote)), + ao_app->get_image_suffix(ao_app->get_character_path(current_char, "(c)/" + f_emote)) + }; + // if there is a (c) animation + if (file_exists(ui_vp_player_char->find_image(c_paths))) { + emote_menu->addAction("Preview segway: " + f_emote, this, [=]{ preview_emote("(c)" + f_emote); }); + } + } + emote_menu->popup(button->mapToGlobal(pos)); +} + +void Courtroom::preview_emote(QString f_emote) +{ + emote_preview->show(); + emote_preview->raise(); + emote_preview->set_widgets(); + emote_preview->play(f_emote, current_char, ui_flip->isChecked(), ui_pair_offset_spinbox->value(), ui_pair_vert_offset_spinbox->value()); +} + void Courtroom::on_emote_left_clicked() { --current_emote_page;