1/*
2 * LegacyClonk
3 *
4 * Copyright (c) 1998-2000, Matthes Bender (RedWolf Design)
5 * Copyright (c) 2017-2022, The LegacyClonk Team and contributors
6 *
7 * Distributed under the terms of the ISC license; see accompanying file
8 * "COPYING" for details.
9 *
10 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
11 * See accompanying file "TRADEMARK" for details.
12 *
13 * To redistribute this file separately, substitute the full license texts
14 * for the above references.
15 */
16
17/* In-game menu as used by objects, players, and fullscreen options */
18
19#pragma once
20
21#include "C4ForwardDeclarations.h"
22#include "C4Id.h"
23#include "C4FacetEx.h"
24#include "C4Shape.h"
25#include "C4Gui.h"
26#include "C4GuiDialogs.h"
27#include "C4IDList.h"
28#include "StdFile.h"
29
30class C4Viewport;
31
32enum
33{
34 C4MN_SymbolSize = 16,
35 C4MN_FrameWidth = 2
36};
37enum
38{
39 C4MN_Style_Normal = 0,
40 C4MN_Style_Context = 1,
41 C4MN_Style_Info = 2,
42 C4MN_Style_Dialog = 3,
43 C4MN_Style_BaseMask = 127,
44 C4MN_Style_EqualItemHeight = 128
45};
46enum
47{
48 C4MN_Extra_None = 0,
49 C4MN_Extra_Components = 1,
50 C4MN_Extra_Value = 2,
51 C4MN_Extra_MagicValue = 3,
52 C4MN_Extra_Info = 4,
53 C4MN_Extra_ComponentsMagic = 5,
54 C4MN_Extra_LiveMagicValue = 6,
55 C4MN_Extra_ComponentsLiveMagic = 7,
56};
57enum
58{
59 C4MN_Align_Left = 1,
60 C4MN_Align_Right = 2,
61 C4MN_Align_Top = 4,
62 C4MN_Align_Bottom = 8,
63 C4MN_Align_Free = 16
64};
65enum
66{
67 C4MN_Item_NoCount = 12345678
68};
69enum
70{
71 C4MN_AdjustPosition = 1 << 31,
72};
73
74void DrawMenuSymbol(int32_t iMenu, C4Facet &cgo, int32_t iOwner, C4Object *cObj);
75
76class C4MenuItem : public C4GUI::Element
77{
78 friend class C4Menu;
79
80public:
81 ~C4MenuItem();
82
83protected:
84 char Caption[C4MaxTitle + 1];
85 char Command[_MAX_FNAME + 30 + 1];
86 char Command2[_MAX_FNAME + 30 + 1];
87 char InfoCaption[2 * C4MaxTitle + 1];
88 int32_t Count;
89 C4ID id;
90 C4Object *Object;
91 C4FacetExSurface Symbol;
92 uint32_t dwSymbolClr;
93 bool fOwnValue; // if set, a specific value is to be shown
94 int32_t iValue; // specific value to be shown
95 bool fSelected; // item is selected; set by menu
96 int32_t iStyle;
97 class C4Menu *pMenu;
98 int32_t iIndex;
99 bool IsSelectable;
100 int32_t TextDisplayProgress; // dialog menus only: Amount of text which is to be displayed already (-1 for everything)
101 C4IDList Components; // components to be displayed in info line if item is selected
102
103private:
104 bool IsDragElement();
105 int32_t GetSymbolWidth(int32_t iForHeight);
106
107protected:
108 virtual void DrawElement(C4FacetEx &cgo) override; // draw menu item
109
110 C4MenuItem(C4Menu *pMenu, int32_t iIndex, const char *szCaption, const char *szCommand,
111 int32_t iCount, C4Object *pObject, const char *szInfoCaption,
112 C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, int32_t iStyle, bool fIsSelectable);
113 void GrabSymbol(C4FacetExSurface &fctSymbol) { Symbol.GrabFrom(rSource&: fctSymbol); if (Symbol.Surface) dwSymbolClr = Symbol.Surface->GetClr(); }
114 void RefSymbol(const C4FacetEx &fctSymbol) { Symbol.Set(fctSymbol); if (Symbol.Surface) dwSymbolClr = Symbol.Surface->GetClr(); }
115 void SetSelected(bool fToVal) { fSelected = fToVal; }
116 void DoTextProgress(int32_t &riByVal); // progress number of shown characters by given amount
117
118 // GUI calls
119 virtual void MouseInput(class C4GUI::CMouse &rMouse, int32_t iButton, int32_t iX, int32_t iY, uint32_t dwKeyParam) override; // input: mouse movement or buttons
120 virtual void MouseEnter(class C4GUI::CMouse &rMouse) override; // called when mouse cursor enters element region: Select this item (deselects any other)
121 virtual void DoDragging(class C4GUI::CMouse &rMouse, int32_t iX, int32_t iY, uint32_t dwKeyParam) override; // called by mouse: dragging process
122 virtual void StopDragging(class C4GUI::CMouse &rMouse, int32_t iX, int32_t iY, uint32_t dwKeyParam) override; // called by mouse: mouse released after dragging process
123
124public:
125 C4ID GetC4ID() const { return id; }
126 C4Object *GetObject() const { return Object; }
127 const char *GetCommand() const { return Command; }
128
129 void ClearObject() { Object = nullptr; }
130
131 friend class C4DefGraphicsPtrBackup;
132};
133
134class C4Menu : public C4GUI::Dialog
135{
136 typedef C4GUI::Dialog BaseClass;
137
138public:
139 C4Menu();
140 virtual ~C4Menu() { Clear(); }
141
142 void Clear();
143 virtual void Default();
144
145protected:
146 bool LocationSet;
147 bool Permanent;
148 bool NeedRefill;
149 int32_t Style;
150 int32_t Selection, TimeOnSelection;
151 int32_t ItemCount;
152 int32_t ItemWidth, ItemHeight;
153 int32_t Extra, ExtraData;
154 int32_t DrawMenuControls;
155 int32_t Identification;
156 int32_t Columns; // sync
157 int32_t Lines; // async
158 int32_t Alignment;
159 int32_t VisibleCount;
160 int32_t LastSelection; // used by AutoContextMenus
161 StdStrBuf CloseCommand; // script command that will be executed on menu close
162 char Caption[C4MaxTitle + 1];
163 C4FacetExSurface Symbol;
164 C4GUI::ScrollWindow *pClientWindow; // window containing the menu items
165 bool fHasPortrait; // if set, first menu item is used at a portrait at topleft of menu
166 bool fTextProgressing; // if true, text is being shown progressively (dialog menus)
167 bool fEqualIconItemHeight; // for dialog menus only: If set, all options with an icon are forced to have the same height
168 bool fActive; // set if menu is shown - independent of GUI to keep synchronized when there's no GUI
169
170public:
171 bool ConvertCom(int32_t &rCom, int32_t &rData, bool fAsyncConversion);
172 void ClearPointers(C4Object *pObj);
173 bool Refill();
174 void Execute();
175 void SetPermanent(bool fPermanent);
176 void SetAlignment(int32_t iAlignment);
177 int32_t GetIdentification();
178 int32_t GetItemCount();
179 int32_t GetSelection();
180 bool IsContextMenu() { return Style == C4MN_Style_Context; }
181 int GetSymbolSize();
182 int32_t GetItemHeight() { return ItemHeight; }
183 C4MenuItem *GetSelectedItem();
184 C4MenuItem *GetItem(int32_t iIndex);
185 virtual C4Object *GetParentObject() { return nullptr; }
186 bool MoveSelection(int32_t iBy, bool fAdjustPosition, bool fDoCalls);
187 bool SetSelection(int32_t iSelection, bool fAdjustPosition, bool fDoCalls);
188 bool SetPosition(int32_t iPosition);
189 void SetSize(int32_t iToWdt, int32_t iToHgt);
190 bool Enter(bool fRight = false);
191 bool IsActive();
192 bool Control(uint8_t byCom, int32_t iData);
193 bool KeyControl(uint8_t byCom); // direct keyboard callback
194 bool AddRefSym(const char *szCaption, const C4FacetEx &fctSymbol, const char *szCommand,
195 int32_t iCount = C4MN_Item_NoCount, C4Object *pObject = nullptr,
196 const char *szInfoCaption = nullptr,
197 C4ID idID = C4ID_None, const char *szCommand2 = nullptr, bool fOwnValue = false, int32_t iValue = 0, bool fIsSelectable = true);
198 bool Add(const char *szCaption, C4FacetExSurface &fctSymbol, const char *szCommand,
199 int32_t iCount = C4MN_Item_NoCount, C4Object *pObject = nullptr,
200 const char *szInfoCaption = nullptr,
201 C4ID idID = C4ID_None, const char *szCommand2 = nullptr, bool fOwnValue = false, int32_t iValue = 0, bool fIsSelectable = true);
202 void ClearItems(bool fResetSelection = false);
203 void ResetLocation() { LocationSet = false; }
204 bool SetLocation(int32_t iX, int32_t iY); // set location relative to user viewport
205 bool SetTextProgress(int32_t iToProgress, bool fAdd); // enable/disable progressive text display and set starting pos
206 void SetEqualItemHeight(bool fToVal) { fEqualIconItemHeight = fToVal; } // enable/disable equal item heights
207 bool TryClose(bool fOK, bool fControl);
208 void SetCloseCommand(const char *strCommand);
209
210#ifndef NDEBUG
211 void AssertSurfaceNotUsed(C4Surface *sfc);
212#endif
213
214private:
215 bool AddItem(C4MenuItem *pNew, const char *szCaption, const char *szCommand,
216 int32_t iCount, C4Object *pObject, const char *szInfoCaption,
217 C4ID idID, const char *szCommand2, bool fOwnValue, int32_t iValue, bool fIsSelectable);
218 bool InitMenu(const char *szEmpty, int32_t iExtra, int32_t iExtraData, int32_t iId, int32_t iStyle);
219
220protected:
221 bool DoInitRefSym(const C4FacetEx &fctSymbol, const char *szEmpty, int32_t iExtra = C4MN_Extra_None, int32_t iExtraData = 0, int32_t iId = 0, int32_t iStyle = C4MN_Style_Normal);
222 bool DoInit(C4FacetExSurface &fctSymbol, const char *szEmpty, int32_t iExtra = C4MN_Extra_None, int32_t iExtraData = 0, int32_t iId = 0, int32_t iStyle = C4MN_Style_Normal);
223 void AdjustSelection();
224 void AdjustPosition();
225 bool RefillInternal();
226 void DrawFrame(C4Surface *sfcSurface, int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt);
227 void InitLocation(C4Facet &cgo);
228 void InitSize();
229 void UpdateScrollBar(); // call InitSize if a scroll bar is needed but not present or vice vera
230 void UserSelectItem(int32_t Player, C4MenuItem *pItem); // select item (direct) or do control (object menus)
231 void UserEnter(int32_t Player, C4MenuItem *pItem, bool fRight); // enter on an item
232 bool HasMouse(); // returns whether the controlling player has mouse control
233
234 virtual bool DoRefillInternal(bool &rfRefilled) { return true; }
235 virtual bool MenuCommand(const char *szCommand, bool fIsCloseCommand) { return true; }
236 virtual void OnSelectionChanged(int32_t iNewSelection) {} // do object callbacks if selection changed in user menus
237 virtual bool IsCloseDenied() { return false; } // do MenuQueryCancel-callbacks for user menus
238 virtual void OnUserSelectItem(int32_t Player, int32_t iIndex) {}
239 virtual void OnUserEnter(int32_t Player, int32_t iIndex, bool fRight) {}
240 virtual void OnUserClose() {}
241 virtual bool IsReadOnly() { return false; } // determine whether the menu is just viewed by an observer, and should not issue any calls
242 virtual int32_t GetControllingPlayer() { return NO_OWNER; }
243
244 virtual const char *GetID() override { return nullptr; } // no ID needed, because it's a viewport dlg
245
246 bool HasPortrait() { return fHasPortrait; } // dialog menus only: Whether a portrait is shown in the topleft
247
248protected:
249 // C4GUI
250 virtual C4Viewport *GetViewport() override; // return associated viewport
251 virtual bool IsExternalDrawDialog() override { return true; } // drawn by viewport drawing proc
252 virtual bool IsMouseControlled() override { return false; }
253 virtual void UpdateOwnPos() override;
254 void UpdateElementPositions(); // reposition list items so they are stacked vertically
255 virtual int32_t GetZOrdering() override { return -1; }
256 virtual void Draw(C4FacetEx &cgo) override;
257 virtual void DrawElement(C4FacetEx &cgo) override; // draw menu
258 virtual bool IsOwnPtrElement() override { return true; }
259 virtual void UserClose(bool fOK) override;
260
261 // bottom area needed for extra info
262 virtual int32_t GetMarginBottom() override { return ((Extra || DrawMenuControls) ? C4MN_SymbolSize : 0) + C4MN_FrameWidth + BaseClass::GetMarginBottom(); }
263 virtual int32_t GetMarginLeft() override { return C4MN_FrameWidth + BaseClass::GetMarginLeft(); }
264 virtual int32_t GetMarginRight() override { return C4MN_FrameWidth + BaseClass::GetMarginRight(); }
265
266 friend C4Viewport; // for drawing
267 friend class C4MenuItem;
268};
269