Bläddra i källkod

Changed units and races raw-pointers to std::shared_ptr, completed recruitment scene rewriting

Ivan Arkhipov 6 år sedan
förälder
incheckning
598cfd84fa

BIN
assets/common/cursors/click.gif


BIN
assets/common/cursors/simple.gif


BIN
assets/common/window/frame.png


+ 5 - 6
client.pro

@@ -135,6 +135,7 @@ HEADERS +=                                      \
                                                 \
     include/gui/guiscenemanager.h               \
     include/gui/scene.h                         \
+    include/gui/buttoneventlistener.h           \
                                                 \
     include/hotseatgame/gamemanager.h           \
     include/hotseatgame/raceicon.h              \
@@ -154,11 +155,10 @@ HEADERS +=                                      \
     ui/hotseat_prebattle/prebattlescene.h       \
     ui/hotseat_recruitment/recruitmentscene.h   \
     ui/loading_form/loadingform.h               \
-    ui/main_menu/mainmenu.h \
-    ui/main_menu/mainmenubackground.h \
-    include/gui/buttoneventlistener.h \
-    ui/hotseat_recruitment/iconhint.h \
-    ui/dialog_form/dialogform.h \
+    ui/main_menu/mainmenu.h                     \
+    ui/main_menu/mainmenubackground.h           \
+    ui/hotseat_recruitment/iconhint.h           \
+    ui/dialog_form/dialogform.h                 \
     ui/about_us/aboutus.h
 
 FORMS +=                                        \
@@ -169,7 +169,6 @@ FORMS +=                                        \
     ui/loading_form/loadingform.ui              \
     ui/main_menu/mainmenu.ui \
     ui/main_menu/mainmenubackground.ui \
-    ui/hotseat_recruitment/iconhint.ui \
     ui/dialog_form/dialogform.ui \
     ui/about_us/aboutus.ui
 

+ 5 - 4
include/abstractfactory.h

@@ -2,12 +2,13 @@
 #include <iostream>
 #include <string>
 #include <map>
+#include <memory>
 
 template <class Base, typename CreatorParam>
 class AbstractCreator {
 public:
 	virtual ~AbstractCreator() {}
-    virtual Base* create(const CreatorParam &id) const = 0;
+    virtual std::shared_ptr<Base> create(const CreatorParam &id) const = 0;
 };
 
 template <class ObjectClass, class Base, typename CreatorParam>
@@ -15,8 +16,8 @@ class Creator : public AbstractCreator<Base, CreatorParam> {
 public:
     Creator() {}
 	virtual ~Creator() {}
-    Base* create(const CreatorParam &params) const {
-        return dynamic_cast<Base*>(new ObjectClass(params));
+    std::shared_ptr<Base> create(const CreatorParam &params) const {
+        return std::static_pointer_cast<Base>(std::make_shared<ObjectClass>(params));
 	}
 };
 
@@ -40,7 +41,7 @@ public:
 	}
 
     template <typename CreatorParam>
-    Base* createObject(const IdType &idClass, const CreatorParam &parameters) {
+    std::shared_ptr<Base> createObject(const IdType &idClass, const CreatorParam &parameters) {
         return factory_[idClass]->create(parameters);
 	}
 

+ 2 - 0
include/gui/guiscenemanager.h

@@ -27,6 +27,8 @@ public slots:
 
     bool changeScene(QString scene_name, QString args = "");
 
+    Scene *getScene(QString scene_name);
+
     bool show(QString scene_name);
 
     bool hide(QString scene_name);

+ 10 - 10
include/player.h

@@ -16,7 +16,7 @@ class ObjectFactory;
 
 class Player {
     struct unit_comparator {
-        bool operator() (const Unit* lhs, const Unit* rhs) const {
+        bool operator() (const std::shared_ptr<Unit> lhs, const std::shared_ptr<Unit> rhs) const {
             if (rhs == nullptr)
                 return true;
             if (lhs->getUnitBaseClassId() != rhs->getUnitBaseClassId())
@@ -42,24 +42,24 @@ public:
         return player_name_;
     }
 
-    const std::multiset<Unit*, unit_comparator>& getUnits() {
+    const std::multiset<std::shared_ptr<Unit>, unit_comparator>& getUnits() {
         return units_;
     }
 
-    std::vector<Unit*> getUnitsAsVector() {
-        std::vector<Unit*> result;
+    std::vector<std::shared_ptr<Unit>> getUnitsAsVector() {
+        std::vector<std::shared_ptr<Unit>> result;
         for (auto unit: units_)
             result.push_back(unit);
         return result;
     }
 
-    void addUnit(Unit *a) {
+    void addUnit(std::shared_ptr<Unit> a) {
         if (units_.size() >= 10)
             return;
         units_.insert(a);
     }
 
-    void deleteUnit(Unit *a) {
+    void deleteUnit(std::shared_ptr<Unit> a) {
         qDebug() << "deleting unit " << a->getUnitName();
         auto unit = units_.find(a);
         if (unit != units_.end())
@@ -70,11 +70,11 @@ public:
         units_.clear();
     }
 
-    Race* getRace() {
+    std::shared_ptr<Race> getRace() {
         return race_;
     }
 
-    void setRace(Race* race) {
+    void setRace(std::shared_ptr<Race> race) {
         race_ = race;
     }
 
@@ -84,8 +84,8 @@ public slots:
 
 private:
     QString player_name_;
-    std::multiset<Unit*, unit_comparator> units_;
-    Race* race_;
+    std::multiset<std::shared_ptr<Unit>, unit_comparator> units_;
+    std::shared_ptr<Race> race_;
 };
 
 #endif // INCLUDEPLAYER_H

+ 3 - 3
include/race.h

@@ -17,10 +17,10 @@ class Race : public QObject
 public:
     explicit Race(QString race_name, QObject *parent = nullptr);
 
-    Unit* createUnit(QString unit_name);
+    std::shared_ptr<Unit> createUnit(QString unit_name);
 
     const std::vector<QString> &getAvailableUnitsList();
-    const std::vector<Unit*> &getAllUnitsList();
+    const std::vector<std::shared_ptr<Unit>> &getAllUnitsList();
 
     QString getRaceId();
     QString getRaceName();
@@ -34,7 +34,7 @@ private:
     QString race_descr_;
     ObjectFactory<Unit, QString> units_factory_;
     std::vector<QString> available_units_list_;
-    std::vector<Unit*> all_units_list_;
+    std::vector<std::shared_ptr<Unit>> all_units_list_;
 
 signals:
 

+ 3 - 2
include/racemanager.h

@@ -4,6 +4,7 @@
 #include <QObject>
 
 #include <vector>
+#include <memory>
 
 class Race;
 
@@ -18,12 +19,12 @@ public:
         return instance;
     }
 
-    Race* getRace(QString race_name);
+    std::shared_ptr<Race> getRace(QString race_name);
     const std::vector<QString>& getAvailableRacesList();
 
 private:
     std::vector<QString> available_races_;
-    std::map<QString, Race*> races_;
+    std::map<QString, std::shared_ptr<Race>> races_;
 
 signals:
 

+ 1 - 0
res/common_data.qrc

@@ -37,5 +37,6 @@
         <file>../assets/common/window/thick_opaque-border-topleft.png</file>
         <file>../assets/common/window/thick_opaque-border-topright.png</file>
         <file>../assets/common/team_logo.jpg</file>
+        <file>../assets/common/window/frame.png</file>
     </qresource>
 </RCC>

+ 1 - 1
source/gui/buttoneventlistener.cpp

@@ -28,7 +28,7 @@ bool ButtonEventListener::eventFilter(QObject * watched, QEvent * event) {
         return false;
     }
 
-    if (event->type() == QEvent::MouseButtonPress) {
+    if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) {
         SoundEngine::getInstance().playAsync("qrc:/assets/common/buttons/button_click.mp3");
         return false;
     }

+ 9 - 3
source/gui/guiscenemanager.cpp

@@ -1,5 +1,7 @@
 #include "gui/guiscenemanager.h"
 
+#include "ui/about_us/aboutus.h"
+#include "ui/dialog_form/dialogform.h"
 #include "ui/main_menu/mainmenu.h"
 #include "ui/main_menu/mainmenubackground.h"
 
@@ -7,7 +9,7 @@
 #include "ui/hotseat_intro/playervsplayerintro.h"
 #include "ui/hotseat_prebattle/prebattlescene.h"
 #include "ui/hotseat_game/hotseatgame.h"
-#include "ui/about_us/aboutus.h"
+
 
 #include <QResource>
 #include <QApplication>
@@ -44,6 +46,7 @@ GuiSceneManager::GuiSceneManager(QObject *parent) : QObject(parent) {
     registerScene("prebattle", new PreBattleScene(window_));
     registerScene("hotseatgame", new HotSeatGame(window_));
     registerScene("about_us", new AboutUs(window_));
+    registerScene("dialog_form", new DialogForm(window_));
 
     QTimer::singleShot(100, [=] {
         changeScene("main_menu");
@@ -52,7 +55,6 @@ GuiSceneManager::GuiSceneManager(QObject *parent) : QObject(parent) {
 
 GuiSceneManager::~GuiSceneManager() {}
 
-
 bool GuiSceneManager::registerScene(QString scene_name, Scene* scene) {
     if (scene_name == "none")
         return false;
@@ -85,6 +87,11 @@ bool GuiSceneManager::changeScene(QString scene_name, QString args) {
     return true;
 }
 
+Scene *GuiSceneManager::getScene(QString scene_name)
+{
+    return scenes_[scene_name];
+}
+
 bool GuiSceneManager::show(QString scene_name)
 {
     if (scenes_.count(scene_name) == 0)
@@ -95,7 +102,6 @@ bool GuiSceneManager::show(QString scene_name)
     return true;
 }
 
-
 bool GuiSceneManager::hide(QString scene_name)
 {
     if (scenes_.count(scene_name) == 0)

+ 2 - 2
source/race.cpp

@@ -70,7 +70,7 @@ QString Race::getRaceDescr() {
     return race_descr_;
 }
 
-Unit* Race::createUnit(QString unit_name) {
+std::shared_ptr<Unit> Race::createUnit(QString unit_name) {
     qDebug() << unit_name;
     QFile file(":/assets/units/" + race_id_ + "/" + unit_name + "/baseclass.txt");
     file.open(QIODevice::ReadOnly);
@@ -85,6 +85,6 @@ const std::vector<QString>& Race::getAvailableUnitsList() {
     return available_units_list_;
 }
 
-const std::vector<Unit*> &Race::getAllUnitsList() {
+const std::vector<std::shared_ptr<Unit>> &Race::getAllUnitsList() {
     return all_units_list_;
 }

+ 3 - 3
source/racemanager.cpp

@@ -23,20 +23,20 @@ RaceManager::RaceManager(QObject *parent) : QObject(parent)
             continue;
         //qDebug() << available_races_;
         available_races_.push_back(race_name);
-        races_[race_name] = new Race(race_name);
+        races_[race_name] = std::make_shared<Race>(race_name);
         race_name = in.readLine();
     }
 
     if (race_name.length() >= 2) {
         //qDebug() << available_races_;
         available_races_.push_back(race_name);
-        races_[race_name] = new Race(race_name);
+        races_[race_name] = std::make_shared<Race>(race_name);
         race_name = in.readLine();
     }
 
 }
 
-Race* RaceManager::getRace(QString race_name) {
+std::shared_ptr<Race> RaceManager::getRace(QString race_name) {
     if (races_.count(race_name) == 0) {
         qWarning() << "Error! Not found race with name " << race_name;
         return nullptr;

+ 1 - 0
source/units/unit.cpp

@@ -61,6 +61,7 @@ void Unit::loadUnitTraits(QString unit_folder) {
     activity_points_ = rand();
     attack_cost_ = rand();
     attack_range_ = rand();
+    cost_ = rand() % 300;
 }
 
 void Unit::loadUnitIcon(QString unit_folder) {

+ 42 - 1
ui/dialog_form/dialogform.cpp

@@ -2,14 +2,55 @@
 #include "ui_dialogform.h"
 
 DialogForm::DialogForm(QWidget *parent) :
-    QWidget(parent),
+    Scene(parent),
     ui(new Ui::DialogForm)
 {
+    ok = false;
     setWindowModality(Qt::ApplicationModal);
     ui->setupUi(this);
+    raise();
+}
+
+void DialogForm::exec()
+{
+    raise();
+    QEventLoop loop;
+    connect(ui->ok_button, &QPushButton::clicked, &loop, &QEventLoop::quit);
+    connect(ui->cancel_button, &QPushButton::clicked, &loop, &QEventLoop::quit);
+    loop.exec();
+}
+
+bool DialogForm::isOk()
+{
+    return ok;
+}
+
+void DialogForm::setTitle(QString title)
+{
+    ui->title->setText(title);
+}
+
+void DialogForm::setText(QString text)
+{
+    ui->text->setText(text);
+}
+
+void DialogForm::setShowCancel(bool show)
+{
+    show ? ui->cancel_button->show() : ui->cancel_button->hide();
 }
 
 DialogForm::~DialogForm()
 {
     delete ui;
 }
+
+void DialogForm::on_cancel_button_clicked()
+{
+    ok = false;
+}
+
+void DialogForm::on_ok_button_clicked()
+{
+    ok = true;
+}

+ 19 - 1
ui/dialog_form/dialogform.h

@@ -2,20 +2,38 @@
 #define DIALOGFORM_H
 
 #include <QWidget>
+#include "gui/scene.h"
 
 namespace Ui {
 class DialogForm;
 }
 
-class DialogForm : public QWidget
+class DialogForm : public Scene
 {
     Q_OBJECT
 
 public:
     explicit DialogForm(QWidget *parent = 0);
+
+    void exec();
+
+    bool isOk();
+
+    void setTitle(QString title);
+
+    void setText(QString text);
+
+    void setShowCancel(bool show);
+
     ~DialogForm();
 
+private slots:
+    void on_cancel_button_clicked();
+
+    void on_ok_button_clicked();
+
 private:
+    bool ok;
     Ui::DialogForm *ui;
 };
 

+ 5 - 2
ui/dialog_form/dialogform.ui

@@ -195,7 +195,10 @@ color: rgb(255, 255, 149);</string>
              </widget>
             </item>
             <item row="2" column="0">
-             <widget class="QPushButton" name="pushButton">
+             <widget class="QPushButton" name="cancel_button">
+              <property name="enabled">
+               <bool>true</bool>
+              </property>
               <property name="styleSheet">
                <string notr="true">font: 10pt &quot;D-determination (RUS BY LYAJKA)&quot;;
 color: rgb(255, 255, 255);</string>
@@ -219,7 +222,7 @@ color: rgb(255, 255, 255);</string>
              </spacer>
             </item>
             <item row="2" column="2">
-             <widget class="QPushButton" name="pushButton_2">
+             <widget class="QPushButton" name="ok_button">
               <property name="styleSheet">
                <string notr="true">font: 10pt &quot;D-determination (RUS BY LYAJKA)&quot;;
 color: rgb(255, 255, 255);</string>

+ 23 - 9
ui/hotseat_recruitment/iconhint.cpp

@@ -1,28 +1,42 @@
 #include "iconhint.h"
-#include "ui_iconhint.h"
 
 #include <QDebug>
 
 IconHint::IconHint(QWidget *parent) :
-    QWidget(parent),
-    ui(new Ui::IconHint)
+    QLabel(parent)
 {
     setObjectName("hint");
-    ui->setupUi(this);
+    setStyleSheet("border-image: url(:/assets/common/window/frame.png);\nbackground-color: rgb(0, 0, 0);\ncolor: rgb(255, 255, 255);");
+    setIndent(10);
+    setWordWrap(true);
+    setAlignment(Qt::AlignCenter);
+    //setScaledContents(true);
     show();
+    raise();
+    title_ = "Title";
+    text_  = "Text";
 }
 
-void IconHint::setTitle(QString title)
+void IconHint::setHintTitle(const QString &title)
 {
-    ui->title->setText(title);
+    title_ = title;
+    updateText();
 }
 
-void IconHint::setText(QString text)
+void IconHint::setHintText(const QString &text)
 {
-    ui->text->setText(text);
+    text_ = text;
+    updateText();
 }
 
 IconHint::~IconHint()
 {
-    delete ui;
+}
+
+void IconHint::updateText()
+{
+    setText("<p style=\"font-size:12pt\">" + title_ + "</p><p>" + text_ + "</p>");
+    adjustSize();
+    resize(width() + 30, height() + 30);
+    setIndent(15);
 }

+ 9 - 9
ui/hotseat_recruitment/iconhint.h

@@ -1,27 +1,27 @@
 #ifndef ICONHINT_H
 #define ICONHINT_H
 
-#include <QWidget>
+#include <QLabel>
 
-namespace Ui {
-class IconHint;
-}
-
-class IconHint : public QWidget
+class IconHint : public QLabel
 {
     Q_OBJECT
 
 public:
     explicit IconHint(QWidget *parent = 0);
 
-    void setTitle(QString title);
+    void setHintTitle(const QString &title);
 
-    void setText(QString text);
+    void setHintText(const QString &text);
 
     ~IconHint();
 
 private:
-    Ui::IconHint *ui;
+    void updateText();
+
+private:
+    QString title_;
+    QString text_;
 };
 
 #endif // ICONHINT_H

+ 0 - 309
ui/hotseat_recruitment/iconhint.ui

@@ -1,309 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>IconHint</class>
- <widget class="QWidget" name="IconHint">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>172</width>
-    <height>128</height>
-   </rect>
-  </property>
-  <property name="sizePolicy">
-   <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
-    <horstretch>0</horstretch>
-    <verstretch>0</verstretch>
-   </sizepolicy>
-  </property>
-  <property name="maximumSize">
-   <size>
-    <width>320</width>
-    <height>16777215</height>
-   </size>
-  </property>
-  <property name="windowTitle">
-   <string>Form</string>
-  </property>
-  <layout class="QGridLayout" name="gridLayout">
-   <item row="0" column="0">
-    <widget class="QWidget" name="widget" native="true">
-     <property name="sizePolicy">
-      <sizepolicy hsizetype="Fixed" vsizetype="Minimum">
-       <horstretch>0</horstretch>
-       <verstretch>99</verstretch>
-      </sizepolicy>
-     </property>
-     <property name="maximumSize">
-      <size>
-       <width>150</width>
-       <height>16777215</height>
-      </size>
-     </property>
-     <layout class="QGridLayout" name="gridLayout_2">
-      <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>
-      <property name="spacing">
-       <number>0</number>
-      </property>
-      <item row="0" column="0">
-       <widget class="QWidget" name="topleft_border" native="true">
-        <property name="minimumSize">
-         <size>
-          <width>8</width>
-          <height>8</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>8</width>
-          <height>8</height>
-         </size>
-        </property>
-        <property name="styleSheet">
-         <string notr="true">background-image: url(:/assets/common/window/opaque-border-topleft.png);</string>
-        </property>
-       </widget>
-      </item>
-      <item row="0" column="1">
-       <widget class="QWidget" name="top_border" native="true">
-        <property name="minimumSize">
-         <size>
-          <width>0</width>
-          <height>8</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>16777215</width>
-          <height>8</height>
-         </size>
-        </property>
-        <property name="styleSheet">
-         <string notr="true">background-image: url(:/assets/common/window/opaque-border-top.png);</string>
-        </property>
-       </widget>
-      </item>
-      <item row="0" column="2">
-       <widget class="QWidget" name="topright_border" native="true">
-        <property name="minimumSize">
-         <size>
-          <width>8</width>
-          <height>8</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>8</width>
-          <height>8</height>
-         </size>
-        </property>
-        <property name="styleSheet">
-         <string notr="true">background-image: url(:/assets/common/window/opaque-border-topright.png);</string>
-        </property>
-       </widget>
-      </item>
-      <item row="1" column="0">
-       <widget class="QWidget" name="left_border" native="true">
-        <property name="minimumSize">
-         <size>
-          <width>8</width>
-          <height>0</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>8</width>
-          <height>16777215</height>
-         </size>
-        </property>
-        <property name="styleSheet">
-         <string notr="true">background-image: url(:/assets/common/window/opaque-border-left.png);</string>
-        </property>
-       </widget>
-      </item>
-      <item row="1" column="2">
-       <widget class="QWidget" name="right_border" native="true">
-        <property name="minimumSize">
-         <size>
-          <width>8</width>
-          <height>0</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>8</width>
-          <height>16777215</height>
-         </size>
-        </property>
-        <property name="styleSheet">
-         <string notr="true">background-image: url(:/assets/common/window/opaque-border-right.png);</string>
-        </property>
-       </widget>
-      </item>
-      <item row="2" column="0">
-       <widget class="QWidget" name="botleft_border" native="true">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
-          <horstretch>8</horstretch>
-          <verstretch>8</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="minimumSize">
-         <size>
-          <width>8</width>
-          <height>8</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>8</width>
-          <height>8</height>
-         </size>
-        </property>
-        <property name="styleSheet">
-         <string notr="true">background-image: url(:/assets/common/window/opaque-border-botleft.png);</string>
-        </property>
-       </widget>
-      </item>
-      <item row="2" column="1">
-       <widget class="QWidget" name="bottom_border" native="true">
-        <property name="minimumSize">
-         <size>
-          <width>0</width>
-          <height>8</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>16777215</width>
-          <height>8</height>
-         </size>
-        </property>
-        <property name="styleSheet">
-         <string notr="true">background-image: url(:/assets/common/window/opaque-border-bottom.png);</string>
-        </property>
-       </widget>
-      </item>
-      <item row="2" column="2">
-       <widget class="QWidget" name="botright_border" native="true">
-        <property name="minimumSize">
-         <size>
-          <width>8</width>
-          <height>8</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>8</width>
-          <height>8</height>
-         </size>
-        </property>
-        <property name="styleSheet">
-         <string notr="true">background-image: url(:/assets/common/window/opaque-border-botright.png);</string>
-        </property>
-       </widget>
-      </item>
-      <item row="1" column="1">
-       <widget class="QWidget" name="widget_2" native="true">
-        <property name="styleSheet">
-         <string notr="true">background-color: rgb(0, 0, 0);</string>
-        </property>
-        <layout class="QVBoxLayout" name="verticalLayout">
-         <property name="spacing">
-          <number>0</number>
-         </property>
-         <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="QLabel" name="title">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
-             <horstretch>0</horstretch>
-             <verstretch>0</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="styleSheet">
-            <string notr="true">font: 10pt &quot;D-determination (RUS BY LYAJKA)&quot;;
-color: rgb(255, 255, 255);</string>
-           </property>
-           <property name="text">
-            <string>Заголовок</string>
-           </property>
-           <property name="scaledContents">
-            <bool>true</bool>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignCenter</set>
-           </property>
-           <property name="wordWrap">
-            <bool>true</bool>
-           </property>
-          </widget>
-         </item>
-         <item>
-          <widget class="QLabel" name="text">
-           <property name="sizePolicy">
-            <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
-             <horstretch>1</horstretch>
-             <verstretch>1</verstretch>
-            </sizepolicy>
-           </property>
-           <property name="contextMenuPolicy">
-            <enum>Qt::DefaultContextMenu</enum>
-           </property>
-           <property name="styleSheet">
-            <string notr="true">font: 8pt &quot;D-determination (RUS BY LYAJKA)&quot;;
-color: rgb(255, 255, 255);</string>
-           </property>
-           <property name="lineWidth">
-            <number>0</number>
-           </property>
-           <property name="text">
-            <string>вапроилорптавыварлпdfghjklmj,hgtf rsd' djyekwsad hlck sreuf efuh qeurf qke qiuywgrfqiurygf qurg fquye gfqeyr fgiqeyr gfqiuyer fiyqerg fuqeyg fyuiqe</string>
-           </property>
-           <property name="scaledContents">
-            <bool>true</bool>
-           </property>
-           <property name="alignment">
-            <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
-           </property>
-           <property name="wordWrap">
-            <bool>true</bool>
-           </property>
-           <property name="margin">
-            <number>3</number>
-           </property>
-          </widget>
-         </item>
-        </layout>
-       </widget>
-      </item>
-     </layout>
-    </widget>
-   </item>
-  </layout>
- </widget>
- <resources/>
- <connections/>
-</ui>

+ 263 - 36
ui/hotseat_recruitment/recruitmentscene.cpp

@@ -1,17 +1,23 @@
 #include "ui/hotseat_recruitment/recruitmentscene.h"
+#include "ui/dialog_form/dialogform.h"
+#include "ui_recruitmentscene.h"
+
 #include "gui/guiscenemanager.h"
 #include "gui/scene.h"
-#include "playermanager.h"
+
 #include "player.h"
-#include "racemanager.h"
+#include "playermanager.h"
 #include "race.h"
+#include "racemanager.h"
+
 #include "soundengine.h"
 
-#include <ui_recruitmentscene.h>
+
 #include <QString>
 #include <QStringList>
 #include <QMovie>
 #include <QDebug>
+#include <QMouseEvent>
 
 #include <vector>
 
@@ -43,17 +49,17 @@ RecruitmentScene::RecruitmentScene(QWidget *parent)
     // Создаём обработчик событий нажатия иконок юнитов
     unit_icon_watcher = new UnitIconEventListener(this, this);
 
-//    for (unsigned i = 0; i < AVAILABLE_UNIT_NUMBER; i++) {
-//        QLabel* unit_icon = findChild<QLabel*>("available_unit_" + QString::number(i));
-//        if (unit_icon)
-//            unit_icon->installEventFilter(unit_icon_watcher);
-//    }
+    for (unsigned i = 0; i < AVAILABLE_UNIT_NUMBER; i++) {
+        QLabel* unit_icon = findChild<QLabel*>("available_unit_" + QString::number(i));
+        if (unit_icon)
+            unit_icon->installEventFilter(unit_icon_watcher);
+    }
 
-//    for (unsigned i = 0; i < MAX_PARTY_SIZE; i++) {
-//        QLabel* unit_icon = findChild<QLabel*>("chosen_unit_" + QString::number(i));
-//        if (unit_icon)
-//            unit_icon->installEventFilter(unit_icon_watcher);
-//    }
+    for (unsigned i = 0; i < MAX_PARTY_SIZE; i++) {
+        QLabel* unit_icon = findChild<QLabel*>("chosen_unit_" + QString::number(i));
+        if (unit_icon)
+            unit_icon->installEventFilter(unit_icon_watcher);
+    }
 }
 
 RecruitmentScene::~RecruitmentScene()
@@ -92,15 +98,49 @@ void RecruitmentScene::init() {
         "<img src=\":/assets/units/" + race_name + "/icon.png\" width=\"100\" height=\"100\"/>"
     );
 
-    setMoney(current_money_);
+    updateMoney();
+
+    DialogForm* form = qobject_cast<DialogForm*>(GuiSceneManager::getInstance().getScene("dialog_form"));
+    if (!form)
+        return;
+    form->setTitle("Найм юнитов для игрока: " + current_player_->getPlayerName());
+    form->setShowCancel(false);
+    form->setText("Игрок \"" + current_player_->getPlayerName() + "\", пришло время вам набрать свой отряд!");
+    GuiSceneManager::getInstance().show("dialog_form");
+    form->exec();
+    GuiSceneManager::getInstance().hide("dialog_form");
+}
+
+Player *RecruitmentScene::getActivePlayer()
+{
+    return current_player_;
+}
+
+bool RecruitmentScene::buyUnit(std::shared_ptr<Unit> unit)
+{
+    if (!unit || unit->getCost() > current_money_ || current_player_->getUnits().size() >= MAX_PARTY_SIZE)
+        return false;
+    current_player_->addUnit(unit);
+    current_money_ -= unit->getCost();
+    updateMoney();
+    showChosenUnits();
+    return true;
+}
+
+bool RecruitmentScene::removeUnit(std::shared_ptr<Unit> unit) {
+    current_money_ += unit->getCost();
+    updateMoney();
+    current_player_->deleteUnit(unit);
+    showChosenUnits();
+    return true;
 }
 
 void RecruitmentScene::initAvailableRaces() {
     auto races = RaceManager::getInstance().getAvailableRacesList();
-    race_ids_.clear();
+    races_list.clear();
     for (unsigned i = 0; i < std::min(RACES_NUMBER, races.size()); i++) {
         QString race_name = races[i];
-        race_ids_.push_back(race_name);
+        races_list.push_back(RaceManager::getInstance().getRace(race_name));
         QLabel* race_icon = findChild<QLabel*>("available_race_" + QString::number(i));
         if (race_icon)
             race_icon->setText("<img src=\":/assets/units/" + race_name + "/icon.png\" width=\"66\" height=\"66\"/>");
@@ -109,11 +149,11 @@ void RecruitmentScene::initAvailableRaces() {
 
 void RecruitmentScene::initAvailableUnits() {
     auto units_list = current_player_->getRace()->getAllUnitsList();
-    available_unit_ids.clear();
+    available_units_list.clear();
     for (unsigned i = 0; i < std::min(AVAILABLE_UNIT_NUMBER, units_list.size()); i++) {
         QString race_name = current_player_->getRace()->getRaceId();
         QString unit_name = units_list[i]->getUnitId();
-        available_unit_ids.push_back(unit_name);
+        available_units_list.push_back(units_list[i]);
 
         QLabel* unit_icon = findChild<QLabel*>("available_unit_" + QString::number(i));
         qDebug() << "<img src=\":/assets/units/" + race_name + "/" + unit_name + "/icon.png\" width=\"58\" height=\"58\"/>";
@@ -123,44 +163,57 @@ void RecruitmentScene::initAvailableUnits() {
 }
 
 void RecruitmentScene::showChosenUnits() {
-    int counter = 0;
-    chosen_unit_ids.clear();
+    unsigned counter = 0;
+    chosen_units_list.clear();
 
     for (auto unit : current_player_->getUnits()) {
         if (counter >= MAX_PARTY_SIZE)
             break;
         QString unit_name = unit->getUnitId();
-        chosen_unit_ids.push_back(unit_name);
+        chosen_units_list.push_back(unit);
         QString race_name = current_player_->getRace()->getRaceId();
         QLabel* unit_icon = findChild<QLabel*>("chosen_unit_" + QString::number(counter));
-        if (unit_icon)
+        if (unit_icon) {
             unit_icon->setText("<img src=\":/assets/units/" + race_name + "/" + unit_name + "/icon.png\" width=\"58\" height=\"58\"/>");
+            unit_icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_default.png);\nbackground-color: rgb(253, 234, 168);");
+        }
         counter++;
     }
 
 
-    for (int i = counter; i < MAX_PARTY_SIZE; i++) {
+    for (unsigned i = counter; i < MAX_PARTY_SIZE; i++) {
         QLabel* unit_icon = findChild<QLabel*>("chosen_unit_" + QString::number(i));
-        if (unit_icon)
+        if (unit_icon) {
             unit_icon->setText("");
+            unit_icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_default.png);\nbackground-color: rgb(253, 234, 168);");
+        }
     }
-
 }
 
-void RecruitmentScene::changeRace(Race *race) {
+void RecruitmentScene::changeRace(std::shared_ptr<Race> race) {
     current_player_->clearUnits();
     current_player_->setRace(race);
     init();
 }
 
-void RecruitmentScene::setMoney(int money_) {
-   ui->available_money_text_->setText("Монеты: " + QString::number(money_));
+void RecruitmentScene::updateMoney() {
+   ui->available_money_text_->setText("Монеты: " + QString::number(current_money_));
 }
 
 void RecruitmentScene::on_back_button_clicked() {
     GuiSceneManager::getInstance().changeScene("pvp_intro");
 }
 
+void RecruitmentScene::on_complete_choice_button_clicked()
+{
+    qDebug() << "Exiting recruit army scene with player_id =" << current_player_id_;
+    if (current_player_id_ == 0) {
+        qDebug() << "Changing to 1";
+        GuiSceneManager::getInstance().changeScene("recruit_army", "1|" + QString::number(available_money_));
+    } else {
+        GuiSceneManager::getInstance().changeScene("prebattle");
+    }
+}
 
 RaceIconEventListener::RaceIconEventListener(QObject *parent, RecruitmentScene* scene)
     : QObject(parent)
@@ -174,19 +227,25 @@ bool RaceIconEventListener::eventFilter(QObject *watched, QEvent *event) {
     }
 
     if (event->type() == QEvent::Enter) {
-        IconHint *hint = new IconHint(scene_);
-        unsigned race_id_number = icon->objectName().mid(icon->objectName().lastIndexOf('_') + 1).toInt();
-        QString race_name = RaceManager::getInstance().getRace(scene_->race_ids_[race_id_number])->getRaceName();
-        hint->setTitle("Раса \"" + race_name + "\"");
 
         if (icon->objectName() != "chosen_race_image_") {
             icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_hover.png);\nbackground-color: rgb(253, 234, 168);");
+
             SoundEngine::getInstance().playAsync("qrc:/assets/common/buttons/button_hover.mp3");
-            hint->setText("ЛКМ - сменить расу\nПКМ - открыть окно информации");
+
+            unsigned race_id_number = icon->objectName().mid(icon->objectName().lastIndexOf('_') + 1).toInt();
+
+            IconHint *hint = new IconHint(scene_);
+            hint->setHintText("ЛКМ - сменить расу<br>ПКМ - открыть окно информации");
+            hint->setHintTitle("Раса \"" + scene_->races_list[race_id_number]->getRaceName() + "\"");
+            hint->move(icon->mapToGlobal(QPoint(0,0)).x() + icon->width() / 2 - hint->width() / 2, icon->mapToGlobal(QPoint(0,0)).y() + icon->height() + 2);
         } else {
-            hint->setText("ПКМ - открыть окно информации");
+            QString race_name = scene_->getActivePlayer()->getRace()->getRaceName();
+            IconHint *hint = new IconHint(scene_);
+            hint->setHintTitle("Раса \"" + race_name + "\"");
+            hint->setHintText("ПКМ - открыть окно информации");
+            hint->move(icon->mapToGlobal(QPoint(0,0)).x() + icon->width() / 2 - hint->width() / 2, icon->mapToGlobal(QPoint(0,0)).y() + icon->height() + 2);
         }
-        hint->move(icon->mapToGlobal(QPoint(0,0)).x() + icon->width() / 2 - hint->width() / 2, icon->mapToGlobal(QPoint(0,0)).y() + icon->height() + 2);
         return false;
     }
 
@@ -206,8 +265,54 @@ bool RaceIconEventListener::eventFilter(QObject *watched, QEvent *event) {
         return false;
     }
 
-    if (event->type() == QEvent::MouseButtonDblClick) {
+    if (event->type() == QEvent::MouseButtonPress) {
+        if (icon->objectName() != "chosen_race_image_")
+            icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_active.png);\nbackground-color: rgb(253, 234, 168);");
+        SoundEngine::getInstance().playAsync("qrc:/assets/common/buttons/button_click.mp3");
+    }
+
+    if (event->type() == QEvent::MouseButtonRelease) {
+        if (icon->objectName() != "chosen_race_image_")
+            icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_hover.png);\nbackground-color: rgb(253, 234, 168);");
+
+        QMouseEvent *evt = dynamic_cast<QMouseEvent*>(event);
+
+        if (evt->button() == Qt::LeftButton) {
+            if (icon->objectName() == "chosen_race_image_")
+                return false;
+
+            GuiSceneManager::getInstance().show("dialog_form");
+
+            DialogForm* form = qobject_cast<DialogForm*>(GuiSceneManager::getInstance().getScene("dialog_form"));
+
+            if (!form)
+                return false;
+            form->setTitle("Смена расы");
+            form->setShowCancel(true);
+            form->setText("Вы уверены, что хотите сменить расу? В этом случае все нанятые и улучшенные юниты исчезнут, а число монет будет восстановлено");
+            form->exec();
+
+            if (form->isOk()) {
+                unsigned race_id_number = icon->objectName().mid(icon->objectName().lastIndexOf('_') + 1).toInt();
+                scene_->changeRace(scene_->races_list[race_id_number]);
+            }
+
+            GuiSceneManager::getInstance().hide("dialog_form");
+        }
 
+        if (evt->button() == Qt::RightButton) {
+            DialogForm* form = qobject_cast<DialogForm*>(GuiSceneManager::getInstance().getScene("dialog_form"));
+            if (!form)
+                return false;
+            form->setTitle("Окно информации о расе");
+            form->setShowCancel(false);
+            form->setText("Окно информации о расе пока недоступно, извините");
+
+            GuiSceneManager::getInstance().show("dialog_form");
+            form->exec();
+            GuiSceneManager::getInstance().hide("dialog_form");
+            return false;
+        }
     }
 
     return false;
@@ -220,5 +325,127 @@ UnitIconEventListener::UnitIconEventListener(QObject *parent, RecruitmentScene *
 }
 
 bool UnitIconEventListener::eventFilter(QObject *watched, QEvent *event) {
+    QLabel* icon = qobject_cast<QLabel*>(watched);
+    if (!icon) {
+        qDebug() << __FILE__ << " " << __LINE__ << " cannot cast to icon!";
+        return false;
+    }
+
+    unsigned unit_id_number = icon->objectName().mid(icon->objectName().lastIndexOf('_') + 1).toInt();
+    QString icon_name = icon->objectName();
+
+    if (icon_name.contains("available_unit") && unit_id_number >= scene_->available_units_list.size()) {
+        return false;
+    }
+
+    if (icon_name.contains("chosen_unit") && unit_id_number >= scene_->chosen_units_list.size()) {
+        return false;
+    }
+
+    std::shared_ptr<Unit> unit;
+
+    if (icon_name.contains("available_unit"))
+        unit = scene_->available_units_list[unit_id_number];
+    else
+        unit = scene_->chosen_units_list[unit_id_number];
+
+    if (event->type() == QEvent::Enter) {
+        icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_hover.png);\nbackground-color: rgb(253, 234, 168);");
+        SoundEngine::getInstance().playAsync("qrc:/assets/common/buttons/button_hover.mp3");
+
+        IconHint *hint = new IconHint(scene_);
+        hint->resize(300, 300);
+        hint->setHintTitle(unit->getUnitName());
+
+        QString buttons_hint;
+        if (icon_name.contains("available_unit"))
+            buttons_hint = "<br>ЛКМ - нанять юнита<br>ПКМ - информация и улучшения";
+        if (icon_name.contains("chosen_unit"))
+            buttons_hint = "<br>ЛКМ - информация и улучшения<br>ПКМ - вернуть юнита";
+
+        hint->setHintText("Стоимость: " + QString::number(unit->getCost()) + buttons_hint);
+        hint->move(icon->mapToGlobal(QPoint(0,0)).x() + icon->width() / 2 - hint->width() / 2, icon->mapToGlobal(QPoint(0,0)).y() + icon->height() + 2);
+    }
+
+    if (event->type() == QEvent::Leave) {
+        icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_default.png);\nbackground-color: rgb(253, 234, 168);");
+        SoundEngine::getInstance().playAsync("qrc:/assets/common/buttons/button_hover.mp3");
+        QList<IconHint*> hints = scene_->findChildren<IconHint*>("hint");
+        for (auto &hint : hints) {
+            hint->hide();
+            hint->deleteLater();
+        }
+    }
+
+    if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) {
+        icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_active.png);\nbackground-color: rgb(253, 234, 168);");
+        SoundEngine::getInstance().playAsync("qrc:/assets/common/buttons/button_click.mp3");
+    }
+
+    if (event->type() == QEvent::MouseButtonRelease) {
+        icon->setStyleSheet("border-image: url(:/assets/hotseat_recruit/unit_icon_hover.png);\nbackground-color: rgb(253, 234, 168);");
+        QMouseEvent *evt = dynamic_cast<QMouseEvent*>(event);
+        if (evt->button() == Qt::LeftButton) {
+            if (icon_name.contains("available_unit")) {
+                if (scene_->buyUnit(unit))
+                    return false;
+                DialogForm* form = qobject_cast<DialogForm*>(GuiSceneManager::getInstance().getScene("dialog_form"));
+                if (!form)
+                    return false;
+                form->setTitle("Набор юнита " + unit->getUnitName());
+                form->setShowCancel(false);
+                form->setText("Не могу нанять юнита.. Проверьте, возможно он слишком дорогой или для него нет места в отряде?");
+                GuiSceneManager::getInstance().show("dialog_form");
+                form->exec();
+                GuiSceneManager::getInstance().hide("dialog_form");
+                return false;
+            }
+            if (icon_name.contains("chosen_unit")) {
+                DialogForm* form = qobject_cast<DialogForm*>(GuiSceneManager::getInstance().getScene("dialog_form"));
+                if (!form) {
+                    return false;
+                }
+                form->setTitle("Окно информации о юните " + unit->getUnitName());
+                form->setShowCancel(false);
+                form->setText("К сожалению, окно информации о юните и его улучшениях временно недоступно :( <br> В данной версии вы можете выбирать только из юнитов первого звена");
+                GuiSceneManager::getInstance().show("dialog_form");
+                form->exec();
+                GuiSceneManager::getInstance().hide("dialog_form");
+                return false;
+            }
+        }
+        if (evt->button() == Qt::RightButton) {
+            if (icon_name.contains("available_unit")) {
+                DialogForm* form = qobject_cast<DialogForm*>(GuiSceneManager::getInstance().getScene("dialog_form"));
+                if (!form) {
+                    return false;
+                }
+                form->setTitle("Окно информации о юните " + unit->getUnitName());
+                form->setShowCancel(false);
+                form->setText("К сожалению, окно информации о юните и его улучшениях временно недоступно :( <br> В данной версии вы можете выбирать только из юнитов первого звена");
+                GuiSceneManager::getInstance().show("dialog_form");
+                form->exec();
+                GuiSceneManager::getInstance().hide("dialog_form");
+                return false;
+            }
+            if (icon_name.contains("chosen_unit")) {
+                scene_->removeUnit(unit);
+                QList<IconHint*> hints = scene_->findChildren<IconHint*>("hint");
+                for (auto &hint : hints) {
+                    hint->hide();
+                    hint->deleteLater();
+                }
+                if (scene_->childAt(QCursor::pos()) == icon) {
+                    QEvent *event = new QEvent(QEvent::Enter);
+                    QCoreApplication::postEvent(icon, event);
+                } else {
+                    qDebug() << "FUUUUUUUUUUUUUUUUUUUUU";
+                }
+            }
+        }
+    }
+
     return false;
 }
+
+

+ 29 - 15
ui/hotseat_recruitment/recruitmentscene.h

@@ -8,6 +8,7 @@
 #include <QWidget>
 
 #include <vector>
+#include <memory>
 
 class UnitIcon;
 class RaceIcon;
@@ -70,42 +71,54 @@ public:
 
 private:
     void initAvailableRaces();
+
     void initAvailableUnits();
+
     void showChosenUnits();
 
-    void changeRace(Race* race);
-    void setMoney(int money_);
+public:
+    Player *getActivePlayer();
+
+    bool buyUnit(std::shared_ptr<Unit> unit);
+
+    bool removeUnit(std::shared_ptr<Unit> unit);
+
+    void changeRace(std::shared_ptr<Race> race);
+
+    void updateMoney();
 
 private slots:
     void on_back_button_clicked();
 
+    void on_complete_choice_button_clicked();
+
 public:
     /*
-     * race_ids_ - this is a vector of size = RACES_NUMBER
-     * It contains id of each race in races' icons list in GUI
-     * i-th race in races' icons list has its name stored in race_ids_[i];
+     * races_list - this is a vector of size = RACES_NUMBER
+     * It contains pointers to races in races' icons list in GUI
+     * i-th race in races' icons list has its race stored in races_list[i];
      */
 
-    std::vector<QString> race_ids_;
+    std::vector<std::shared_ptr<Race>> races_list;
 
     /*
-     * available_unit_ids - this is a vector of size = AVAILABLE_UNIT_NUMBER
-     * It contains id of each unit in available units' icons list in GUI
-     * i-th race in available units' icons list has its name stored in available_unit_ids[i];
+     * available_units_list - this is a vector of size = AVAILABLE_UNIT_NUMBER
+     * It contains pointer of each unit in available units' icons list in GUI
+     * i-th unit in available units' icons list has its pointer stored in available_units_list[i];
      */
 
-    std::vector<QString> available_unit_ids;
+    std::vector<std::shared_ptr<Unit>> available_units_list;
 
     /*
-     * chosen_unit_ids - this is a vector of size = MAX_PARTY_SIZE
-     * It contains id of each unit in chosen units' icons list in GUI
-     * i-th race in chosen units' icons list has its name stored in chosen_unit_ids[i];
+     * chosen_units_list - this is a vector of size = MAX_PARTY_SIZE
+     * It contains pointer of each unit in chosen units' icons list in GUI
+     * i-th unit in chosen units' icons list has its name stored in chosen_units_list[i];
      */
 
-    std::vector<QString> chosen_unit_ids;
+    std::vector<std::shared_ptr<Unit>> chosen_units_list;
 
 
-private:
+public:
     /*
      * RACES_NUMBER - количество рас.
      * Не должно превосходить количество QLabel available_race_*
@@ -130,6 +143,7 @@ private:
 
     static const unsigned MAX_PARTY_SIZE = 10;
 
+private:
     /*
      * available_money_ - максимальное количество монет у игрока.
      * За монеты можно нанимать и улучшать юнитов.