File: CArtifactHolder.h

package info (click to toggle)
vcmi 0.99%2Bdfsg%2Bgit20190113.f06c8a87-1
  • links: PTS, VCS
  • area: contrib
  • in suites: buster
  • size: 11,096 kB
  • sloc: cpp: 142,605; sh: 315; objc: 248; makefile: 32; ansic: 28; python: 13
file content (189 lines) | stat: -rw-r--r-- 6,550 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*
 * CArtifactHolder.h, part of VCMI engine
 *
 * Authors: listed in file AUTHORS in main folder
 *
 * License: GNU General Public License v2.0 or later
 * Full text of license available in license.txt file, in main folder
 *
 */
#pragma once

#include "MiscWidgets.h"

class CArtifactsOfHero;
class CAnimImage;
class CButton;

struct ArtifactLocation;

class CArtifactHolder
{
public:
	CArtifactHolder();

	virtual void artifactRemoved(const ArtifactLocation &artLoc)=0;
	virtual void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc)=0;
	virtual void artifactDisassembled(const ArtifactLocation &artLoc)=0;
	virtual void artifactAssembled(const ArtifactLocation &artLoc)=0;
};

class CArtPlace : public LRClickableAreaWTextComp
{
protected:
	std::shared_ptr<CAnimImage> image;
	virtual void createImage()=0;
public:
	const CArtifactInstance * ourArt; // should be changed only with setArtifact()

	CArtPlace(Point position, const CArtifactInstance * Art = nullptr);
	void clickLeft(tribool down, bool previousState) override;
	void clickRight(tribool down, bool previousState) override;

	virtual void setArtifact(const CArtifactInstance *art)=0;
};

class CCommanderArtPlace : public CArtPlace
{
protected:
	const CGHeroInstance * commanderOwner;
	ArtifactPosition commanderSlotID;

	void createImage() override;
	void returnArtToHeroCallback();
public:
	CCommanderArtPlace(Point position, const CGHeroInstance * commanderOwner, ArtifactPosition artSlot, const CArtifactInstance * Art = nullptr);
	void clickLeft(tribool down, bool previousState) override;
	void clickRight(tribool down, bool previousState) override;

	virtual void setArtifact(const CArtifactInstance * art) override;

};

/// Artifacts can be placed there. Gets shown at the hero window
class CHeroArtPlace: public CArtPlace
{
	std::shared_ptr<CAnimImage> selection;

	void createImage() override;

public:
	// consider these members as const - change them only with appropriate methods e.g. lockSlot()
	bool locked;
	bool picked;
	bool marked;

	ArtifactPosition slotID; //Arts::EPOS enum + backpack starting from Arts::BACKPACK_START

	CArtifactsOfHero * ourOwner;

	CHeroArtPlace(Point position, const CArtifactInstance * Art = nullptr);

	void lockSlot(bool on);
	void pickSlot(bool on);
	void selectSlot(bool on);

	void clickLeft(tribool down, bool previousState) override;
	void clickRight(tribool down, bool previousState) override;
	void select();
	void deselect();
	void showAll(SDL_Surface * to) override;
	bool fitsHere (const CArtifactInstance * art) const; //returns true if given artifact can be placed here

	void setMeAsDest(bool backpackAsVoid = true);
	void setArtifact(const CArtifactInstance *art) override;
	static bool askToAssemble(const CArtifactInstance *art, ArtifactPosition slot,
	                          const CGHeroInstance *hero);
};

/// Contains artifacts of hero. Distincts which artifacts are worn or backpacked
class CArtifactsOfHero : public CIntObject
{
public:
	using ArtPlacePtr = std::shared_ptr<CHeroArtPlace>;
	using ArtPlaceMap = std::map<ArtifactPosition, ArtPlacePtr>;

	struct SCommonPart
	{
		struct Artpos
		{
			ArtifactPosition slotID;
			const CArtifactsOfHero *AOH;
			const CArtifactInstance *art;

			Artpos();
			void clear();
			void setTo(const CHeroArtPlace *place, bool dontTakeBackpack);
			bool valid();
			bool operator==(const ArtifactLocation &al) const;
		} src, dst;

		std::set<CArtifactsOfHero *> participants; // Needed to mark slots.

		void reset();
	};
	std::shared_ptr<SCommonPart> 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<CButton> leftArtRoll;
	std::shared_ptr<CButton> rightArtRoll;
	bool allowedAssembling;

	std::multiset<const CArtifactInstance*> artifactsOnAltar; //artifacts id that are technically present in backpack but in GUI are moved to the altar - they'll be omitted in backpack slots
	std::function<void(CHeroArtPlace*)> 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 artifactRemoved(const ArtifactLocation &al);
	void artifactAssembled(const ArtifactLocation &al);
	void artifactDisassembled(const ArtifactLocation &al);
	ArtPlacePtr getArtPlace(int slot);//may return null

	void setHero(const CGHeroInstance * hero);
	const CGHeroInstance *getHero() const;
	void dispose(); //free resources not needed after closing windows and reset state
	void scrollBackpack(int dir); //dir==-1 => to left; dir==1 => to right

	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 updateSlot(ArtifactPosition i);

	CArtifactsOfHero(const Point& position, bool createCommonPart = false);
	//Alternative constructor, used if custom artifacts positioning required (Kingdom interface)
	CArtifactsOfHero(ArtPlaceMap ArtWorn, std::vector<ArtPlacePtr> Backpack,
		std::shared_ptr<CButton> leftScroll, std::shared_ptr<CButton> rightScroll, bool createCommonPart = false);
	~CArtifactsOfHero();
	void updateParentWindow();
	friend class CHeroArtPlace;

private:

	const CGHeroInstance * curHero;

	ArtPlaceMap artWorn;

	std::vector<ArtPlacePtr> backpack; //hero's visible backpack (only 5 elements!)
	int backpackPos; //number of first art visible in backpack (in hero's vector)

	void eraseSlotData(ArtPlacePtr artPlace, ArtifactPosition slotID);
	void setSlotData(ArtPlacePtr artPlace, ArtifactPosition slotID);
};

class CWindowWithArtifacts : public CArtifactHolder
{
	std::vector<std::weak_ptr<CArtifactsOfHero>> artSets;
public:
	void addSet(std::shared_ptr<CArtifactsOfHero> artSet);

	std::shared_ptr<CArtifactsOfHero::SCommonPart> getCommonPart();

	void artifactRemoved(const ArtifactLocation &artLoc) override;
	void artifactMoved(const ArtifactLocation &artLoc, const ArtifactLocation &destLoc) override;
	void artifactDisassembled(const ArtifactLocation &artLoc) override;
	void artifactAssembled(const ArtifactLocation &artLoc) override;
};