File: ShopPanel.h

package info (click to toggle)
endless-sky 0.10.16-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 414,608 kB
  • sloc: cpp: 73,435; python: 893; xml: 666; sh: 271; makefile: 28
file content (240 lines) | stat: -rw-r--r-- 7,338 bytes parent folder | download
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
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/* ShopPanel.h
Copyright (c) 2014 by Michael Zahniser

Endless Sky is free software: you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later version.

Endless Sky is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program. If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once

#include "Panel.h"

#include "ClickZone.h"
#include "Mission.h"
#include "OutfitInfoDisplay.h"
#include "Point.h"
#include "Rectangle.h"
#include "ScrollBar.h"
#include "ScrollVar.h"
#include "ShipInfoDisplay.h"
#include "Tooltip.h"

#include <map>
#include <set>
#include <string>
#include <vector>

class CategoryList;
class Outfit;
class Planet;
class PlayerInfo;
class Ship;



// Class representing the common elements of both the shipyard panel and the
// outfitter panel (e.g. the sidebar with the ships you own).
class ShopPanel : public Panel {
public:
	explicit ShopPanel(PlayerInfo &player, bool isOutfitter);

	virtual void Step() override;
	virtual void Draw() override;

	virtual void UpdateTooltipActivation() override;


protected:
	// BuyResult holds the result of an attempt to buy. It is implicitly
	// created from a string or boolean in code. Any string indicates failure.
	// True indicates success, of course, while false (without a string)
	// indicates failure, but no need to pop up a message about it.
	class BuyResult {
	public:
		BuyResult(const char *error) : success(false), message(error) {}
		BuyResult(std::string error) : success(false), message(std::move(error)) {}
		BuyResult(bool result) : success(result), message() {}

		explicit operator bool() const noexcept { return success; }

		bool HasMessage() const noexcept { return !message.empty(); }
		const std::string &Message() const noexcept { return message; }


	private:
		bool success = true;
		std::string message;
	};


protected:
	void DrawShip(const Ship &ship, const Point &center, bool isSelected);

	void CheckForMissions(Mission::Location location);

	// These are for the individual shop panels to override.
	virtual int TileSize() const = 0;
	virtual int VisibilityCheckboxesSize() const;
	virtual bool HasItem(const std::string &name) const = 0;
	virtual void DrawItem(const std::string &name, const Point &point) = 0;
	virtual int DividerOffset() const = 0;
	virtual int DetailWidth() const = 0;
	virtual double DrawDetails(const Point &center) = 0;
	virtual BuyResult CanBuy(bool onlyOwned = false) const = 0;
	virtual void Buy(bool onlyOwned = false) = 0;
	virtual bool CanSell(bool toStorage = false) const = 0;
	virtual void Sell(bool toStorage = false) = 0;
	virtual void FailSell(bool toStorage = false) const;
	virtual bool CanSellMultiple() const;
	virtual bool IsAlreadyOwned() const;
	virtual bool ShouldHighlight(const Ship *ship);
	virtual void DrawKey();
	virtual void ToggleForSale();
	virtual void ToggleStorage();
	virtual void ToggleCargo();

	// Only override the ones you need; the default action is to return false.
	virtual bool KeyDown(SDL_Keycode key, Uint16 mod, const Command &command, bool isNewPress) override;
	virtual bool Click(int x, int y, MouseButton button, int clicks) override;
	virtual bool Hover(int x, int y) override;
	virtual bool Drag(double dx, double dy) override;
	virtual bool Release(int x, int y, MouseButton button) override;
	virtual bool Scroll(double dx, double dy) override;

	void DoFind(const std::string &text);
	virtual int FindItem(const std::string &text) const = 0;

	int64_t LicenseCost(const Outfit *outfit, bool onlyOwned = false) const;

	void DrawButton(const std::string &name, const Rectangle &buttonShape, bool isActive, bool hovering, char keyCode);
	void CheckSelection();


protected:
	class Zone : public ClickZone<const Ship *> {
	public:
		explicit Zone(Point center, Point size, const Ship *ship);
		explicit Zone(Point center, Point size, const Outfit *outfit);

		const Ship *GetShip() const;
		const Outfit *GetOutfit() const;

	private:
		const Outfit *outfit = nullptr;
	};

	enum class ShopPane : int {
		Main,
		Sidebar,
		Info
	};


protected:
	static constexpr int SIDEBAR_PADDING = 5;
	static constexpr int SIDEBAR_CONTENT = 250;
	static constexpr int SIDEBAR_WIDTH = SIDEBAR_CONTENT + SIDEBAR_PADDING;
	static constexpr int INFOBAR_WIDTH = 300;
	static constexpr int SIDE_WIDTH = SIDEBAR_WIDTH + INFOBAR_WIDTH;
	static constexpr int BUTTON_HEIGHT = 70;
	static constexpr int SHIP_SIZE = 250;
	static constexpr int OUTFIT_SIZE = 183;


protected:
	PlayerInfo &player;
	// Remember the current day, for calculating depreciation.
	int day;
	const Planet *planet = nullptr;
	const bool isOutfitter;

	// The player-owned ship that was first selected in the sidebar (or most recently purchased).
	Ship *playerShip = nullptr;
	// The player-owned ship being reordered.
	Ship *dragShip = nullptr;
	bool isDraggingShip = false;
	Point dragPoint;
	// The group of all selected, player-owned ships.
	std::set<Ship *> playerShips;

	// The currently selected Ship, for the ShipyardPanel.
	const Ship *selectedShip = nullptr;
	// The currently selected Outfit, for the OutfitterPanel.
	const Outfit *selectedOutfit = nullptr;
	// (It may be worth moving the above pointers into the derived classes in the future.)

	ScrollVar<double> mainScroll;
	ScrollVar<double> sidebarScroll;
	ScrollVar<double> infobarScroll;
	ShopPane activePane = ShopPane::Main;
	char hoverButton = '\0';

	ScrollBar mainScrollbar;
	ScrollBar sidebarScrollbar;
	ScrollBar infobarScrollbar;

	double previousX = 0.;

	std::vector<Zone> zones;
	std::vector<ClickZone<char>> buttonZones;
	std::vector<ClickZone<const Ship *>> shipZones;
	std::vector<ClickZone<std::string>> categoryZones;

	std::map<std::string, std::vector<std::string>> catalog;
	const CategoryList &categories;
	std::set<std::string> &collapsed;

	ShipInfoDisplay shipInfo;
	OutfitInfoDisplay outfitInfo;


private:
	void DrawShipsSidebar();
	void DrawDetailsSidebar();
	void DrawButtons();
	void DrawMain();

	int DrawPlayerShipInfo(const Point &point);

	bool DoScroll(double dy, int steps = 5);
	bool SetScrollToTop();
	bool SetScrollToBottom();
	void SideSelect(int count);
	void SideSelect(Ship *ship, int clicks = 1);
	void MainAutoScroll(const std::vector<Zone>::const_iterator &selected);
	void MainLeft();
	void MainRight();
	void MainUp();
	void MainDown();
	void CategoryAdvance(const std::string &category);
	std::vector<Zone>::const_iterator Selected() const;
	// Check if the given point is within the button zone, and if so return the
	// letter of the button (or ' ' if it's not on a button).
	char CheckButton(int x, int y);


private:
	bool delayedAutoScroll = false;

	Point hoverPoint;
	std::string shipName;
	std::string warningType;
	Tooltip shipsTooltip;
	Tooltip creditsTooltip;

	// Define the colors used by DrawButton, implemented at the class level to avoid repeat lookups from GameData.
	const Color &hover;
	const Color &active;
	const Color &inactive;
	const Color &back;

	bool checkedHelp = false;
};