1 //  Copyright (C) 2008, 2009, 2010, 2011, 2014, 2020 Ben Asselstine
2 //
3 //  This program is free software; you can redistribute it and/or modify
4 //  it under the terms of the GNU General Public License as published by
5 //  the Free Software Foundation; either version 3 of the License, or
6 //  (at your option) any later version.
7 //
8 //  This program is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 //  GNU Library General Public License for more details.
12 //
13 //  You should have received a copy of the GNU General Public License
14 //  along with this program; if not, write to the Free Software
15 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 //  02110-1301, USA.
17 
18 #pragma once
19 #ifndef SHIELDSET_H
20 #define SHIELDSET_H
21 
22 #include <gtkmm.h>
23 #include <map>
24 #include <vector>
25 #include <sigc++/trackable.h>
26 
27 #include "shield.h"
28 #include "tartan.h"
29 #include "set.h"
30 #include "defs.h"
31 
32 class XML_Helper;
33 class ShieldStyle;
34 
35 //! A list of Shield graphic objects in a shield theme.
36 /**
37  * Every scenario has a shield set; it is the theme of the shield graphics
38  * within the game.  Shields come in three sizes -- small, medium and large.
39  * Small shields appear on the OverviewMap.  Medium shields appear in the turn
40  * indicator in the top right of the GameWindow.  Large shields appear in many
41  * dialogs, chiefly the FightWindow, and DiplomacyDialog.
42  * Every shield belongs to one of 9 players (the ninth is the Neutral player).
43  * The players aren't Player objects in this case; instead it refers to a
44  * Shield::ShieldColour.  e.g. Not `The Sirians' but rather the `White player'
45  * of the scenario.
46  *
47  * The Shieldset dictates the dimensions of these three sizes of shields.
48  *
49  * Shieldsets are referred to by their basename.  This is the last part of the
50  * filename, minus the file extension.
51  *
52  * The shieldset configuration file is a tar file that contains an XML file,
53  * and a set of png files.  Filenames have the following form:
54  * shield/${Shieldset::d_basename}.lws.
55  */
56 class Shieldset: public std::list<Shield *>, public sigc::trackable, public Set
57 {
58     public:
59 
60 	//! The xml tag of this object in a shieldset configuration file.
61 	static Glib::ustring d_tag;
62 
63 	//! The file extension for shieldset files.  It includes the dot.
64 	static Glib::ustring file_extension;
65 
66 
67 	//! Default constructor.
68 	/**
69 	 * Make a new shieldset given a unique id and a basename name.
70 	 */
71 	Shieldset(guint32 id, Glib::ustring name);
72 
73         //! Copy constructor.
74         Shieldset(const Shieldset& s);
75 
76 	//! Load a Shieldset from an opened shieldset configuration file.
77 	/**
78 	 * Make a new Shieldset object by reading it in from the shieldset
79 	 * configuration file.
80 	 *
81 	 * @param helper  The opened shieldset configuration file to load the
82 	 *                Shieldset from.
83 	 */
84         Shieldset(XML_Helper* helper, Glib::ustring directory);
85 
86 	//! Destructor.
87         ~Shieldset();
88 
89 	// Get Methods
90 
91 	//! Return the mask colour for the given player.
92 	Gdk::RGBA getColor(guint32 owner) const;
93 
94 	//! Return the number of pixels high the small shields are.
getSmallHeight()95 	guint32 getSmallHeight() const {return d_small_height;}
96 
97 	//! Return the number of pixels wide the small shields are.
getSmallWidth()98 	guint32 getSmallWidth() const {return d_small_width;}
99 
100 	//! Return the number of pixels high the medium shields are.
getMediumHeight()101 	guint32 getMediumHeight() const {return d_medium_height;}
102 
103 	//! Return the number of pixels wide the medium shields are.
getMediumWidth()104 	guint32 getMediumWidth() const {return d_medium_width;}
105 
106 	//! Return the number of pixels the large shields are.
getLargeHeight()107 	guint32 getLargeHeight() const {return d_large_height;}
108 
109 	//! Return the number of pixels wide the large shields are.
getLargeWidth()110 	guint32 getLargeWidth() const {return d_large_width;}
111 
112 	//! Return the total number of shields in this shieldset.
getSize()113         guint32 getSize() const {return size();}
114 
115         bool isAnyHeightAndWidthSet();
116         bool isSmallHeightAndWidthSet();
117         bool isMediumHeightAndWidthSet();
118         bool isLargeHeightAndWidthSet();
119 
120 	// Set Methods
121 
122 	//! Return the number of pixels high the small shields are.
setSmallHeight(guint32 n)123 	void setSmallHeight(guint32 n) {d_small_height = n;}
124 
125 	//! Set how wide in pixels small shields are scaled to.
setSmallWidth(guint32 n)126 	void setSmallWidth(guint32 n) {d_small_width = n;}
127 
128 	//! Set how high in pixels medium shields are scaled to.
setMediumHeight(guint32 n)129 	void setMediumHeight(guint32 n) {d_medium_height = n;}
130 
131 	//! Set how wide in pixels medium shields are scaled to.
setMediumWidth(guint32 n)132 	void setMediumWidth(guint32 n) {d_medium_width = n;}
133 
134 	//! Set how high in pixels large shields are scaled to.
setLargeHeight(guint32 n)135 	void setLargeHeight(guint32 n) {d_large_height = n;}
136 
137 	//! Set how wide in pixels large shields are scaled to.
setLargeWidth(guint32 n)138 	void setLargeWidth(guint32 n) {d_large_width = n;}
139 
140         //! Load the shieldset again.
141         void reload(bool &broken);
142 
143         //! Set the dimensions based on the largest image of that shieldstyle.
144         void setHeightsAndWidthsFromImages(ShieldStyle *s);
145         void setHeightsAndWidthsFromImages();
146         void setSmallHeightsAndWidthsFromImages();
147         void setMediumHeightsAndWidthsFromImages();
148         void setLargeHeightsAndWidthsFromImages();
149 
150 	// Methods that operate on the class data but do not modify the class.
151 
152 	bool save(XML_Helper *helper) const;
153 
154         bool save(Glib::ustring filename, Glib::ustring extension) const;
155 
156 	//! Find the shield of a given size and colour in this Shieldset.
157 	/**
158 	 * Scan through all Shield objects in this set for first one that is
159 	 * the desired size, and for the desired player.
160 	 *
161 	 * @param type    One of the values in Shield::ShieldType.
162 	 * @param colour  One of the values in Shield::ShieldColour.
163 	 *
164 	 * @return A pointer to the shield that matches the size and player.
165 	 *         If no Shield object could be found that matches the given
166 	 *         parameters, NULL is returned.
167 	 */
168 	ShieldStyle* lookupShieldByTypeAndColour(guint32 type, guint32 colour) const;
169         Shield* lookupShieldByColour(guint32 colour) const;
170 
171         //! Get the image and mask associated with the shield of a given colour.
172         /**
173          * This gets the left tartan image and mask for a player denoted by
174          * colour.
175          */
176         void lookupTartanImage(guint32 colour, Tartan::Type type,
177                                PixMask **image, PixMask **mask);
178 
179 	//! Check to see if this shieldset can be used in the game.
180 	bool validate() const;
181 
182 	//! Check to see if the number of shields is sufficient.
183 	bool validateNumberOfShields() const;
184 
185 	//! Check to see if the images for the shields are supplied.
186 	bool validateShieldImages(Shield::Colour c) const;
187 
188 	//! Check to see if the images for the tartans are supplied.
189 	bool validateTartanImages(Shield::Colour c) const;
190 
191         guint32 countEmptyImageNames() const;
192 
193 	// Methods that operate on the class data and also modify the class.
194 
195         //! Load the images associated with this shieldset.
196         /**
197          * Go get the image files from the shieldset file and create the
198          * various pixmask objects.
199          *
200          * @param scale   The images are clamped to the sizes held in
201          *                d_small_width, d_small_height (for the small
202          *                shields) and so on.
203          * @param broken  True when couldn't read the shieldset file.
204          */
205 	void instantiateImages(bool scale, bool &broken);
206 
207 	//! Destroy images associated with this shieldset.
208 	void uninstantiateImages();
209 
210         //! destroy any image that has this name
211         void uninstantiateSameNamedImages (Glib::ustring imgname);
212 
213 	// Static Methods
214 
215 	//! Create a shieldset from the given shieldset configuration file.
216 	static Shieldset *create(Glib::ustring filename, bool &unsupported);
217 
218         static Shieldset *copy (const Shieldset *orig);
219 
220         //! rewrite old shieldset files.
221         static bool upgrade(Glib::ustring filename, Glib::ustring old_version, Glib::ustring new_version);
222         static void support_backward_compatibility();
223 
224     private:
225 
226 	//! Callback function to load Shield objects into the Shieldset.
227 	bool loadShield(Glib::ustring tag, XML_Helper* helper);
228 
229 	// DATA
230 
231 	//! The number of pixels high the small shield images are scaled to.
232 	/**
233 	 * Equates to the shieldset.d_small_height XML entity in the shieldset
234 	 * configuration file.
235 	 */
236 	guint32 d_small_height;
237 
238 	//! The number of pixels wide the small shield images are scaled to.
239 	/**
240 	 * Equates to the shieldset.d_small_width XML entity in the shieldset
241 	 * configuration file.
242 	 */
243 	guint32 d_small_width;
244 
245 	//! The number of pixels high the medium shield images are scaled to.
246 	/**
247 	 * Equates to the shieldset.d_medium_height XML entity in the shieldset
248 	 * configuration file.
249 	 */
250 	guint32 d_medium_height;
251 
252 	//! The number of pixels wide the medium shield images are scaled to.
253 	/**
254 	 * Equates to the shieldset.d_medium_width XML entity in the shieldset
255 	 * configuration file.
256 	 */
257 	guint32 d_medium_width;
258 
259 	//! The number of pixels high the large shield images are scaled to.
260 	/**
261 	 * Equates to the shieldset.d_large_height XML entity in the shieldset
262 	 * configuration file.
263 	 */
264 	guint32 d_large_height;
265 
266 	//! The number of pixels wide the large shield images are scaled to.
267 	/**
268 	 * Equates to the shieldset.d_large_width XML entity in the shieldset
269 	 * configuration file.
270 	 */
271 	guint32 d_large_width;
272 };
273 
274 #endif // SHIELDSET_H
275 
276