File indexing completed on 2024-05-19 05:40:49

0001 /***************************************************************************
0002  *  Copyright (C) 2020 by Renaud Guezennec                               *
0003  *   http://www.rolisteam.org/contact                                      *
0004  *                                                                         *
0005  *   This software is free software; you can redistribute it and/or modify *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "updater/media/vmapupdater.h"
0021 
0022 #include <QDebug>
0023 #include <QMetaObject>
0024 #include <QMetaProperty>
0025 #include <QSet>
0026 #include <QTimer>
0027 
0028 #include "controller/item_controllers/vmapitemfactory.h"
0029 #include "controller/view_controller/vectorialmapcontroller.h"
0030 #include "data/campaignmanager.h"
0031 #include "model/contentmodel.h"
0032 #include "worker/vectorialmapmessagehelper.h"
0033 
0034 #include "updater/vmapitem/characteritemupdater.h"
0035 #include "updater/vmapitem/ellipsecontrollerupdater.h"
0036 #include "updater/vmapitem/imagecontrollerupdater.h"
0037 #include "updater/vmapitem/linecontrollerupdater.h"
0038 #include "updater/vmapitem/pathcontrollerupdater.h"
0039 #include "updater/vmapitem/rectcontrollerupdater.h"
0040 #include "updater/vmapitem/sightupdater.h"
0041 #include "updater/vmapitem/textcontrollerupdater.h"
0042 #include "updater/vmapitem/vmapitemcontrollerupdater.h"
0043 
0044 VectorialMapController* findMap(const std::vector<VectorialMapController*>& vmaps, const QString& id)
0045 {
0046     auto it
0047         = std::find_if(vmaps.begin(), vmaps.end(), [id](VectorialMapController* ctrl) { return ctrl->uuid() == id; });
0048     if(vmaps.end() == it)
0049         return nullptr;
0050     return (*it);
0051 }
0052 
0053 VMapUpdater::VMapUpdater(campaign::CampaignManager* manager, FilteredContentModel* model, QObject* parent)
0054     : MediaUpdaterInterface(manager, parent)
0055     , m_vmapModel(model)
0056     , m_diceParser(manager ? manager->diceparser() : nullptr)
0057 {
0058     m_updaters.insert(
0059         {vmap::VisualItemController::LINE, std::unique_ptr<LineControllerUpdater>(new LineControllerUpdater)});
0060     m_updaters.insert(
0061         {vmap::VisualItemController::PATH, std::unique_ptr<PathControllerUpdater>(new PathControllerUpdater)});
0062     m_updaters.insert(
0063         {vmap::VisualItemController::RECT, std::unique_ptr<RectControllerUpdater>(new RectControllerUpdater)});
0064     m_updaters.insert(
0065         {vmap::VisualItemController::IMAGE, std::unique_ptr<ImageControllerUpdater>(new ImageControllerUpdater)});
0066     m_updaters.insert(
0067         {vmap::VisualItemController::CHARACTER, std::unique_ptr<CharacterItemUpdater>(new CharacterItemUpdater)});
0068     m_updaters.insert(
0069         {vmap::VisualItemController::ELLIPSE, std::unique_ptr<EllipseControllerUpdater>(new EllipseControllerUpdater)});
0070     m_updaters.insert(
0071         {vmap::VisualItemController::TEXT, std::unique_ptr<TextControllerUpdater>(new TextControllerUpdater)});
0072     m_updaters.insert({vmap::VisualItemController::SIGHT, std::unique_ptr<SightUpdater>(new SightUpdater)});
0073 
0074     ReceiveEvent::registerNetworkReceiver(NetMsg::VMapCategory, this);
0075 }
0076 
0077 void VMapUpdater::addMediaController(MediaControllerBase* base)
0078 {
0079     if(nullptr == base)
0080         return;
0081 
0082     auto ctrl= dynamic_cast<VectorialMapController*>(base);
0083 
0084     if(ctrl == nullptr)
0085         return;
0086 
0087     ctrl->setDiceParser(m_diceParser);
0088 
0089     connect(ctrl, &VectorialMapController::collisionChanged, this,
0090             [this, ctrl]() { sendOffChanges<bool>(ctrl, QStringLiteral("collision")); });
0091     connect(ctrl, &VectorialMapController::characterVisionChanged, this,
0092             [this, ctrl]() { sendOffChanges<bool>(ctrl, QStringLiteral("characterVision")); });
0093     connect(ctrl, &VectorialMapController::gridColorChanged, this,
0094             [this, ctrl]() { sendOffChanges<QColor>(ctrl, QStringLiteral("gridColor")); });
0095     connect(ctrl, &VectorialMapController::gridScaleChanged, this,
0096             [this, ctrl]() { sendOffChanges<qreal>(ctrl, QStringLiteral("gridScale")); });
0097     connect(ctrl, &VectorialMapController::gridSizeChanged, this,
0098             [this, ctrl]() { sendOffChanges<int>(ctrl, QStringLiteral("gridSize")); });
0099     connect(ctrl, &VectorialMapController::gridVisibilityChanged, this,
0100             [this, ctrl]() { sendOffChanges<bool>(ctrl, QStringLiteral("gridVisibility")); });
0101     connect(ctrl, &VectorialMapController::gridAboveChanged, this,
0102             [this, ctrl]() { sendOffChanges<bool>(ctrl, QStringLiteral("gridAbove")); });
0103     connect(ctrl, &VectorialMapController::scaleUnitChanged, this,
0104             [this, ctrl]() { sendOffChanges<Core::ScaleUnit>(ctrl, QStringLiteral("scaleUnit")); });
0105     connect(ctrl, &VectorialMapController::permissionChanged, this,
0106             [this, ctrl]() { sendOffChanges<Core::PermissionMode>(ctrl, QStringLiteral("permission")); });
0107     connect(ctrl, &VectorialMapController::gridPatternChanged, this,
0108             [this, ctrl]() { sendOffChanges<Core::GridPattern>(ctrl, QStringLiteral("gridPattern")); });
0109     connect(ctrl, &VectorialMapController::visibilityChanged, this,
0110             [this, ctrl]() { sendOffChanges<Core::VisibilityMode>(ctrl, QStringLiteral("visibility")); });
0111     connect(ctrl, &VectorialMapController::backgroundColorChanged, this,
0112             [this, ctrl]() { sendOffChanges<QColor>(ctrl, QStringLiteral("backgroundColor")); });
0113     connect(ctrl, &VectorialMapController::layerChanged, this,
0114             [this, ctrl]() { sendOffChanges<Core::Layer>(ctrl, QStringLiteral("layer")); });
0115     connect(ctrl, &VectorialMapController::zIndexChanged, this,
0116             [this, ctrl]() { sendOffChanges<int>(ctrl, QStringLiteral("zIndex")); });
0117 
0118     connect(ctrl, &VectorialMapController::sendOffHighLightAt, this,
0119             [ctrl](const QPointF& p, const qreal& penSize, const QColor& color)
0120             { VectorialMapMessageHelper::sendOffHighLight(p, penSize, color, ctrl->uuid()); });
0121 
0122     connect(ctrl, &VectorialMapController::visualItemControllerCreated, this,
0123             [this](vmap::VisualItemController* itemCtrl)
0124             {
0125                 auto type= itemCtrl->itemType();
0126                 auto mapCtrl= itemCtrl->mapController();
0127 
0128                 if(!mapCtrl)
0129                     return;
0130 
0131                 auto it= m_updaters.find(type);
0132 
0133                 if(it == m_updaters.end())
0134                     return;
0135 
0136                 auto updater= it->second.get();
0137                 if(updater && mapCtrl->editionMode() == Core::EditionMode::Painting)
0138                     updater->addItemController(itemCtrl);
0139             });
0140     connect(ctrl, &VectorialMapController::visualItemControllersRemoved, this,
0141             [ctrl](const QStringList& list) { VectorialMapMessageHelper::sendOffRemoveItems(list, ctrl->uuid()); });
0142 
0143     auto it= m_updaters.find(vmap::VisualItemController::SIGHT);
0144     if(it != std::end(m_updaters))
0145     {
0146         auto updater= it->second.get();
0147         if(updater)
0148             updater->addItemController(ctrl->sightController());
0149     }
0150 
0151     auto const& items= ctrl->model()->items();
0152     std::for_each(std::begin(items), std::end(items),
0153                   [this](vmap::VisualItemController* itemCtrl)
0154                   {
0155                       auto type= itemCtrl->itemType();
0156                       auto mapCtrl= itemCtrl->mapController();
0157 
0158                       if(!mapCtrl)
0159                           return;
0160 
0161                       auto it= m_updaters.find(type);
0162 
0163                       if(it == m_updaters.end())
0164                           return;
0165 
0166                       auto updater= it->second.get();
0167                       if(updater && mapCtrl->editionMode() == Core::EditionMode::Painting)
0168                           updater->addItemController(itemCtrl, false);
0169                   });
0170 
0171     if(!ctrl->remote())
0172     {
0173         connect(ctrl, &VectorialMapController::modifiedChanged, this,
0174                 [ctrl, this]()
0175                 {
0176                     if(ctrl->modified())
0177                     {
0178                         saveMediaController(ctrl);
0179                     }
0180                 });
0181         QTimer::singleShot(1000, ctrl, [ctrl, this]() { saveMediaController(ctrl); });
0182     }
0183 }
0184 
0185 bool VMapUpdater::updateVMapProperty(NetworkMessageReader* msg, VectorialMapController* ctrl)
0186 {
0187     if(nullptr == msg || nullptr == ctrl)
0188         return false;
0189 
0190     updatingCtrl= ctrl;
0191 
0192     auto property= msg->string16();
0193 
0194     QVariant var;
0195     QSet<QString> boolProperties(
0196         {QString("collision"), QString("characterVision"), QString("gridVisibility"), QString("gridAbove")});
0197     QSet<QString> colorProperties({QString("backgroundColor"), QString("gridColor")});
0198     QSet<QString> uint8Properties(
0199         {QString("scaleUnit"), QString("permission"), QString("gridPattern"), QString("visibility"), QString("layer")});
0200     QSet<QString> intProperties({QString("zIndex"), QString("gridSize")});
0201     QSet<QString> realProperties({QString("gridScale")});
0202 
0203     if(boolProperties.contains(property))
0204     {
0205         var= QVariant::fromValue(static_cast<bool>(msg->uint8()));
0206     }
0207     else if(colorProperties.contains(property))
0208     {
0209         var= QVariant::fromValue(QColor(msg->rgb()));
0210     }
0211     else if(intProperties.contains(property))
0212     {
0213         var= QVariant::fromValue(msg->int64());
0214     }
0215     else if(realProperties.contains(property))
0216     {
0217         var= QVariant::fromValue(msg->real());
0218     }
0219     else if(uint8Properties.contains(property))
0220     {
0221         auto value= msg->uint8();
0222         if(property == QStringLiteral("scaleUnit"))
0223         {
0224             var= QVariant::fromValue(static_cast<Core::ScaleUnit>(value));
0225         }
0226         else if(property == QStringLiteral("scaleUnit"))
0227         {
0228             var= QVariant::fromValue(static_cast<Core::ScaleUnit>(value));
0229         }
0230         else if(property == QStringLiteral("permission"))
0231         {
0232             var= QVariant::fromValue(static_cast<Core::PermissionMode>(value));
0233         }
0234         else if(property == QStringLiteral("gridPattern"))
0235         {
0236             var= QVariant::fromValue(static_cast<Core::GridPattern>(value));
0237         }
0238         else if(property == QStringLiteral("visibility"))
0239         {
0240             var= QVariant::fromValue(static_cast<Core::VisibilityMode>(value));
0241         }
0242         else if(property == QStringLiteral("layer"))
0243         {
0244             var= QVariant::fromValue(static_cast<Core::Layer>(value));
0245         }
0246     }
0247     else if(uint8Properties.contains(property))
0248     {
0249         var= QVariant::fromValue(msg->int64());
0250     }
0251     else
0252     {
0253         auto val= msg->string32();
0254         var= QVariant::fromValue(val);
0255     }
0256 
0257     m_updatingFromNetwork= true;
0258     auto feedback= ctrl->setProperty(property.toLocal8Bit().data(), var);
0259     m_updatingFromNetwork= false;
0260     updatingCtrl= nullptr;
0261 
0262     return feedback;
0263 }
0264 
0265 NetWorkReceiver::SendType VMapUpdater::processMessage(NetworkMessageReader* msg)
0266 {
0267     NetWorkReceiver::SendType type= NetWorkReceiver::NONE;
0268     QString vmapId= msg->string8();
0269     auto map= findMap(m_vmapModel->contentController<VectorialMapController*>(), vmapId);
0270     if(nullptr == map)
0271     {
0272         qWarning() << QString("Map with id %1 has not been found").arg(vmapId);
0273         return type;
0274     }
0275 
0276     if(is(msg, NetMsg::MediaCategory, NetMsg::UpdateMediaProperty))
0277     {
0278         updateVMapProperty(msg, map);
0279     }
0280     else if(is(msg, NetMsg::VMapCategory, NetMsg::AddItem))
0281     {
0282         auto item= vmap::VmapItemFactory::createRemoteVMapItem(map, msg);
0283         map->addRemoteItem(item);
0284     }
0285     else if(is(msg, NetMsg::VMapCategory, NetMsg::UpdateItem)
0286             || is(msg, NetMsg::VMapCategory, NetMsg::CharacterVisionChanged))
0287     {
0288         auto itemType= static_cast<vmap::VisualItemController::ItemType>(msg->uint8());
0289         QString itemId= msg->string8();
0290         auto itemCtrl= map->itemController(itemId);
0291         auto it= m_updaters.find(itemType);
0292         if(it != m_updaters.end())
0293         {
0294             it->second->updateItemProperty(msg, itemCtrl);
0295         }
0296     }
0297     else if(is(msg, NetMsg::VMapCategory, NetMsg::HighLightPosition))
0298     {
0299         VectorialMapMessageHelper::readHighLight(map, msg);
0300     }
0301     else if(is(msg, NetMsg::VMapCategory, NetMsg::DeleteItem))
0302     {
0303         auto list= VectorialMapMessageHelper::readRemoveItems(msg);
0304         QSet<QString> ids{list.begin(), list.end()};
0305         map->removeItemController(ids, true);
0306     }
0307     return type;
0308 }