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 }