From 8ece536e4ac6ac53599a366cd42b810e58379f70 Mon Sep 17 00:00:00 2001 From: EndrII Date: Thu, 17 Jun 2021 13:57:57 +0300 Subject: [PATCH 1/9] engine impruvments --- src/Client/CMakeLists.txt | 4 +-- src/Core/Crawl/clientapp.h | 2 +- src/Core/Crawl/iworld.cpp | 46 ++++++++++++++++---------- src/Core/Crawl/iworld.h | 40 ++++++++++++++++++----- src/Core/CrawlModule/GraphicItem.qml | 14 +++++++- src/Core/CrawlModule/Scene.qml | 49 ++++++++++++++++++---------- src/CrawlTestLvl | 2 +- 7 files changed, 107 insertions(+), 50 deletions(-) diff --git a/src/Client/CMakeLists.txt b/src/Client/CMakeLists.txt index eb13bd4..a39536b 100644 --- a/src/Client/CMakeLists.txt +++ b/src/Client/CMakeLists.txt @@ -50,8 +50,8 @@ if (ANDROID) addDeployAPK(${CURRENT_PROJECT} "${CMAKE_CURRENT_LIST_DIR}/android" - "Crawl" - "${SIGPATH}/Crawl.keystore" + "Snake" + "${SIGPATH}/Snake.keystore" "${SIGPASS_SNAKE}" "${TARGET_DIR}" "${SNAKE_EXTRA_LIBS}") diff --git a/src/Core/Crawl/clientapp.h b/src/Core/Crawl/clientapp.h index 8f89b5b..ac7e6c4 100644 --- a/src/Core/Crawl/clientapp.h +++ b/src/Core/Crawl/clientapp.h @@ -40,7 +40,7 @@ class CRAWL_EXPORT ClientApp : public QObject Q_OBJECT public: ClientApp(); - ~ClientApp(); + ~ClientApp() override; /** * @brief init This method initialize engine on application. diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index eb256d9..191a0a4 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -61,10 +61,34 @@ bool IWorld::start() { worldChanged(*_worldRules->begin()); - return true; } +QObject *IWorld::player() const { + return _player; +} + +void IWorld::setPlayer(QObject *newPlayer) { + if (_player == newPlayer) + return; + + auto newPlayerObject = dynamic_cast(newPlayer); + if (!newPlayerObject) { + QuasarAppUtils::Params::log("Failed to set player object. The input object is not player.", + QuasarAppUtils::Error); + return; + } + + if (_player) { + removeItem(_player->guiId()); + } + + _player = newPlayerObject; + addItem("player", _player); + + emit playerChanged(); +} + bool IWorld::stop() { start(); @@ -90,8 +114,9 @@ bool IWorld::init() { return true; _worldRules = initWorldRules(); + _hdrMap = initHdrBackGround(); - _player = initPlayer(); + setPlayer(initPlayer()); _player->initOnWorld(this, _player); _userInterface = initUserInterface(); _backgroundAI = initBackGroundAI(); @@ -109,7 +134,6 @@ bool IWorld::init() { initPlayerControl(_userInterface); initPlayerControl(dynamic_cast(_backgroundAI)); - generateGround(); return true; } @@ -148,21 +172,6 @@ void IWorld::deinit() { } -void IWorld::generateGround() { - int count = 10; - - QVector3D position = {0,0,0}; - float increment = cameraReleativePosition().z() * 2; - - while (count--) { - auto item = generateGroundTile(); - item->initOnWorld(this, _player); - - position.setX(position.x() + increment); - item->setposition(position); - addItem("groundTile", item); - } -} void IWorld::addItem(const QString& group, IWorldItem* obj) { _items.insert(obj->guiId(), WorldObjectWraper{obj, group}); @@ -188,6 +197,7 @@ int IWorld::removeAnyItemFromGroup(const QString &group) { int anyObjectId = _itemsGroup.value(group); if (!removeItem(anyObjectId)) { return false; + } return anyObjectId; diff --git a/src/Core/Crawl/iworld.h b/src/Core/Crawl/iworld.h index 6925067..20f74b5 100644 --- a/src/Core/Crawl/iworld.h +++ b/src/Core/Crawl/iworld.h @@ -52,6 +52,7 @@ class CRAWL_EXPORT IWorld : public QObject, public IRender Q_OBJECT Q_PROPERTY(QVector3D cameraReleativePosition READ cameraReleativePosition NOTIFY cameraReleativePositionChanged) Q_PROPERTY(QQuaternion cameraRatation READ cameraRatation NOTIFY cameraRatationChanged) + Q_PROPERTY(QObject * player READ player WRITE setPlayer NOTIFY playerChanged) Q_PROPERTY(int worldStatus READ wordlStatus WRITE setWorldStatus NOTIFY worldStatusChanged) @@ -59,14 +60,6 @@ public: IWorld(); virtual ~IWorld(); - /** - * @brief generateGroundTile This method should be generate a new tile of the world. - * @return raw pointer to tile of the world ground. - * @note The tile count sets automaticly. - * @note All generated objects will be distroed automaticaly. - */ - virtual IGround* generateGroundTile() = 0; - /** * @brief initPlayer The implementation of This interface must be return playerObject. * @return raw pointer to the player object. @@ -211,6 +204,12 @@ public: */ const QQuaternion &cameraRatation() const; + /** + * @brief player This method return player object + * @return player object + */ + QObject *player() const; + signals: /** * @brief sigGameFinished This signal emit when game are finished @@ -245,13 +244,37 @@ signals: */ void cameraRatationChanged(); + void playerChanged(); + protected: + /** + * @brief setPlayer This method sets new player object + * @param newPlayer This is new player object. + * @note This method remove old player object if it exists + */ + void setPlayer(QObject *newPlayer); + /** * @brief generate This method shold be generate object from the @a objectType. * Override this method for add support yourown objects. * @param objectType This is string type name of the object, * @return pointer to the object. + * + * **Example** + * ```cpp + * IWorldItem* generate(const QString& objectType)) const { + * if (auto obj = IWorld::generate(objectType)) { + * return obj; + * } + * + * ... + * // custom implementation + * ... + * + * return nullptr; + * } + * ``` */ virtual IWorldItem* generate(const QString& objectType) const = 0; @@ -279,7 +302,6 @@ private: bool init(); void deinit(); - void generateGround(); void worldChanged(const WorldObjects& objects); void clearItems(); void addItem(const QString &group, IWorldItem *obj); diff --git a/src/Core/CrawlModule/GraphicItem.qml b/src/Core/CrawlModule/GraphicItem.qml index 295cb4f..d4c7459 100644 --- a/src/Core/CrawlModule/GraphicItem.qml +++ b/src/Core/CrawlModule/GraphicItem.qml @@ -29,7 +29,7 @@ Model { } materials: [ - (fMapColor)? objectMaterial: defaultMaterial + (fMapColor)? objMaterial: defaultMaterial ] rotation: (model)? model.ratation: Qt.quaternion(0, 0, 0, 0) @@ -38,3 +38,15 @@ Model { position: (model) ? model.position: Qt.vector3d(0,0,0); } + +//Model { +// source: "#Cube"; +// property var model: null +// property int guiId: (model) ? model.guiId : -1; +// materials: [ +// DefaultMaterial { +// id: defaultMaterial +// diffuseColor: "#ff1111" +// } +// ] +//} diff --git a/src/Core/CrawlModule/Scene.qml b/src/Core/CrawlModule/Scene.qml index 16cdc0c..e86dede 100644 --- a/src/Core/CrawlModule/Scene.qml +++ b/src/Core/CrawlModule/Scene.qml @@ -12,47 +12,47 @@ View3D { property var model: null; property alias showMenu: privateRoot.showMenu + renderMode: View3D.Underlay PerspectiveCamera { id: camera - position: (privateRoot.player)? Qt.vector3d( - privateRoot.player.position.x + privateRoot.releativeCameraPosition.x, - privateRoot.player.position.y + privateRoot.releativeCameraPosition.y, - privateRoot.player.position.z + privateRoot.releativeCameraPosition.z - ) + position: (privateRoot.player && privateRoot.releativeCameraPosition)? + Qt.vector3d(privateRoot.player.position.x + privateRoot.releativeCameraPosition.x, + privateRoot.player.position.y + privateRoot.releativeCameraPosition.y, + privateRoot.player.position.z + privateRoot.releativeCameraPosition.z) : - Qt.vector3d(0,0,0) + Qt.vector3d(0,0,100) + + onPositionChanged: { + console.log(position) + } rotation: (privateRoot.world)? privateRoot.world.cameraRatation: Qt.quaternion(0,0,0,0) } - DirectionalLight { - position: Qt.vector3d(0,0,100) - eulerRotation.z: 90 - - } - - Node { - id: mainScane + PointLight { + position: camera.position + brightness: 1500 } environment: SceneEnvironment { id: background backgroundMode: SceneEnvironment.SkyBox - lightProbe: Texture { source: (model)? model.hdr: "" } } - Item { + Node { id: privateRoot property var arrayObjects: [] - property var player: (model)? model.player: null property var world: (model)? model.world: null + property int oldPlayerId: -1 + property var gameMenuModel: (model)? model.menu: null + property var player: (world)? world.player: null property var releativeCameraPosition: (world)? world.cameraReleativePosition: null property var progress: (model)? model.prepareLvlProgress: null @@ -75,7 +75,7 @@ View3D { var temp = Qt.createComponent(viewTemplate) if (temp.status === Component.Ready) { - var obj = temp.createObject(mainScane) // mainScane - это обьект на который будет помещен соззданный элемент + var obj = temp.createObject(privateRoot) obj.model = model.getGameObject(cppObjId); arrayObjects.push(obj) } else { @@ -122,6 +122,19 @@ View3D { Connections { target: privateRoot; + function onPlayerChanged() { + + if (!privateRoot.player) + return + + if (privateRoot.oldPlayerId >= 0) { + privateRoot.remove(privateRoot.oldPlayerId); + } + + privateRoot.add(privateRoot.player.guiId); + privateRoot.oldPlayerId = privateRoot.player.guiId + } + function onGameMenuModelChanged() { if (!privateRoot.gameMenuModel) { return; diff --git a/src/CrawlTestLvl b/src/CrawlTestLvl index 9fe1e01..b49a93a 160000 --- a/src/CrawlTestLvl +++ b/src/CrawlTestLvl @@ -1 +1 @@ -Subproject commit 9fe1e017da688c760fa2c9aaaa76622ad3c2f658 +Subproject commit b49a93ac987ad3bb4f478bb47c2241262fafe2d3 From 262efb493af3670fec65f105708a6cb376ff17d2 Mon Sep 17 00:00:00 2001 From: EndrII Date: Thu, 17 Jun 2021 18:32:32 +0300 Subject: [PATCH 2/9] begin work on clasters --- src/Core/Crawl/claster.cpp | 32 ++++++++++++++ src/Core/Crawl/claster.h | 52 +++++++++++++++++++++++ src/Core/Crawl/iplayer.h | 8 +++- src/Core/Crawl/irender.h | 1 + src/Core/Crawl/iworld.cpp | 2 + src/Core/Crawl/iworld.h | 7 +++ src/Core/Crawl/iworlditem.h | 14 +++--- src/Core/Crawl/singleclasterworlditem.cpp | 22 ++++++++++ src/Core/Crawl/singleclasterworlditem.h | 38 +++++++++++++++++ src/CrawlTestLvl | 2 +- 10 files changed, 170 insertions(+), 8 deletions(-) create mode 100644 src/Core/Crawl/claster.cpp create mode 100644 src/Core/Crawl/claster.h create mode 100644 src/Core/Crawl/singleclasterworlditem.cpp create mode 100644 src/Core/Crawl/singleclasterworlditem.h diff --git a/src/Core/Crawl/claster.cpp b/src/Core/Crawl/claster.cpp new file mode 100644 index 0000000..75c8152 --- /dev/null +++ b/src/Core/Crawl/claster.cpp @@ -0,0 +1,32 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "claster.h" +#include "singleclasterworlditem.h" + +Claster::Claster() { + +} + +void Claster::add(IWorldItem *object) { + _objects.insert(object->guiId(), object); + if (auto singlClasterObject = dynamic_cast(object)) { + singlClasterObject->setClaster(this); + } +} + +void Claster::remove(IWorldItem *object) { + _objects.remove(object->guiId()); +} + +void Claster::remove(int id) { + _objects.remove(id); +} + +const QHash &Claster::objects() const { + return _objects; +} diff --git a/src/Core/Crawl/claster.h b/src/Core/Crawl/claster.h new file mode 100644 index 0000000..417386b --- /dev/null +++ b/src/Core/Crawl/claster.h @@ -0,0 +1,52 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#ifndef CLASTER_H +#define CLASTER_H + +#include "Crawl/iworlditem.h" + + +/** + * @brief The Claster class are object with support multiple objects render. + * For example snake with 20 points of the snake blocks. + */ +class CRAWL_EXPORT Claster: public IWorldItem +{ + Q_OBJECT +public: + Claster(); + + /** + * @brief add This method added new object to claster. + * @param object This is model of added object + */ + void add(IWorldItem* object); + + /** + * @brief remove This method remove object from claster + * @param object poiter of removed object + */ + void remove(IWorldItem* object); + + /** + * @brief remove some as a Claster::remove(IWorldItem* object) but by id. + * @param id of the remved object. + */ + void remove(int id); + + /** + * @brief objects This method return list of collected objects. + * @return return const reference to objects list . + */ + const QHash &objects() const; + +private: + QHash _objects; +}; + +#endif // CLASTER_H diff --git a/src/Core/Crawl/iplayer.h b/src/Core/Crawl/iplayer.h index f46f386..6a88bec 100644 --- a/src/Core/Crawl/iplayer.h +++ b/src/Core/Crawl/iplayer.h @@ -51,7 +51,7 @@ public: * @param control This is control object. * @note This method can invoked two or more times, for example connect with AI control object and player control object. So your implementation should be contains disconnect methods. */ - virtual void setControl(const IControl* control) = 0; + virtual void setControl(const IControl* control); protected: @@ -90,6 +90,12 @@ protected: */ void fine(int value); + /** + * @brief onTap This method invoked when user tap on screen. + * @note method connected in the IPlayer::setControl function. So if you overrid the IPlayer::setControl method then please invoke method of a parent class. + */ + virtual void onTap() = 0; + private: bool _fDead = false; int _currentPoints = 0; diff --git a/src/Core/Crawl/irender.h b/src/Core/Crawl/irender.h index 2f66981..7c996f4 100644 --- a/src/Core/Crawl/irender.h +++ b/src/Core/Crawl/irender.h @@ -17,6 +17,7 @@ class CRAWL_EXPORT IRender { public: IRender(); + virtual ~IRender() = default; /** * @brief render This method should be recalc all properyes of the this object. diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index 191a0a4..bec893a 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -257,6 +257,8 @@ void IWorld::worldChanged(const WorldObjects &objects) { for ( int i = 0; i < count; ++i ) { IWorldItem *obj = generate(it.key()); + TO-Do Add support of clasters. + obj->initOnWorld(this, _player); if (!obj) { diff --git a/src/Core/Crawl/iworld.h b/src/Core/Crawl/iworld.h index 20f74b5..33b10ad 100644 --- a/src/Core/Crawl/iworld.h +++ b/src/Core/Crawl/iworld.h @@ -244,6 +244,9 @@ signals: */ void cameraRatationChanged(); + /** + * @brief playerChanged This signal eited when player are changed. + */ void playerChanged(); protected: @@ -291,6 +294,10 @@ protected: void setCameraRatation(const QQuaternion &newCameraRatation); private slots: + + /** + * @brief handleStop This slot invoked when user click return main menu button. + */ void handleStop(); private: diff --git a/src/Core/Crawl/iworlditem.h b/src/Core/Crawl/iworlditem.h index 1ac6551..f419741 100644 --- a/src/Core/Crawl/iworlditem.h +++ b/src/Core/Crawl/iworlditem.h @@ -22,6 +22,13 @@ public: const IWorld *world() const; + /** + * @brief render This implementation move objects from end of scane to begin. + * @param tbfMsec + * @note new position = playerPosition + scaneSize; + */ + void render(unsigned int tbfMsec) override; + protected: /** @@ -42,12 +49,7 @@ protected: */ const IWorldItem * getPlayer() const; - /** - * @brief render This implementation move objects from end of scane to begin. - * @param tbfMsec - * @note new position = playerPosition + scaneSize; - */ - void render(unsigned int tbfMsec) override; + private: void initOnWorld(const IWorld* world, const IWorldItem *player); diff --git a/src/Core/Crawl/singleclasterworlditem.cpp b/src/Core/Crawl/singleclasterworlditem.cpp new file mode 100644 index 0000000..18ad78f --- /dev/null +++ b/src/Core/Crawl/singleclasterworlditem.cpp @@ -0,0 +1,22 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#include "claster.h" +#include "singleclasterworlditem.h" + +SingleClasterWorldItem::SingleClasterWorldItem() { + +} + +void SingleClasterWorldItem::setClaster(Claster *claster) { + if (_parentClaster) { + _parentClaster->remove(guiId()); + } + + _parentClaster = claster; +} diff --git a/src/Core/Crawl/singleclasterworlditem.h b/src/Core/Crawl/singleclasterworlditem.h new file mode 100644 index 0000000..3f1509b --- /dev/null +++ b/src/Core/Crawl/singleclasterworlditem.h @@ -0,0 +1,38 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + + +#ifndef SINGLECLASTERWORLDITEM_H +#define SINGLECLASTERWORLDITEM_H + +#include "iworlditem.h" + +class Claster; + +/** + * @brief The SingleClasterWorldItem class This is wraper of the OWorldOitem for the controll parent clasters. + * This object can belong to only one cluster in one time + */ +class CRAWL_EXPORT SingleClasterWorldItem: public IWorldItem +{ +public: + SingleClasterWorldItem(); + +private: + + /** + * @brief setClaster invoked when object added to new claster. + * @param claster pointer to invoker claster object. + */ + void setClaster(Claster *claster); + + Claster* _parentClaster = nullptr; + + friend class Claster; +}; + +#endif // SINGLECLASTERWORLDITEM_H diff --git a/src/CrawlTestLvl b/src/CrawlTestLvl index b49a93a..1b5db3e 160000 --- a/src/CrawlTestLvl +++ b/src/CrawlTestLvl @@ -1 +1 @@ -Subproject commit b49a93ac987ad3bb4f478bb47c2241262fafe2d3 +Subproject commit 1b5db3e86f869811ac85b412f6c2392e8524bab9 From eb29d8fcac41080eb289843b12e6d609e0acec99 Mon Sep 17 00:00:00 2001 From: EndrII Date: Fri, 18 Jun 2021 17:33:31 +0300 Subject: [PATCH 3/9] added clasters items --- src/Core/Crawl/clasteritem.cpp | 27 ++++++++++++ src/Core/Crawl/clasteritem.h | 54 +++++++++++++++++++++++ src/Core/Crawl/iworld.cpp | 33 ++++++++++---- src/Core/Crawl/iworld.h | 27 +++++++++--- src/Core/Crawl/singleclasterworlditem.cpp | 11 +++-- src/Core/Crawl/singleclasterworlditem.h | 10 ++--- tests/units/clasterstest.cpp | 18 ++++++++ tests/units/clasterstest.h | 27 ++++++++++++ 8 files changed, 186 insertions(+), 21 deletions(-) create mode 100644 src/Core/Crawl/clasteritem.cpp create mode 100644 src/Core/Crawl/clasteritem.h create mode 100644 tests/units/clasterstest.cpp create mode 100644 tests/units/clasterstest.h diff --git a/src/Core/Crawl/clasteritem.cpp b/src/Core/Crawl/clasteritem.cpp new file mode 100644 index 0000000..595203c --- /dev/null +++ b/src/Core/Crawl/clasteritem.cpp @@ -0,0 +1,27 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "claster.h" +#include "clasteritem.h" + +ClasterItem::ClasterItem() { + +} + +ClasterItem::~ClasterItem() { + if (parentClasters().size() && *parentClasters().begin()) { + (*parentClasters().begin())->remove(this); + } +} + +void ClasterItem::setClaster(Claster *claster) { + _parentClasters += claster; +} + +const QSet &ClasterItem::parentClasters() const { + return _parentClasters; +} diff --git a/src/Core/Crawl/clasteritem.h b/src/Core/Crawl/clasteritem.h new file mode 100644 index 0000000..46fc448 --- /dev/null +++ b/src/Core/Crawl/clasteritem.h @@ -0,0 +1,54 @@ +//# +//# Copyright (C) 2021-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "iworlditem.h" + +#include + + +#ifndef CLASTERITEM_H +#define CLASTERITEM_H + +class Claster; + +/** + * @brief The ClasterItem class This is item of the claster object. Thi class can be used as a one element of the claster class. + * @note This object invoke the Claster::remove method in destructor. + */ +class ClasterItem: public IWorldItem +{ + Q_OBJECT +public: + ClasterItem(); + ~ClasterItem(); + +protected: + /** + * @brief setClaster invoked when object added to new claster. + * @param claster pointer to invoker claster object. + */ + virtual void setClaster(Claster *claster); + + /** + * @brief removeClaster + * @param claster + */ + virtual void removeClaster(Claster *claster); + + /** + * @brief parentClasters return current parent clasters list; + * @return + */ + const QSet &parentClasters() const; +private: + + QSet _parentClasters; + + friend class Claster; +}; + +#endif // CLASTERITEM_H diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index bec893a..ecfd158 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -5,6 +5,7 @@ //# of this license document, but changing it is not allowed. //# +#include "claster.h" #include "iai.h" #include "iworld.h" #include "iworlditem.h" @@ -80,11 +81,11 @@ void IWorld::setPlayer(QObject *newPlayer) { } if (_player) { - removeItem(_player->guiId()); + removeIAtomictem(_player->guiId()); } _player = newPlayerObject; - addItem("player", _player); + addAtomicItem("player", _player); emit playerChanged(); } @@ -146,6 +147,22 @@ void IWorld::clearItems() { _items.clear(); } +void IWorld::addItem(IWorldItem *obj) { + // Work wih claster + if (auto claster = dynamic_cast(obj)) { + + return; + } + // Work With atomic items + +} + +void IWorld::removeItem(int id) { + // Work wih claster + + // Work With atomic items +} + void IWorld::deinit() { if (_player) { delete _player; @@ -173,12 +190,12 @@ void IWorld::deinit() { } -void IWorld::addItem(const QString& group, IWorldItem* obj) { +void IWorld::addAtomicItem(const QString& group, IWorldItem* obj) { _items.insert(obj->guiId(), WorldObjectWraper{obj, group}); _itemsGroup.insert(group, obj->guiId()); } -bool IWorld::removeItem(int id) { +bool IWorld::removeIAtomictem(int id) { auto obj = _items.value(id); if (!obj.objectPtr) { @@ -193,9 +210,9 @@ bool IWorld::removeItem(int id) { return true; } -int IWorld::removeAnyItemFromGroup(const QString &group) { +int IWorld::removeAnyAtomicItemFromGroup(const QString &group) { int anyObjectId = _itemsGroup.value(group); - if (!removeItem(anyObjectId)) { + if (!removeIAtomictem(anyObjectId)) { return false; } @@ -268,12 +285,12 @@ void IWorld::worldChanged(const WorldObjects &objects) { break; } - addItem(it.key(), obj); + addAtomicItem(it.key(), obj); diff.addedIds.append(obj->guiId()); } } else { for (; count < 0; ++count ) { - int removedObjectId = removeAnyItemFromGroup(it.key()); + int removedObjectId = removeAnyAtomicItemFromGroup(it.key()); if (!removedObjectId) { QuasarAppUtils::Params::log("World::changeCountObjects error delete object!", QuasarAppUtils::Warning); diff --git a/src/Core/Crawl/iworld.h b/src/Core/Crawl/iworld.h index 33b10ad..e087e7b 100644 --- a/src/Core/Crawl/iworld.h +++ b/src/Core/Crawl/iworld.h @@ -311,22 +311,39 @@ private: void worldChanged(const WorldObjects& objects); void clearItems(); - void addItem(const QString &group, IWorldItem *obj); /** - * @brief removeItem This method remove object with @a id. + * @brief addItem This method remove object from the scane. If object are calster then this method remove all child objects. + * @param obj pointer to any engine object. + */ + void addItem(IWorldItem *obj); + + /** + * @brief removeItem This method remove item from the world. If the @a id are id of the claster object then its child object will be removed too. + */ + void removeItem(int id); + + /** + * @brief addAtomicItem This method execure atomic operation of add new item. This method support only atomic objects. (not clasters) + * @param group This is group of the atomic object. + * @param obj This is pointer to the atomic object. If the object are claster then it will be added without childs objects. + */ + void addAtomicItem(const QString &group, IWorldItem *obj); + + /** + * @brief removeIAtomictem This method remove object with @a id. This method work with atomic objects only. If you rty remove claster objects then it will be ramoved witohout child objects. * @param id This is id of removed objects. * @return return true if object remove successul */ - bool removeItem(int id); + bool removeIAtomictem(int id); /** - * @brief removeAnyItemFromGroup This method remove any object from group and return id of removed object. + * @brief removeAnyAtomicItemFromGroup This method remove any object from group and return id of removed object. * @param group This is name of the objects group * @return id of removed object. * @note if object not removed return 0 */ - int removeAnyItemFromGroup(const QString &group); + int removeAnyAtomicItemFromGroup(const QString &group); QHash _items; QMultiHash _itemsGroup; diff --git a/src/Core/Crawl/singleclasterworlditem.cpp b/src/Core/Crawl/singleclasterworlditem.cpp index 18ad78f..1e5b5ee 100644 --- a/src/Core/Crawl/singleclasterworlditem.cpp +++ b/src/Core/Crawl/singleclasterworlditem.cpp @@ -8,15 +8,20 @@ #include "claster.h" #include "singleclasterworlditem.h" +#include "quasarapp.h" SingleClasterWorldItem::SingleClasterWorldItem() { } void SingleClasterWorldItem::setClaster(Claster *claster) { - if (_parentClaster) { - _parentClaster->remove(guiId()); + if (parentClasters().size() > 0) { + debug_assert(parentClasters().size() > 1, "Internal error occured, The singleClaster object have multiple claster parents!!"); + + Claster* parent = *parentClasters().begin(); + parent->remove(this); + removeClaster(parent); } - _parentClaster = claster; + ClasterItem::setClaster(claster); } diff --git a/src/Core/Crawl/singleclasterworlditem.h b/src/Core/Crawl/singleclasterworlditem.h index 3f1509b..85227c5 100644 --- a/src/Core/Crawl/singleclasterworlditem.h +++ b/src/Core/Crawl/singleclasterworlditem.h @@ -9,7 +9,7 @@ #ifndef SINGLECLASTERWORLDITEM_H #define SINGLECLASTERWORLDITEM_H -#include "iworlditem.h" +#include "clasteritem.h" class Claster; @@ -17,8 +17,9 @@ class Claster; * @brief The SingleClasterWorldItem class This is wraper of the OWorldOitem for the controll parent clasters. * This object can belong to only one cluster in one time */ -class CRAWL_EXPORT SingleClasterWorldItem: public IWorldItem +class CRAWL_EXPORT SingleClasterWorldItem: public ClasterItem { + Q_OBJECT public: SingleClasterWorldItem(); @@ -27,10 +28,9 @@ private: /** * @brief setClaster invoked when object added to new claster. * @param claster pointer to invoker claster object. + * @note This implementation can be sets only one object as a parent. */ - void setClaster(Claster *claster); - - Claster* _parentClaster = nullptr; + void setClaster(Claster *claster) override; friend class Claster; }; diff --git a/tests/units/clasterstest.cpp b/tests/units/clasterstest.cpp new file mode 100644 index 0000000..cb989e6 --- /dev/null +++ b/tests/units/clasterstest.cpp @@ -0,0 +1,18 @@ +//# +//# Copyright (C) 2020-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//# + +#include "clasterstest.h" +#include + +ClastersTest::ClastersTest() +{ + +} + +void ClastersTest::test() { + QVERIFY(false); +} diff --git a/tests/units/clasterstest.h b/tests/units/clasterstest.h new file mode 100644 index 0000000..34f1e3e --- /dev/null +++ b/tests/units/clasterstest.h @@ -0,0 +1,27 @@ +//# +//# Copyright (C) 2020-2021 QuasarApp. +//# Distributed under the GPLv3 software license, see the accompanying +//# Everyone is permitted to copy and distribute verbatim copies +//# of this license document, but changing it is not allowed. +//#s + +#include "test.h" +#include "testutils.h" + +#ifndef CLASTERSTEST_H +#define CLASTERSTEST_H + +/** + * @brief The ClastersTest class This test of the claster objects system. + */ +class ClastersTest: public Test, protected TestUtils +{ +public: + ClastersTest(); + + // Test interface +public: + void test() override; +}; + +#endif // CLASTERSTEST_H From 748fb4dab666564a16ba9d35f2a0bb3f59e9f6fd Mon Sep 17 00:00:00 2001 From: EndrII Date: Fri, 18 Jun 2021 17:34:31 +0300 Subject: [PATCH 4/9] added integration with clasters tests --- tests/tstMain.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/tstMain.cpp b/tests/tstMain.cpp index 6655607..b38d014 100644 --- a/tests/tstMain.cpp +++ b/tests/tstMain.cpp @@ -7,6 +7,7 @@ #include #include "pluginloadertest.h" +#include "clasterstest.h" // Use This macros for initialize your own test classes. // Check exampletests @@ -33,6 +34,8 @@ private slots: // BEGIN TESTS CASES TestCase(exampleTest, PluginLoaderTest) + TestCase(clastersTest, ClastersTest) + // END TEST CASES private: From f4e6c3876cba3679e16a541b9ae5293a06368cf9 Mon Sep 17 00:00:00 2001 From: EndrII Date: Fri, 18 Jun 2021 22:33:00 +0300 Subject: [PATCH 5/9] added support of clastters (not testsed) --- src/Core/Crawl/claster.cpp | 17 +++- src/Core/Crawl/claster.h | 15 ++- src/Core/Crawl/clasteritem.cpp | 13 ++- src/Core/Crawl/clasteritem.h | 10 +- src/Core/Crawl/guiobject.cpp | 8 +- src/Core/Crawl/guiobject.h | 15 ++- src/Core/Crawl/iground.cpp | 5 +- src/Core/Crawl/iground.h | 4 +- src/Core/Crawl/iplayer.cpp | 5 +- src/Core/Crawl/iplayer.h | 6 +- src/Core/Crawl/iworld.cpp | 116 +++++++++++++--------- src/Core/Crawl/iworld.h | 40 ++++---- src/Core/Crawl/iworlditem.cpp | 5 +- src/Core/Crawl/iworlditem.h | 5 +- src/Core/Crawl/singleclasterworlditem.cpp | 5 +- src/Core/Crawl/singleclasterworlditem.h | 4 +- src/CrawlTestLvl | 2 +- 17 files changed, 187 insertions(+), 88 deletions(-) diff --git a/src/Core/Crawl/claster.cpp b/src/Core/Crawl/claster.cpp index 75c8152..0253c98 100644 --- a/src/Core/Crawl/claster.cpp +++ b/src/Core/Crawl/claster.cpp @@ -8,18 +8,27 @@ #include "claster.h" #include "singleclasterworlditem.h" -Claster::Claster() { +Claster::Claster(const QString &name, + const QString &viewTempalte, + QObject *ptr): + IWorldItem(name, viewTempalte, ptr) { } -void Claster::add(IWorldItem *object) { +Claster::~Claster() { + for (auto child : qAsConst(_objects)) { + child->removeClaster(this); + } +} + +void Claster::add(ClasterItem *object) { _objects.insert(object->guiId(), object); if (auto singlClasterObject = dynamic_cast(object)) { singlClasterObject->setClaster(this); } } -void Claster::remove(IWorldItem *object) { +void Claster::remove(ClasterItem *object) { _objects.remove(object->guiId()); } @@ -27,6 +36,6 @@ void Claster::remove(int id) { _objects.remove(id); } -const QHash &Claster::objects() const { +const QHash &Claster::objects() const { return _objects; } diff --git a/src/Core/Crawl/claster.h b/src/Core/Crawl/claster.h index 417386b..d341d24 100644 --- a/src/Core/Crawl/claster.h +++ b/src/Core/Crawl/claster.h @@ -10,6 +10,7 @@ #include "Crawl/iworlditem.h" +class ClasterItem; /** * @brief The Claster class are object with support multiple objects render. @@ -19,19 +20,23 @@ class CRAWL_EXPORT Claster: public IWorldItem { Q_OBJECT public: - Claster(); + Claster(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); + + ~Claster(); /** * @brief add This method added new object to claster. * @param object This is model of added object */ - void add(IWorldItem* object); + void add(ClasterItem* object); /** * @brief remove This method remove object from claster * @param object poiter of removed object */ - void remove(IWorldItem* object); + void remove(ClasterItem* object); /** * @brief remove some as a Claster::remove(IWorldItem* object) but by id. @@ -43,10 +48,10 @@ public: * @brief objects This method return list of collected objects. * @return return const reference to objects list . */ - const QHash &objects() const; + const QHash &objects() const; private: - QHash _objects; + QHash _objects; }; #endif // CLASTER_H diff --git a/src/Core/Crawl/clasteritem.cpp b/src/Core/Crawl/clasteritem.cpp index 595203c..9ec2d99 100644 --- a/src/Core/Crawl/clasteritem.cpp +++ b/src/Core/Crawl/clasteritem.cpp @@ -8,7 +8,10 @@ #include "claster.h" #include "clasteritem.h" -ClasterItem::ClasterItem() { +ClasterItem::ClasterItem(const QString &name, + const QString &viewTempalte, + QObject *ptr): + IWorldItem(name, viewTempalte, ptr) { } @@ -18,10 +21,18 @@ ClasterItem::~ClasterItem() { } } +int ClasterItem::parentClastersCount() const { + return _parentClasters.size(); +} + void ClasterItem::setClaster(Claster *claster) { _parentClasters += claster; } +void ClasterItem::removeClaster(Claster *claster) { + _parentClasters -= claster; +} + const QSet &ClasterItem::parentClasters() const { return _parentClasters; } diff --git a/src/Core/Crawl/clasteritem.h b/src/Core/Crawl/clasteritem.h index 46fc448..59d5bcf 100644 --- a/src/Core/Crawl/clasteritem.h +++ b/src/Core/Crawl/clasteritem.h @@ -23,9 +23,17 @@ class ClasterItem: public IWorldItem { Q_OBJECT public: - ClasterItem(); + ClasterItem(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); ~ClasterItem(); + /** + * @brief parentClastersCount This method return count of the parent clasters. + * @return parent clasters count + */ + int parentClastersCount() const; + protected: /** * @brief setClaster invoked when object added to new claster. diff --git a/src/Core/Crawl/guiobject.cpp b/src/Core/Crawl/guiobject.cpp index fdade29..88319e3 100644 --- a/src/Core/Crawl/guiobject.cpp +++ b/src/Core/Crawl/guiobject.cpp @@ -9,11 +9,11 @@ #include -GuiObject::GuiObject(const QString &viewTempalte, QObject *ptr): +GuiObject::GuiObject(const QString &name, const QString &viewTempalte, QObject *ptr): QObject (ptr) { _viewTemplate = viewTempalte; + _className = name; generateId(); - } QString GuiObject::color() const { @@ -33,6 +33,10 @@ void GuiObject::generateId() { _guiId = id++; } +const QString &GuiObject::className() const { + return _className; +} + void GuiObject::reset() { setX(0); setY(0); diff --git a/src/Core/Crawl/guiobject.h b/src/Core/Crawl/guiobject.h index e746dd0..2e4f8a7 100644 --- a/src/Core/Crawl/guiobject.h +++ b/src/Core/Crawl/guiobject.h @@ -15,6 +15,8 @@ #include #include "Crawl/irender.h" +#define DEFAULT_VIEW_TEMPLATE "qrc:/CrawlModule/GraphicItem.qml" + /** * @brief The GuiObject class This base model for gui objects. */ @@ -38,7 +40,9 @@ class CRAWL_EXPORT GuiObject: public QObject, public IRender { public: - GuiObject(const QString& viewTempalte = "qrc:/CrawlModule/GraphicItem.qml", QObject *ptr = nullptr); + GuiObject(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); QString color() const; void setColor(QString color); @@ -97,6 +101,14 @@ public: const QString &mash() const; void setMash(const QString &newMash); + /** + * @brief className This method return class name. + * The class name using as a group of objects on thw world. + * @return class name; + * @note the class name should be sets on the consturctor of child classes of this class. + */ + const QString &className() const; + signals: void guiIdChanged(int guiId); void colorChanged(QString color); @@ -131,6 +143,7 @@ private: QVector3D _size; QQuaternion _ratation; QString _mash; + QString _className; }; #endif // GUIOBJECT_H diff --git a/src/Core/Crawl/iground.cpp b/src/Core/Crawl/iground.cpp index f8c68b4..3a97c55 100644 --- a/src/Core/Crawl/iground.cpp +++ b/src/Core/Crawl/iground.cpp @@ -8,7 +8,10 @@ #include "iground.h" #include "iworld.h" -IGround::IGround() { +IGround::IGround(const QString &name, + const QString &viewTempalte, + QObject *ptr): + IWorldItem(name, viewTempalte, ptr) { } diff --git a/src/Core/Crawl/iground.h b/src/Core/Crawl/iground.h index c60c749..8dbd4b0 100644 --- a/src/Core/Crawl/iground.h +++ b/src/Core/Crawl/iground.h @@ -16,7 +16,9 @@ */ class CRAWL_EXPORT IGround: public IWorldItem { public: - IGround(); + IGround(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); // IRender interface public: diff --git a/src/Core/Crawl/iplayer.cpp b/src/Core/Crawl/iplayer.cpp index 736007c..d1d80ff 100644 --- a/src/Core/Crawl/iplayer.cpp +++ b/src/Core/Crawl/iplayer.cpp @@ -7,7 +7,10 @@ #include "iplayer.h" -IPlayer::IPlayer() { +IPlayer::IPlayer(const QString &name, + const QString &viewTempalte, + QObject *ptr): + IWorldItem(name, viewTempalte, ptr) { } diff --git a/src/Core/Crawl/iplayer.h b/src/Core/Crawl/iplayer.h index 6a88bec..0a3a3dc 100644 --- a/src/Core/Crawl/iplayer.h +++ b/src/Core/Crawl/iplayer.h @@ -20,7 +20,9 @@ class IControl; class CRAWL_EXPORT IPlayer: public IWorldItem { Q_OBJECT public: - IPlayer(); + IPlayer(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); /** * @brief getCurrentStatus This method return current game state of the player. @@ -51,7 +53,7 @@ public: * @param control This is control object. * @note This method can invoked two or more times, for example connect with AI control object and player control object. So your implementation should be contains disconnect methods. */ - virtual void setControl(const IControl* control); + virtual void setControl(const IControl* control) = 0; protected: diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index ecfd158..8f819dc 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -15,6 +15,7 @@ #include "defaultcontrol.h" #include "worldstatus.h" #include "iai.h" +#include "clasteritem.h" IWorld::IWorld() { @@ -31,11 +32,11 @@ IControl *IWorld::initUserInterface() const { void IWorld::render(unsigned int tbfMsec) { for (auto i = _items.begin(); i != _items.end(); ++i) { - (*i).objectPtr->render(tbfMsec); + (*i)->render(tbfMsec); // intersects event. - if ((*i).objectPtr->intersects(*_player)) { - _player->onIntersects((*i).objectPtr); + if ((*i)->intersects(*_player)) { + _player->onIntersects((*i)); } } @@ -85,7 +86,7 @@ void IWorld::setPlayer(QObject *newPlayer) { } _player = newPlayerObject; - addAtomicItem("player", _player); + addAtomicItem(_player); emit playerChanged(); } @@ -106,7 +107,7 @@ IAI *IWorld::initBackGroundAI() const { } IWorldItem *IWorld::getItem(int id) const { - return _items.value(id, {}).objectPtr; + return _items.value(id, nullptr); } bool IWorld::init() { @@ -141,26 +142,57 @@ bool IWorld::init() { void IWorld::clearItems() { for (const auto& item : qAsConst(_items)) { - delete item.objectPtr; + delete item; } _items.clear(); } -void IWorld::addItem(IWorldItem *obj) { +void IWorld::addItem(IWorldItem *obj, QList *addedObjectsList) { + if (!obj) + return; + // Work wih claster if (auto claster = dynamic_cast(obj)) { - - return; + for (auto item : claster->objects()) { + addAtomicItem(item); + if (item && addedObjectsList) { + addedObjectsList->push_back(item->guiId()); + } + } } - // Work With atomic items + + addAtomicItem(obj); + if (addedObjectsList) + addedObjectsList->push_back(obj->guiId()); } -void IWorld::removeItem(int id) { - // Work wih claster +void IWorld::removeItem(int id, QList *removedObjectsList) { + + auto obj = getItem(id); + + if (!obj) + return; + + // Work wih claster + if (auto claster = dynamic_cast(obj)) { + for (auto item : claster->objects()) { + if (!item || item->parentClastersCount()) + continue; + + int id = item->guiId(); + + removeIAtomictem(item); + if (removedObjectsList) + removedObjectsList->push_back(id); + + } + } + + addAtomicItem(obj); + removedObjectsList->push_back(obj->guiId()); - // Work With atomic items } void IWorld::deinit() { @@ -190,34 +222,46 @@ void IWorld::deinit() { } -void IWorld::addAtomicItem(const QString& group, IWorldItem* obj) { - _items.insert(obj->guiId(), WorldObjectWraper{obj, group}); - _itemsGroup.insert(group, obj->guiId()); +void IWorld::addAtomicItem(IWorldItem* obj) { + if (!obj) + return; + + _items.insert(obj->guiId(), obj); + _itemsGroup.insert(obj->className(), obj->guiId()); } bool IWorld::removeIAtomictem(int id) { auto obj = _items.value(id); - if (!obj.objectPtr) { + if (!obj) { return false; } - _itemsGroup.remove(obj.groupName, id); + _itemsGroup.remove(obj->className(), id); _items.remove(id); - delete obj.objectPtr; + delete obj; return true; } -int IWorld::removeAnyAtomicItemFromGroup(const QString &group) { - int anyObjectId = _itemsGroup.value(group); - if (!removeIAtomictem(anyObjectId)) { +bool IWorld::removeIAtomictem(IWorldItem *obj) { + if (!obj) { return false; - } - return anyObjectId; + _itemsGroup.remove(obj->className(), obj->guiId()); + _items.remove(obj->guiId()); + + delete obj; + + return true; +} + +void IWorld::removeAnyItemFromGroup(const QString &group, + QList *removedObjectsList) { + int anyObjectId = _itemsGroup.value(group); + removeItem(anyObjectId, removedObjectsList); } const QQuaternion &IWorld::cameraRatation() const { @@ -272,31 +316,11 @@ void IWorld::worldChanged(const WorldObjects &objects) { if (count > 0) { for ( int i = 0; i < count; ++i ) { - IWorldItem *obj = generate(it.key()); - - TO-Do Add support of clasters. - - obj->initOnWorld(this, _player); - - if (!obj) { - QuasarAppUtils::Params::log("object not created line:" + - QString::fromLatin1(Q_FUNC_INFO), - QuasarAppUtils::Warning); - break; - } - - addAtomicItem(it.key(), obj); - diff.addedIds.append(obj->guiId()); + addItem(generate(it.key()), &diff.addedIds); } } else { for (; count < 0; ++count ) { - int removedObjectId = removeAnyAtomicItemFromGroup(it.key()); - if (!removedObjectId) { - QuasarAppUtils::Params::log("World::changeCountObjects error delete object!", - QuasarAppUtils::Warning); - break; - } - diff.removeIds.append(removedObjectId); + removeAnyItemFromGroup(it.key(), &diff.removeIds); } } } diff --git a/src/Core/Crawl/iworld.h b/src/Core/Crawl/iworld.h index e087e7b..0d5a282 100644 --- a/src/Core/Crawl/iworld.h +++ b/src/Core/Crawl/iworld.h @@ -36,14 +36,6 @@ typedef QMap WorldObjects; */ typedef QMap WorldRule; -/** - * @brief The WorldObjectWraper struct This is simple wraper structure for the internal functionality of the IWorld objects. - */ -struct WorldObjectWraper { - IWorldItem* objectPtr = nullptr; - QString groupName = ""; -}; - /** * @brief The IWorld class use this interface for implementation your own game levels */ @@ -315,20 +307,24 @@ private: /** * @brief addItem This method remove object from the scane. If object are calster then this method remove all child objects. * @param obj pointer to any engine object. + * @param addedObjectsList This is list of added items into world. */ - void addItem(IWorldItem *obj); + void addItem(IWorldItem *obj, + QList* addedObjectsList = nullptr); /** * @brief removeItem This method remove item from the world. If the @a id are id of the claster object then its child object will be removed too. + * @param id This is id of removed object. + * @param removedObjectsList This is list of removed objects. Leave this argument nullptr for ignore this argument. */ - void removeItem(int id); + void removeItem(int id, + QList* removedObjectsList = nullptr); /** * @brief addAtomicItem This method execure atomic operation of add new item. This method support only atomic objects. (not clasters) - * @param group This is group of the atomic object. * @param obj This is pointer to the atomic object. If the object are claster then it will be added without childs objects. */ - void addAtomicItem(const QString &group, IWorldItem *obj); + void addAtomicItem(IWorldItem *obj); /** * @brief removeIAtomictem This method remove object with @a id. This method work with atomic objects only. If you rty remove claster objects then it will be ramoved witohout child objects. @@ -338,14 +334,22 @@ private: bool removeIAtomictem(int id); /** - * @brief removeAnyAtomicItemFromGroup This method remove any object from group and return id of removed object. - * @param group This is name of the objects group - * @return id of removed object. - * @note if object not removed return 0 + * @brief removeIAtomictem This method remove object @a obj. This method work with atomic objects only. If you rty remove claster objects then it will be ramoved witohout child objects. + * @param obj This is id of removed objects. + * @return return true if object remove successul */ - int removeAnyAtomicItemFromGroup(const QString &group); + bool removeIAtomictem(IWorldItem *obj); - QHash _items; + /** + * @brief removeAnyItemFromGroup This method remove any object from group and return id of removed object. If The objec are claster then this method remove all child objects. + * @param group This is name of the objects group + * @param removedObjectsList This is list of removed objcts. + * @return id of removed object. + */ + void removeAnyItemFromGroup(const QString &group, + QList* removedObjectsList = nullptr); + + QHash _items; QMultiHash _itemsGroup; QVector3D _cameraReleativePosition; QQuaternion _cameraRatation; diff --git a/src/Core/Crawl/iworlditem.cpp b/src/Core/Crawl/iworlditem.cpp index 72b809e..9db8175 100644 --- a/src/Core/Crawl/iworlditem.cpp +++ b/src/Core/Crawl/iworlditem.cpp @@ -9,7 +9,10 @@ #include "iworld.h" #include "quasarapp.h" -IWorldItem::IWorldItem() { +IWorldItem::IWorldItem(const QString& name, + const QString& viewTempalte, + QObject *ptr): + GuiObject(name, viewTempalte, ptr) { } diff --git a/src/Core/Crawl/iworlditem.h b/src/Core/Crawl/iworlditem.h index f419741..5f42158 100644 --- a/src/Core/Crawl/iworlditem.h +++ b/src/Core/Crawl/iworlditem.h @@ -17,8 +17,11 @@ class IWorld; */ class CRAWL_EXPORT IWorldItem: public GuiObject { Q_OBJECT + public: - IWorldItem(); + IWorldItem(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); const IWorld *world() const; diff --git a/src/Core/Crawl/singleclasterworlditem.cpp b/src/Core/Crawl/singleclasterworlditem.cpp index 1e5b5ee..418b630 100644 --- a/src/Core/Crawl/singleclasterworlditem.cpp +++ b/src/Core/Crawl/singleclasterworlditem.cpp @@ -10,7 +10,10 @@ #include "singleclasterworlditem.h" #include "quasarapp.h" -SingleClasterWorldItem::SingleClasterWorldItem() { +SingleClasterWorldItem::SingleClasterWorldItem(const QString &name, + const QString &viewTempalte, + QObject *ptr): + ClasterItem(name, viewTempalte, ptr) { } diff --git a/src/Core/Crawl/singleclasterworlditem.h b/src/Core/Crawl/singleclasterworlditem.h index 85227c5..13cf259 100644 --- a/src/Core/Crawl/singleclasterworlditem.h +++ b/src/Core/Crawl/singleclasterworlditem.h @@ -21,7 +21,9 @@ class CRAWL_EXPORT SingleClasterWorldItem: public ClasterItem { Q_OBJECT public: - SingleClasterWorldItem(); + SingleClasterWorldItem(const QString& name, + const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, + QObject *ptr = nullptr); private: diff --git a/src/CrawlTestLvl b/src/CrawlTestLvl index 1b5db3e..e099a72 160000 --- a/src/CrawlTestLvl +++ b/src/CrawlTestLvl @@ -1 +1 @@ -Subproject commit 1b5db3e86f869811ac85b412f6c2392e8524bab9 +Subproject commit e099a72604c4ed58e752664ac5ed0998429acca4 From fb8e23f08f5303b422a0d28aaa4566de3cdc32b0 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 20 Jun 2021 12:48:08 +0300 Subject: [PATCH 6/9] added clasters tests --- src/Core/Crawl/claster.cpp | 2 +- src/Core/Crawl/clasteritem.cpp | 4 +- src/Core/Crawl/iworld.cpp | 21 ++-- src/Core/Crawl/iworld.h | 83 +++++++++++--- src/Core/Crawl/singleclasterworlditem.cpp | 2 - tests/units/clasterstest.cpp | 131 +++++++++++++++++++++- tests/units/clasterstest.h | 14 ++- 7 files changed, 224 insertions(+), 33 deletions(-) diff --git a/src/Core/Crawl/claster.cpp b/src/Core/Crawl/claster.cpp index 0253c98..5f37fa2 100644 --- a/src/Core/Crawl/claster.cpp +++ b/src/Core/Crawl/claster.cpp @@ -23,7 +23,7 @@ Claster::~Claster() { void Claster::add(ClasterItem *object) { _objects.insert(object->guiId(), object); - if (auto singlClasterObject = dynamic_cast(object)) { + if (auto singlClasterObject = dynamic_cast(object)) { singlClasterObject->setClaster(this); } } diff --git a/src/Core/Crawl/clasteritem.cpp b/src/Core/Crawl/clasteritem.cpp index 9ec2d99..6294640 100644 --- a/src/Core/Crawl/clasteritem.cpp +++ b/src/Core/Crawl/clasteritem.cpp @@ -16,8 +16,8 @@ ClasterItem::ClasterItem(const QString &name, } ClasterItem::~ClasterItem() { - if (parentClasters().size() && *parentClasters().begin()) { - (*parentClasters().begin())->remove(this); + for (auto claster : qAsConst(_parentClasters)) { + claster->remove(this); } } diff --git a/src/Core/Crawl/iworld.cpp b/src/Core/Crawl/iworld.cpp index 8f819dc..b5fa62e 100644 --- a/src/Core/Crawl/iworld.cpp +++ b/src/Core/Crawl/iworld.cpp @@ -82,7 +82,7 @@ void IWorld::setPlayer(QObject *newPlayer) { } if (_player) { - removeIAtomictem(_player->guiId()); + removeIAtomicItem(_player->guiId()); } _player = newPlayerObject; @@ -91,6 +91,10 @@ void IWorld::setPlayer(QObject *newPlayer) { emit playerChanged(); } +IWorldItem *IWorld::generate(const QString &objectType) const { + return _registeredTypes.value(objectType, [](){return nullptr;}).operator()(); +} + bool IWorld::stop() { start(); @@ -177,13 +181,14 @@ void IWorld::removeItem(int id, QList *removedObjectsList) { // Work wih claster if (auto claster = dynamic_cast(obj)) { - for (auto item : claster->objects()) { - if (!item || item->parentClastersCount()) + auto copyOfObjectsList = claster->objects(); + for (auto item : copyOfObjectsList) { + if (!item || !item->parentClastersCount()) continue; int id = item->guiId(); - removeIAtomictem(item); + removeIAtomicItem(item); if (removedObjectsList) removedObjectsList->push_back(id); @@ -191,7 +196,8 @@ void IWorld::removeItem(int id, QList *removedObjectsList) { } addAtomicItem(obj); - removedObjectsList->push_back(obj->guiId()); + if (removedObjectsList) + removedObjectsList->push_back(obj->guiId()); } @@ -230,7 +236,7 @@ void IWorld::addAtomicItem(IWorldItem* obj) { _itemsGroup.insert(obj->className(), obj->guiId()); } -bool IWorld::removeIAtomictem(int id) { +bool IWorld::removeIAtomicItem(int id) { auto obj = _items.value(id); if (!obj) { @@ -245,7 +251,7 @@ bool IWorld::removeIAtomictem(int id) { return true; } -bool IWorld::removeIAtomictem(IWorldItem *obj) { +bool IWorld::removeIAtomicItem(IWorldItem *obj) { if (!obj) { return false; } @@ -341,3 +347,4 @@ void IWorld::setWorldStatus(int newWorldStatus) { _worldStatus = newWorldStatus; emit worldStatusChanged(); } + diff --git a/src/Core/Crawl/iworld.h b/src/Core/Crawl/iworld.h index 0d5a282..3eeee9a 100644 --- a/src/Core/Crawl/iworld.h +++ b/src/Core/Crawl/iworld.h @@ -63,11 +63,27 @@ public: /** * @brief initWorldRules The implementation of this interface must be retun initialized list of the world rules. * For more information see the WorldRules map. + * + * Example of use : + * + * ```cpp + * WorldRule *World::initWorldRules() { + * return new WorldRule { + * { + * 0, {{registerObject(), 10}}, + * 100, {{registerObject(), 10}, {registerObject(), 1}}, + * } + * }; + * } + * ``` + * * @return a raw pointer to world a rules map. * @note The Palyer object will be deleted when wold distroed. * So do not delete your created player pbject yuorself. + * + * */ - virtual WorldRule* initWorldRules() const = 0; + virtual WorldRule* initWorldRules() = 0; /** * @brief initUserInterface This method should be return point to userInterface object. @@ -253,25 +269,22 @@ protected: /** * @brief generate This method shold be generate object from the @a objectType. * Override this method for add support yourown objects. + * @note If your objects not requre custom setting then use the default implementation of the generate method. * @param objectType This is string type name of the object, * @return pointer to the object. * * **Example** * ```cpp * IWorldItem* generate(const QString& objectType)) const { - * if (auto obj = IWorld::generate(objectType)) { - * return obj; + * auto registeredObject = IWorld::generate(objectType); + * if (registeredObject) { + * // process creating of object. * } - * - * ... - * // custom implementation - * ... - * - * return nullptr; + * return registeredObject; * } * ``` */ - virtual IWorldItem* generate(const QString& objectType) const = 0; + virtual IWorldItem* generate(const QString& objectType) const; /** * @brief setCameraReleativePosition This method update camera position @@ -285,6 +298,40 @@ protected: */ void setCameraRatation(const QQuaternion &newCameraRatation); + template + + /** + * @brief registerObject This method will register object type for generation on the world. + * + * Example of use: + * + * ```cpp + * ... + * QString className = registerObject(); + * ... + * ``` + * + * @return name of registered class. + */ + QString registerObject() { + + static_assert(std::is_base_of_v, + "You try register no IWorldItem class. Please inherit of IWorldItem class and try again"); + + QString type = Type().className(); + + if (!_registeredTypes.contains(type)) { + + auto wraper = []() { + return new Type(); + }; + + _registeredTypes.insert(type, wraper); + } + + return type; + } + private slots: /** @@ -331,14 +378,14 @@ private: * @param id This is id of removed objects. * @return return true if object remove successul */ - bool removeIAtomictem(int id); + bool removeIAtomicItem(int id); /** - * @brief removeIAtomictem This method remove object @a obj. This method work with atomic objects only. If you rty remove claster objects then it will be ramoved witohout child objects. + * @brief removeIAtomicItem This method remove object @a obj. This method work with atomic objects only. If you rty remove claster objects then it will be ramoved witohout child objects. * @param obj This is id of removed objects. * @return return true if object remove successul */ - bool removeIAtomictem(IWorldItem *obj); + bool removeIAtomicItem(IWorldItem *obj); /** * @brief removeAnyItemFromGroup This method remove any object from group and return id of removed object. If The objec are claster then this method remove all child objects. @@ -359,9 +406,15 @@ private: IPlayer *_player = nullptr; IControl *_userInterface = nullptr; IAI *_backgroundAI = nullptr; - - friend class Engine; int _worldStatus = 0; + QHash> _registeredTypes; + + // engine + friend class Engine; + + // testing + friend class ClastersTest; + }; #endif // IWORLD_H diff --git a/src/Core/Crawl/singleclasterworlditem.cpp b/src/Core/Crawl/singleclasterworlditem.cpp index 418b630..6bada5e 100644 --- a/src/Core/Crawl/singleclasterworlditem.cpp +++ b/src/Core/Crawl/singleclasterworlditem.cpp @@ -19,8 +19,6 @@ SingleClasterWorldItem::SingleClasterWorldItem(const QString &name, void SingleClasterWorldItem::setClaster(Claster *claster) { if (parentClasters().size() > 0) { - debug_assert(parentClasters().size() > 1, "Internal error occured, The singleClaster object have multiple claster parents!!"); - Claster* parent = *parentClasters().begin(); parent->remove(this); removeClaster(parent); diff --git a/tests/units/clasterstest.cpp b/tests/units/clasterstest.cpp index cb989e6..78151f4 100644 --- a/tests/units/clasterstest.cpp +++ b/tests/units/clasterstest.cpp @@ -7,12 +7,137 @@ #include "clasterstest.h" #include +#include +#include +#include +#include -ClastersTest::ClastersTest() -{ +// Test claster object. +class TestClasterObject: public Claster { + +public: + TestClasterObject(): Claster("TestClaster"){}; +protected: + void onIntersects(const IWorldItem *) {}; +}; + +// Test single claster item +class TestClasterSingleItem: public SingleClasterWorldItem { +public: + TestClasterSingleItem(): SingleClasterWorldItem("TestClasterSingleItem"){}; +protected: + void onIntersects(const IWorldItem *) {}; +}; + +// Test claster item +class TestClasterItem: public ClasterItem { +public: + TestClasterItem(): ClasterItem("TestClasterItem"){}; +protected: + void onIntersects(const IWorldItem *) {}; +}; + +// Test world of clasters +class TestWorld: public IWorld { +public: + TestWorld(): IWorld(){}; + + // IWorld interface +public: + IPlayer *initPlayer() const {return nullptr;}; + WorldRule *initWorldRules() {return nullptr;}; + QString initHdrBackGround() const {return "";}; + QString description() const {return "";}; + QString imagePreview() const {return "";}; + QString name() const {return "TestWorld";}; + int costToUnlock() const {return 0;}; + + friend class ClastersTest; +}; + +ClastersTest::ClastersTest() { } void ClastersTest::test() { - QVERIFY(false); + // test clasters + testOneClaster(); + testClastersWithWorld(); +} + +void ClastersTest::testOneClaster() const { + TestClasterItem item; + TestClasterSingleItem singleItem; + + // life of the clasters + { + TestClasterObject claster, claster2; + + // Add items to first clasters + claster.add(&item); + claster.add(&singleItem); + + // in the first claster should be 2 objects + QVERIFY(claster.objects().size() == 2); + + // item sould be contains oly one parents claster object. + QVERIFY(item.parentClastersCount() == 1); + QVERIFY(singleItem.parentClastersCount() == 1); + + // Add items into second claster object + claster2.add(&item); + claster2.add(&singleItem); + + // in the second claster should be 2 objects + QVERIFY(claster2.objects().size() == 2); + // but first claster should be contains only one claster item because the singleclater item cannot are child of the two clasters. + QVERIFY(claster.objects().size() == 1); + + // item sould be contains two parents claster object. + + QVERIFY(item.parentClastersCount() == 2); + // item sould be contains oly one parents claster object. + QVERIFY(singleItem.parentClastersCount() == 1); + } + + // after distrou clasters objects the parents list size should be equals 0 + QVERIFY(item.parentClastersCount() == 0); + QVERIFY(singleItem.parentClastersCount() == 0); + +} + +void ClastersTest::testClastersWithWorld() const { + TestWorld world; + TestClasterObject *claster = new TestClasterObject(), + *claster2 = new TestClasterObject(); + + TestClasterItem *item = new TestClasterItem(), + *item2 = new TestClasterItem; + + // Add to first claster two items. + claster->add(item); + claster->add(item2); + + // The claster 2 contains item 2 only. + claster2->add(item2); + + // Add claster item to world + world.addItem(claster); + + // After adding claster object ito world child objects should be addeed automaticaly + QVERIFY(world._items.size() == 3); + + // add second claster ot world + world.addItem(claster2); + + QVERIFY(world._items.size() == 4); + + // remove claster with 2 items from world + world.removeItem(claster->guiId()); + + // after removing claster ovject child items should be removed too. but ony items that contains one parent claster. + QVERIFY(world._items.size() == 2); + + world.removeItem(claster2->guiId()); + } diff --git a/tests/units/clasterstest.h b/tests/units/clasterstest.h index 34f1e3e..436326f 100644 --- a/tests/units/clasterstest.h +++ b/tests/units/clasterstest.h @@ -18,10 +18,18 @@ class ClastersTest: public Test, protected TestUtils { public: ClastersTest(); - - // Test interface -public: void test() override; +private: + + /** + * @brief testOneClaster This test check functionality of the claster class. + */ + void testOneClaster() const; + + /** + * @brief testClastersWithWorld This test check clasters integrarion on the world + */ + void testClastersWithWorld() const; }; #endif // CLASTERSTEST_H From b14abf1f3d056137925529888585d6601c43e969 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 20 Jun 2021 12:49:12 +0300 Subject: [PATCH 7/9] update test lvl --- src/CrawlTestLvl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CrawlTestLvl b/src/CrawlTestLvl index e099a72..3f8198a 160000 --- a/src/CrawlTestLvl +++ b/src/CrawlTestLvl @@ -1 +1 @@ -Subproject commit e099a72604c4ed58e752664ac5ed0998429acca4 +Subproject commit 3f8198a0767f860fa17fed86f6772f09462077fa From c683e8eb46a46569fa0e0109f5b437718bb606f2 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 20 Jun 2021 18:39:04 +0300 Subject: [PATCH 8/9] fix windows build --- src/Core/Crawl/clasteritem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Crawl/clasteritem.h b/src/Core/Crawl/clasteritem.h index 59d5bcf..503b1c4 100644 --- a/src/Core/Crawl/clasteritem.h +++ b/src/Core/Crawl/clasteritem.h @@ -19,7 +19,7 @@ class Claster; * @brief The ClasterItem class This is item of the claster object. Thi class can be used as a one element of the claster class. * @note This object invoke the Claster::remove method in destructor. */ -class ClasterItem: public IWorldItem +class CRAWL_EXPORT ClasterItem: public IWorldItem { Q_OBJECT public: From 4870c3f16928233fabd6839f0165b7f538f42555 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 20 Jun 2021 18:50:50 +0300 Subject: [PATCH 9/9] check statuses --- src/Core/Crawl/singleclasterworlditem.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Core/Crawl/singleclasterworlditem.h b/src/Core/Crawl/singleclasterworlditem.h index 13cf259..875cef9 100644 --- a/src/Core/Crawl/singleclasterworlditem.h +++ b/src/Core/Crawl/singleclasterworlditem.h @@ -24,7 +24,6 @@ public: SingleClasterWorldItem(const QString& name, const QString& viewTempalte = DEFAULT_VIEW_TEMPLATE, QObject *ptr = nullptr); - private: /**