diff --git a/src/Core/Crawl/clientapp.cpp b/src/Core/Crawl/clientapp.cpp index a99fa4a..286555f 100644 --- a/src/Core/Crawl/clientapp.cpp +++ b/src/Core/Crawl/clientapp.cpp @@ -126,7 +126,7 @@ bool ClientApp::init(QQmlApplicationEngine *engine) { QMultiHash<int, const IItem *> availabelItems; initStore(availabelItems); - _engine->initStore(availabelItems); + _engine->init(availabelItems); _engine->setLevel(getLastLevel()); diff --git a/src/Core/Crawl/iitem.cpp b/src/Core/Crawl/iitem.cpp index 5c6f23d..b16e11b 100644 --- a/src/Core/Crawl/iitem.cpp +++ b/src/Core/Crawl/iitem.cpp @@ -19,8 +19,8 @@ const QHash<int, const IItem *>& IItem::childItems() const { return _childs; } -QMultiHash<int, const IItem *> IItem::childItemsRecursive() const { - QMultiHash<int, const IItem *> result; +QMultiHash<int, const IItem *> IItem::childItemsRecursive() const { + QMultiHash<int, const IItem *> result; for (const IItem* item : _childs) { result.unite(item->childItemsRecursive()); @@ -70,4 +70,22 @@ void IItem::deactivate(int item) { bool IItem::isActive(int item) { return _childs.contains(item) && _activeItems.contains(item); } + +unsigned int IItem::itemType() { + if (_typeItem) { + return _typeItem; + } + + _typeItem = qHash(itemTextType()); + return _typeItem; +} + +unsigned int IItem::itemType() const { + if (_typeItem) { + return _typeItem; + } + + return qHash(itemTextType()); +} + } diff --git a/src/Core/Crawl/iitem.h b/src/Core/Crawl/iitem.h index 804fed8..cd7b98c 100644 --- a/src/Core/Crawl/iitem.h +++ b/src/Core/Crawl/iitem.h @@ -34,6 +34,13 @@ public: */ virtual QString itemTextId() const = 0; + /** + * @brief itemTextType This method return text of the item group or type. + * @return text of the item group of type. + * @see IITem::itemType + */ + virtual QString itemTextType() const = 0; + /** * @brief itemName This method should be return name of the item. * @return Name of the item (translated to all supported languages) @@ -92,6 +99,7 @@ public: /** * @brief itemId This method return hash of the IItem::itemTextId. * @return hash of the IItem::itemTextId. + * @see IItem::itemTextId * @note The not const implementation inlike const implementation write a id to cache. */ unsigned int itemId(); @@ -99,10 +107,27 @@ public: /** * @brief itemId This method return hash of the IItem::itemTextId. * @return hash of the IItem::itemTextId. - * @warning if the object are const and not const implementation of the IItem::itemId method never invoked then this method return 0. + * @see IItem::itemTextId + * @warning This method not cached id value, so works sloyle then not cons implementation. */ unsigned int itemId() const; + /** + * @brief itemType This method return item type id. (items group) + * @return item type id. + * @see IItem::itemTextType + * @note The not const implementation inlike const implementation write a id to cache. + */ + unsigned int itemType(); + + /** + * @brief itemType This method return item type id. (items group) + * @return item type id. + * @see IItem::itemTextType + * @warning This method not cached id value, so works sloyle then not cons implementation. + */ + unsigned int itemType() const; + /** * @brief activeItems This method return set of the actived items. * @return set of the actived items. @@ -156,6 +181,7 @@ public: private: unsigned int _id = 0; + unsigned int _typeItem = 0; QHash<int, const IItem*> _childs; QSet<int> _activeItems; diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index 3884643..5000d9a 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -41,6 +41,18 @@ IWorld::~IWorld() { delete _eventServer; } +QString IWorld::itemTextType() const { + return IWorld::typeText(); +} + +unsigned int IWorld::type() { + return qHash(IWorld::typeText()); +} + +QString IWorld::typeText() { + return "WorldObject"; +} + void IWorld::init() { } diff --git a/src/Core/Crawl/iworld.h b/src/Core/Crawl/iworld.h index 45a31e2..783e87e 100644 --- a/src/Core/Crawl/iworld.h +++ b/src/Core/Crawl/iworld.h @@ -81,6 +81,22 @@ public: IWorld(); ~IWorld() override; + QString itemTextType() const override; + + /** + * @brief type This method return const string value of the all world types. + * @return const string value of the all world types. + * @see IItem::itemTextType + * @see IItem::type + */ + static QString typeText(); + + /** + * @brief type This is wrapper of the IWorld::typeText method that invoke the qHash function for results string. + * @return integer type object id. + */ + static unsigned int type(); + void init() override; /** @@ -549,6 +565,7 @@ private: // testing friend ClastersTest; + }; } diff --git a/src/Core/Crawl/snake.cpp b/src/Core/Crawl/snake.cpp index 0674ecd..d50538d 100644 --- a/src/Core/Crawl/snake.cpp +++ b/src/Core/Crawl/snake.cpp @@ -41,6 +41,18 @@ Snake::~Snake( ){ delete [] _vectors; } +QString Snake::itemTextType() const { + return Snake::typeText(); +} + +QString Snake::typeText() { + return "PlayableObject"; +} + +unsigned int Snake::type() { + return qHash(typeText()); +} + void Snake::render(unsigned int tbfMsec) { PlayableObject::render(tbfMsec); } diff --git a/src/Core/Crawl/snake.h b/src/Core/Crawl/snake.h index 669c425..6afa0de 100644 --- a/src/Core/Crawl/snake.h +++ b/src/Core/Crawl/snake.h @@ -28,6 +28,22 @@ public: QObject *ptr = nullptr); ~Snake() override; + QString itemTextType() const override; + + /** + * @brief type This method return const string value of the all world types. + * @return const string value of the all world types. + * @see IItem::itemTextType + * @see IItem::type + */ + static QString typeText(); + + /** + * @brief type This is wrapper of the IWorld::typeText method that invoke the qHash function for results string. + * @return integer type object id. + */ + static unsigned int type(); + void render(unsigned int tbfMsec) override; void add(ClasterItem *object) override; @@ -132,6 +148,7 @@ private: float _speed; int _hp = 100; + }; } diff --git a/src/Core/private/availablelevelsmodel.cpp b/src/Core/private/availablelevelsmodel.cpp index 5224b2e..001c629 100644 --- a/src/Core/private/availablelevelsmodel.cpp +++ b/src/Core/private/availablelevelsmodel.cpp @@ -42,4 +42,8 @@ void AvailableLevelsModel::select(int levelId) { } } +const IItem *AvailableLevelsModel::getItem(int id) const { + return _allLevels.value(id, nullptr); +} + } diff --git a/src/Core/private/availablelevelsmodel.h b/src/Core/private/availablelevelsmodel.h index 9d31813..e524b6f 100644 --- a/src/Core/private/availablelevelsmodel.h +++ b/src/Core/private/availablelevelsmodel.h @@ -18,6 +18,7 @@ class IItem; /** * @brief The AvailableLevelsModel class is model of the available levels qml view. * This model just show available levels of the current user. + * @see the SelectLevelView.qml module. */ class AvailableLevelsModel: public BaseUserListModel { @@ -64,6 +65,11 @@ public: */ Q_INVOKABLE void select(int levelId); + + // BaseUserListModel interface +protected: + const IItem *getItem(int id) const; + signals: /** * @brief currentLevelChanged This signal emited when the currentLevel propertye is changed. @@ -82,6 +88,7 @@ signals: private: QList<const IItem*> _allLevels; int currentLevel = -1; + }; } diff --git a/src/Core/private/baseuserlistmodel.cpp b/src/Core/private/baseuserlistmodel.cpp index b7c4df2..b42a19c 100644 --- a/src/Core/private/baseuserlistmodel.cpp +++ b/src/Core/private/baseuserlistmodel.cpp @@ -72,6 +72,27 @@ void BaseUserListModel::setKeys(const QList<int> &visibleKeysList) { } } +void BaseUserListModel::addKey(int newKey) { + beginInsertRows({}, _keys.size(), _keys.size()); + _keys.push_back(newKey); + _keysIndexes[newKey] = _keys.size(); + endInsertRows(); +} + +void BaseUserListModel::removeKey(int oldKey) { + int idx = getIndexById(oldKey); + + if (idx >= 0) { + beginInsertRows({}, _keys.size(), _keys.size()); + + _keys.removeAt(idx); + _keysIndexes.remove(oldKey); + + endInsertRows(); + + } +} + int BaseUserListModel::rowCount(const QModelIndex &) const { return _keys.size(); } diff --git a/src/Core/private/baseuserlistmodel.h b/src/Core/private/baseuserlistmodel.h index 2b863d9..5c9d518 100644 --- a/src/Core/private/baseuserlistmodel.h +++ b/src/Core/private/baseuserlistmodel.h @@ -44,6 +44,18 @@ public: */ void setKeys(const QList<int>& visibleKeysList); + /** + * @brief addKey This method add new key value for view. + * @param newKey new key value. + */ + void addKey(int newKey); + + /** + * @brief removeKey This method remove old key from view. + * @param oldKey This is old key that will be removed. + */ + void removeKey(int oldKey); + int rowCount(const QModelIndex &parent = {}) const override; int columnCount(const QModelIndex &parent = {}) const override; QVariant data(const QModelIndex &index, int role) const override; diff --git a/src/Core/private/engine.cpp b/src/Core/private/engine.cpp index 72d0944..b67c760 100644 --- a/src/Core/private/engine.cpp +++ b/src/Core/private/engine.cpp @@ -5,6 +5,7 @@ //# of this license document, but changing it is not allowed. //# +#include "availablelevelsmodel.h" #include "engine.h" #include "mainmenumodel.h" @@ -24,9 +25,10 @@ namespace CRAWL { Engine::Engine(QObject *parent): QObject(parent) { _store = new Store(); - _currentUser = new User(); _menu = new MainMenuModel(); + setNewUser(new User()); + } Engine::~Engine() { @@ -124,6 +126,18 @@ void Engine::stop() const { _currentLevel->previewScane()->start(_currentLevel->previewScane()->configuration()); } +void Engine::handleUnlockedItem(int item) { + static_cast<AvailableLevelsModel*>(_menu->selectLevelModle())->addKey(item); +} + +void Engine::handleDroppedItem(int item) { + static_cast<AvailableLevelsModel*>(_menu->selectLevelModle())->removeKey(item); +} + +void Engine::handleUnlockedItemsListChanged(const QSet<int> &newSet) { + static_cast<AvailableLevelsModel*>(_menu->selectLevelModle())->setKeys(QList<int>(newSet.begin(), newSet.end())); +} + QObject *Engine::getGameObject(int id) const { if (!_currentLevel) return nullptr; @@ -171,6 +185,29 @@ QObject *Engine::menu() const { return _menu; } +void Engine::setNewUser(User *user) { + if (_currentUser) { + + disconnect(_currentUser, &User::sigUnlcoked, this, &Engine::handleUnlockedItem); + disconnect(_currentUser, &User::sigDropped, this, &Engine::handleDroppedItem); + disconnect(_currentUser, &User::sigUlockedItemsChanged, + this, &Engine::handleUnlockedItemsListChanged); + } + + _currentUser = user; + static_cast<StoreViewModel*>(_menu->storeView())->setUser(_currentUser); + static_cast<AvailableLevelsModel*>(_menu->selectLevelModle())->setUser(_currentUser); + + + if (_currentUser) { + + connect(_currentUser, &User::sigUnlcoked, this, &Engine::handleUnlockedItem); + connect(_currentUser, &User::sigDropped, this, &Engine::handleDroppedItem); + connect(_currentUser, &User::sigUlockedItemsChanged, + this, &Engine::handleUnlockedItemsListChanged); + } +} + Store *Engine::store() const { return _store; } @@ -186,10 +223,18 @@ User *Engine::currentUser() const { return _currentUser; } - -void Engine::initStore(const QMultiHash<int, const IItem *> &availabelItems) { +void Engine::init(const QMultiHash<int, const IItem *> &availabelItems) { _store->init(availabelItems); static_cast<StoreViewModel*>(_menu->storeView())->init(_store, _currentUser); + + QList<const IItem*> availableWorlds; + for (const IItem * item : availabelItems) { + if (item->itemType() == IWorld::type()) { + availableWorlds.push_back(item); + } + } + + static_cast<AvailableLevelsModel*>(_menu->selectLevelModle())->setAllLevels(availableWorlds); } } diff --git a/src/Core/private/engine.h b/src/Core/private/engine.h index 280d161..66a3c2b 100644 --- a/src/Core/private/engine.h +++ b/src/Core/private/engine.h @@ -107,10 +107,10 @@ public: User *currentUser() const; /** - * @brief initStore This method is wrapper of the Store::init method. + * @brief init This method initialize the main model. Sets available levels and items. * @param availabelItems This is list of available items. */ - void initStore(const QMultiHash<int, const IItem *> &availabelItems); + void init(const QMultiHash<int, const IItem *> &availabelItems); /** * @brief store This pointer return pointer to store. @@ -130,6 +130,11 @@ public: */ QObject *menu() const; + /** + * @brief setNewUser This method will initialise the new user profile. + * @param user This is pointer to new user profile. + */ + void setNewUser(User* user); signals: void scaneChanged(); @@ -151,6 +156,24 @@ private slots: */ void stop() const; + /** + * @brief handleUnlockedItem This slot invoked when emited the User::unclokItem signal. + * @param item This is id of the unlocked item + */ + void handleUnlockedItem(int item); + + /** + * @brief handleUnlockedItem This slot invoked when emited the User::droppItem signal. + * @param item This is id of the dropped item + */ + void handleDroppedItem(int item); + + /** + * @brief handleUnlockedItem This slot invoked when emited the User::setUnlockedItems signal. + * @param item This is new list of the unclod items. + */ + void handleUnlockedItemsListChanged(const QSet<int>& newSet); + private: void renderLoop(); diff --git a/src/Core/private/mainmenumodel.cpp b/src/Core/private/mainmenumodel.cpp index 7b8eca2..b334d9a 100644 --- a/src/Core/private/mainmenumodel.cpp +++ b/src/Core/private/mainmenumodel.cpp @@ -6,6 +6,7 @@ //# #include <listviewmodel.h> +#include "availablelevelsmodel.h" #include "mainmenumodel.h" #include "settingsviewmodel.h" #include "storeviewmodel.h" @@ -19,10 +20,12 @@ MainMenuModel::MainMenuModel(QObject *ptr): QObject (ptr) { _conf = QuasarAppUtils::Settings::instance(); _userSettingsModel = new SettingsViewModel(this); _storeView = new StoreViewModel(); + _selectLevelModle = new AvailableLevelsModel(); } MainMenuModel::~MainMenuModel() { delete _storeView; + delete _selectLevelModle; } QObject *MainMenuModel::userSettingsModel() const { @@ -44,4 +47,8 @@ QObject *MainMenuModel::storeView() const { return _storeView; } +AvailableLevelsModel *MainMenuModel::selectLevelModle() const { + return _selectLevelModle; +} + } diff --git a/src/Core/private/mainmenumodel.h b/src/Core/private/mainmenumodel.h index eee7dca..28c4998 100644 --- a/src/Core/private/mainmenumodel.h +++ b/src/Core/private/mainmenumodel.h @@ -19,6 +19,7 @@ namespace CRAWL { class WorldInfo; class StoreViewModel; +class AvailableLevelsModel; /** * @brief The MainMenuModel class This is main class for controll user interface @@ -30,13 +31,28 @@ class MainMenuModel : public QObject Q_PROPERTY(QObject* userSettingsModel READ userSettingsModel NOTIFY userSettingsModelChanged) Q_PROPERTY(bool visible READ getVisible WRITE setVisible NOTIFY visibleChanged) Q_PROPERTY(QObject * storeView READ storeView NOTIFY storeViewChanged) + Q_PROPERTY(AvailableLevelsModel * selectLevelModle READ selectLevelModle NOTIFY selectLevelModleChanged) public: MainMenuModel(QObject *ptr = nullptr); ~MainMenuModel(); + + /** + * @brief userSettingsModel This method return pointer to the setting model. + * @return This is pointer to setting model. + */ QObject* userSettingsModel() const; + /** + * @brief getVisible This method return visible property of the main game menu. + * @return true if the menu is visble. + */ bool getVisible() const; + + /** + * @brief setVisible This method will change visible of the main menu. + * @param newVisible This is new vlaue of the visible. + */ void setVisible(bool newVisible); /** @@ -45,18 +61,25 @@ public: */ QObject *storeView() const; + /** + * @brief selectLevelModle This method return pointer to the available levels model. + * @return pointer to main available levels model. + */ + AvailableLevelsModel *selectLevelModle() const; + + signals: void userSettingsModelChanged(QObject* userSettingsModel); - void visibleChanged(); - void storeViewChanged(); + void selectLevelModleChanged(); private: Settings *_conf = nullptr; QObject* _userSettingsModel = nullptr; bool visible = true; StoreViewModel *_storeView = nullptr; + AvailableLevelsModel *_selectLevelModle = nullptr; };