diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 8a7e94391..b952c9e46 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -143,6 +143,7 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player) duringMovement = false; ignoreEvents = false; + numOfMovedArts = 0; } CPlayerInterface::~CPlayerInterface() @@ -2149,21 +2150,28 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->infoBar->showSelection(); + + bool redraw = true; + // If a bulk transfer has arrived, then redrawing only the last art movement. + if(numOfMovedArts != 0) + { + numOfMovedArts--; + if(numOfMovedArts != 0) + redraw = false; + } + for(auto isa : GH.listInt) { auto artWin = dynamic_cast(isa.get()); if (artWin) - artWin->artifactMoved(src, dst); + artWin->artifactMoved(src, dst, redraw); } - if(!GH.objsToBlit.empty()) - GH.objsToBlit.back()->redraw(); - waitWhileDialog(); } -void CPlayerInterface::artifactPossibleAssembling(const ArtifactLocation & dst) +void CPlayerInterface::bulkArtMovementStart(size_t numOfArts) { - askToAssembleArtifact(dst); + numOfMovedArts = numOfArts; } void CPlayerInterface::artifactAssembled(const ArtifactLocation &al) diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 01dfff7fe..68bd37e3f 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -131,8 +131,9 @@ public: void artifactPut(const ArtifactLocation &al) override; void artifactRemoved(const ArtifactLocation &al) override; void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) override; + void bulkArtMovementStart(size_t numOfArts) override; void artifactAssembled(const ArtifactLocation &al) override; - void artifactPossibleAssembling(const ArtifactLocation & dst) override; + void askToAssembleArtifact(const ArtifactLocation & dst) override; void artifactDisassembled(const ArtifactLocation &al) override; void heroVisit(const CGHeroInstance * visitor, const CGObjectInstance * visitedObj, bool start) override; @@ -276,10 +277,10 @@ private: bool duringMovement; bool ignoreEvents; + size_t numOfMovedArts; void doMoveHero(const CGHeroInstance *h, CGPath path); void setMovementStatus(bool value); - void askToAssembleArtifact(const ArtifactLocation &al); }; extern CPlayerInterface * LOCPLINT; diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 5ef04afdb..f4811ffe9 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -268,7 +268,7 @@ void ApplyClientNetPackVisitor::visitMoveArtifact(MoveArtifact & pack) { callInterfaceIfPresent(cl, player, &IGameEventsReceiver::artifactMoved, pack.src, pack.dst); if(pack.askAssemble) - callInterfaceIfPresent(cl, player, &IGameEventsReceiver::artifactPossibleAssembling, pack.dst); + callInterfaceIfPresent(cl, player, &IGameEventsReceiver::askToAssembleArtifact, pack.dst); }; moveArtifact(pack.src.owningPlayer()); @@ -284,12 +284,14 @@ void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack) { auto srcLoc = ArtifactLocation(pack.srcArtHolder, slotToMove.srcPos); auto dstLoc = ArtifactLocation(pack.dstArtHolder, slotToMove.dstPos); - callInterfaceIfPresent(cl, srcLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); - if(srcLoc.owningPlayer() != dstLoc.owningPlayer()) - callInterfaceIfPresent(cl, dstLoc.owningPlayer(), &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); + MoveArtifact ma(&srcLoc, &dstLoc, false); + visitMoveArtifact(ma); } }; + // Begin a session of bulk movement of arts. It is not necessary but useful for the client optimization. + callInterfaceIfPresent(cl, cl.getCurrentPlayer(), &IGameEventsReceiver::bulkArtMovementStart, + pack.artsPack0.size() + pack.artsPack1.size()); applyMove(pack.artsPack0); if(pack.swap) applyMove(pack.artsPack1); diff --git a/client/widgets/CArtifactHolder.cpp b/client/widgets/CArtifactHolder.cpp index a2c7eb81d..e8a685976 100644 --- a/client/widgets/CArtifactHolder.cpp +++ b/client/widgets/CArtifactHolder.cpp @@ -471,13 +471,14 @@ void CArtifactsOfHero::scrollBackpack(int dir) * * @param art Artifact checked against. */ -void CArtifactsOfHero::markPossibleSlots(const CArtifactInstance* art) +void CArtifactsOfHero::markPossibleSlots(const CArtifactInstance* art, bool withRedraw) { for(CArtifactsOfHero *aoh : commonInfo->participants) for(auto p : aoh->artWorn) p.second->selectSlot(art->canBePutAt(ArtifactLocation(aoh->curHero, p.second->slotID), true)); - safeRedraw(); + if(withRedraw) + safeRedraw(); } /** @@ -489,7 +490,7 @@ void CArtifactsOfHero::unmarkSlots(bool withRedraw) for(CArtifactsOfHero *aoh : commonInfo->participants) aoh->unmarkLocalSlots(false); else - unmarkLocalSlots(false);\ + unmarkLocalSlots(false); if(withRedraw) safeRedraw(); @@ -546,7 +547,6 @@ CArtifactsOfHero::CArtifactsOfHero(ArtPlaceMap ArtWorn, std::vector backpack(Backpack), backpackPos(0), commonInfo(nullptr), - updateState(false), leftArtRoll(leftScroll), rightArtRoll(rightScroll), allowedAssembling(true), @@ -580,7 +580,6 @@ CArtifactsOfHero::CArtifactsOfHero(const Point & position, bool createCommonPart : curHero(nullptr), backpackPos(0), commonInfo(nullptr), - updateState(false), allowedAssembling(true), highlightModeCallback(nullptr) { @@ -644,26 +643,13 @@ CArtifactsOfHero::~CArtifactsOfHero() void CArtifactsOfHero::updateParentWindow() { - if (CHeroWindow* chw = dynamic_cast(GH.topInt().get())) + if(CHeroWindow * chw = dynamic_cast(GH.topInt().get())) { - if(updateState) - chw->curHero = curHero; - else - chw->update(curHero, true); + chw->update(curHero, true); } - else if(CExchangeWindow* cew = dynamic_cast(GH.topInt().get())) + else if(CExchangeWindow * cew = dynamic_cast(GH.topInt().get())) { - //use our copy of hero to draw window - if(cew->heroInst[0]->id == curHero->id) - cew->heroInst[0] = curHero; - else - cew->heroInst[1] = curHero; - - if(!updateState) - { - cew->updateWidgets(); - cew->redraw(); - } + cew->updateWidgets(); } } @@ -686,7 +672,7 @@ void CArtifactsOfHero::realizeCurrentTransaction() ArtifactLocation(commonInfo->dst.AOH->curHero, commonInfo->dst.slotID)); } -void CArtifactsOfHero::artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst) +void CArtifactsOfHero::artifactMoved(const ArtifactLocation & src, const ArtifactLocation & dst, bool withUIUpdate) { bool isCurHeroSrc = src.isHolder(curHero), isCurHeroDst = dst.isHolder(curHero); @@ -714,7 +700,8 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation & src, const Artifac auto art = curHero->getArt(ArtifactPosition::TRANSITION_POS); assert(art); CCS->curh->dragAndDropCursor("artifact", art->artType->getIconIndex()); - markPossibleSlots(art); + if(withUIUpdate) + markPossibleSlots(art); commonInfo->src.art = art; commonInfo->src.slotID = src.slot; @@ -752,17 +739,20 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation & src, const Artifac assert(commonInfo->src.AOH); CCS->curh->dragAndDropCursor("artifact", dst.getArt()->artType->getIconIndex()); } - if(!curHero->artifactsTransitionPos.empty()) + if(!curHero->artifactsTransitionPos.empty() && withUIUpdate) { markPossibleSlots(curHero->getArt(ArtifactPosition::TRANSITION_POS)); } } - updateParentWindow(); - // If backpack is changed, update it - if((isCurHeroSrc && ArtifactUtils::isSlotBackpack(src.slot)) - || (isCurHeroDst && ArtifactUtils::isSlotBackpack(dst.slot))) - scrollBackpack(0); + if(withUIUpdate) + { + updateParentWindow(); + // If backpack is changed, update it + if((isCurHeroSrc && ArtifactUtils::isSlotBackpack(src.slot)) + || (isCurHeroDst && ArtifactUtils::isSlotBackpack(dst.slot))) + scrollBackpack(0); + } } void CArtifactsOfHero::artifactRemoved(const ArtifactLocation &al) @@ -806,9 +796,9 @@ void CArtifactsOfHero::artifactUpdateSlots(const ArtifactLocation & al) if(al.isHolder(curHero)) { if(ArtifactUtils::isSlotBackpack(al.slot)) - updateBackpackSlots(); + updateBackpackSlots(true); else - updateWornSlots(); + updateWornSlots(true); } } @@ -872,7 +862,7 @@ void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation &artLoc) } } -void CWindowWithArtifacts::artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc) +void CWindowWithArtifacts::artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc, bool withRedraw) { CArtifactsOfHero * destaoh = nullptr; @@ -881,8 +871,7 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation &artLoc, const A std::shared_ptr realPtr = artSetWeak.lock(); if(realPtr) { - realPtr->artifactMoved(artLoc, destLoc); - realPtr->redraw(); + realPtr->artifactMoved(artLoc, destLoc, withRedraw); if(destLoc.isHolder(realPtr->getHero())) destaoh = realPtr.get(); } @@ -922,17 +911,12 @@ void CArtifactsOfHero::SCommonPart::Artpos::clear() art = nullptr; } -CArtifactsOfHero::SCommonPart::Artpos::Artpos() -{ - clear(); -} - void CArtifactsOfHero::SCommonPart::Artpos::setTo(const CHeroArtPlace *place, bool dontTakeBackpack) { slotID = place->slotID; AOH = place->ourOwner; - if(slotID >= 19 && dontTakeBackpack) + if(ArtifactUtils::isSlotBackpack(slotID) && dontTakeBackpack) art = nullptr; else art = place->ourArt; diff --git a/client/widgets/CArtifactHolder.h b/client/widgets/CArtifactHolder.h index 9ff040f4e..9cc72b524 100644 --- a/client/widgets/CArtifactHolder.h +++ b/client/widgets/CArtifactHolder.h @@ -27,7 +27,7 @@ public: CArtifactHolder(); virtual void artifactRemoved(const ArtifactLocation &artLoc)=0; - virtual void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc)=0; + virtual void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc, bool withRedraw)=0; virtual void artifactDisassembled(const ArtifactLocation &artLoc)=0; virtual void artifactAssembled(const ArtifactLocation &artLoc)=0; }; @@ -114,7 +114,6 @@ public: const CArtifactsOfHero *AOH; const CArtifactInstance *art; - Artpos(); void clear(); void setTo(const CHeroArtPlace *place, bool dontTakeBackpack); bool valid(); @@ -127,8 +126,6 @@ public: }; std::shared_ptr commonInfo; //when we have more than one CArtifactsOfHero in one window with exchange possibility, we use this (eg. in exchange window); to be provided externally - bool updateState; // Whether the commonInfo should be updated on setHero or not. - std::shared_ptr leftArtRoll; std::shared_ptr rightArtRoll; bool allowedAssembling; @@ -137,7 +134,7 @@ public: std::function highlightModeCallback; //if set, clicking on art place doesn't pick artifact but highlights the slot and calls this function void realizeCurrentTransaction(); //calls callback with parameters stored in commonInfo - void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst); + void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst, bool withUIUpdate); void artifactRemoved(const ArtifactLocation &al); void artifactUpdateSlots(const ArtifactLocation &al); ArtPlacePtr getArtPlace(ArtifactPosition slot);//may return null @@ -151,11 +148,11 @@ public: void deactivate() override; void safeRedraw(); - void markPossibleSlots(const CArtifactInstance* art); - void unmarkSlots(bool withRedraw = true); //unmarks slots in all visible AOHs - void unmarkLocalSlots(bool withRedraw = true); //unmarks slots in that particular AOH - void updateWornSlots(bool redrawParent = true); - void updateBackpackSlots(bool redrawParent = true); + void markPossibleSlots(const CArtifactInstance * art, bool withRedraw = false); + void unmarkSlots(bool withRedraw = false); //unmarks slots in all visible AOHs + void unmarkLocalSlots(bool withRedraw = false); //unmarks slots in that particular AOH + void updateWornSlots(bool redrawParent = false); + void updateBackpackSlots(bool redrawParent = false); void updateSlot(ArtifactPosition i); @@ -189,7 +186,7 @@ public: std::shared_ptr getCommonPart(); void artifactRemoved(const ArtifactLocation &artLoc) override; - void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc) override; + void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc, bool withRedraw) override; void artifactDisassembled(const ArtifactLocation &artLoc) override; void artifactAssembled(const ArtifactLocation &artLoc) override; }; diff --git a/client/windows/CKingdomInterface.cpp b/client/windows/CKingdomInterface.cpp index bce12e3c5..c4e142fdf 100644 --- a/client/windows/CKingdomInterface.cpp +++ b/client/windows/CKingdomInterface.cpp @@ -668,10 +668,10 @@ void CKingdomInterface::artifactDisassembled(const ArtifactLocation& artLoc) arts->artifactDisassembled(artLoc); } -void CKingdomInterface::artifactMoved(const ArtifactLocation& artLoc, const ArtifactLocation& destLoc) +void CKingdomInterface::artifactMoved(const ArtifactLocation& artLoc, const ArtifactLocation& destLoc, bool withRedraw) { if(auto arts = std::dynamic_pointer_cast(tabArea->getItem())) - arts->artifactMoved(artLoc, destLoc); + arts->artifactMoved(artLoc, destLoc, withRedraw); } void CKingdomInterface::artifactRemoved(const ArtifactLocation& artLoc) diff --git a/client/windows/CKingdomInterface.h b/client/windows/CKingdomInterface.h index 8d0eb899e..9d8448a71 100644 --- a/client/windows/CKingdomInterface.h +++ b/client/windows/CKingdomInterface.h @@ -251,7 +251,7 @@ public: void townChanged(const CGTownInstance *town); void updateGarrisons() override; void artifactRemoved(const ArtifactLocation &artLoc) override; - void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc) override; + void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc, bool withRedraw) override; void artifactDisassembled(const ArtifactLocation &artLoc) override; void artifactAssembled(const ArtifactLocation &artLoc) override; }; diff --git a/lib/IGameEventsReceiver.h b/lib/IGameEventsReceiver.h index 6b47b3023..cc9964efc 100644 --- a/lib/IGameEventsReceiver.h +++ b/lib/IGameEventsReceiver.h @@ -90,7 +90,8 @@ public: virtual void artifactAssembled(const ArtifactLocation &al){}; virtual void artifactDisassembled(const ArtifactLocation &al){}; virtual void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst){}; - virtual void artifactPossibleAssembling(const ArtifactLocation & dst) {}; + virtual void bulkArtMovementStart(size_t numOfArts) {}; + virtual void askToAssembleArtifact(const ArtifactLocation & dst) {}; virtual void heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start){}; virtual void heroCreated(const CGHeroInstance*){};