1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2010-2019 EDuke32 developers and contributors
4 Copyright (C) 2019 Nuke.YKT
5 
6 This file is part of NBlood.
7 
8 NBlood is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License version 2
10 as published by the Free Software Foundation.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 See the GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 */
22 //-------------------------------------------------------------------------
23 #pragma once
24 
25 #include "compat.h"
26 #include "common_game.h"
27 #include "blood.h"
28 #include "inifile.h"
29 #include "resource.h"
30 #include "qav.h"
31 
32 #define M_MOUSETIMEOUT 210
33 
34 #define kMaxGameMenuItems 128
35 #define kMaxGameCycleItems 128
36 #define kMaxPicCycleItems 128
37 #define kMaxTitleLength 32
38 
39 // alpha increments of 3 --> 255 / 3 = 85 --> round up to power of 2 --> 128 --> divide by 2 --> 64 alphatabs required
40 // use 16 anyway :P
41 #define MOUSEUSEALPHA (videoGetRenderMode() != REND_CLASSIC || numalphatabs >= 15)
42 #define MOUSEALPHA (MOUSEUSEALPHA ? clamp(((int)totalclock - gGameMenuMgr.m_mouselastactivity - 90)*3, 0, 255) : 0)
43 #define CURSORALPHA (MOUSEUSEALPHA ? clamp(((int)totalclock - gGameMenuMgr.m_mouselastactivity - 90)*2 + (255/3), (255/3), 255) : 255/3)
44 #define MOUSEACTIVECONDITION ((int)totalclock - gGameMenuMgr.m_mouselastactivity < M_MOUSETIMEOUT)
45 #define MOUSEACTIVECONDITIONAL(condition) (MOUSEACTIVECONDITION && (condition))
46 #define MOUSEINACTIVECONDITIONAL(condition) (!MOUSEACTIVECONDITION && (condition))
47 #define MOUSEWATCHPOINTCONDITIONAL(condition) ((condition) || gGameMenuMgr.m_mousewake_watchpoint || gGameMenuMgr.m_menuchange_watchpoint == 3)
48 
49 enum {
50     kMenuEventNone = 0,
51     kMenuEventKey = 1,
52     kMenuEventUp = 2,
53     kMenuEventDown = 3,
54     kMenuEventLeft = 4,
55     kMenuEventRight = 5,
56     kMenuEventEnter = 6,
57     kMenuEventEscape = 7,
58     kMenuEventSpace = 8,
59     kMenuEventBackSpace = 9,
60     kMenuEventDelete = 10,
61     kMenuEventScrollUp = 11,
62     kMenuEventScrollDown = 12,
63 
64 
65     kMenuEventInit = 0x8000,
66     kMenuEventDeInit = 0x8001
67 };
68 
69 enum {
70     kMenuSliderNone = 0,
71     kMenuSliderValue,
72     kMenuSliderPercent,
73     kMenuSliderQ16
74 };
75 
76 struct CGameMenuEvent {
77     unsigned short at0;
78     char at2;
79 };
80 
81 // NUKE-TODO:
82 #ifdef DrawText
83 #undef DrawText
84 #endif
85 
86 class CMenuTextMgr
87 {
88 public:
89     int at0;
90     CMenuTextMgr();
91     void DrawText(const char *pString, int nFont, int x, int y, int nShade, int nPalette, bool shadow );
92     void GetFontInfo(int nFont, const char *pString, int *pXSize, int *pYSize);
93 };
94 
95 class CGameMenu;
96 
97 class CGameMenuItem {
98 public:
99     CGameMenu *pMenu;
100     const char* m_pzText;
101     int m_nFont;
102     int m_nX;
103     int m_nY;
104     int m_nWidth;
105     void (*pPreDrawCallback)(CGameMenuItem *pItem);
106     //int nFlags;
107     unsigned int bCanSelect : 1;
108     unsigned int bEnable : 1;
109     unsigned int bNoDraw : 1;
110     CGameMenuItem();
111     virtual ~CGameMenuItem();
112     virtual void Draw(void) = 0;
113     virtual bool Event(CGameMenuEvent &);
114     virtual bool MouseEvent(CGameMenuEvent &);
115 };
116 
117 class CGameMenuItemText : public CGameMenuItem
118 {
119 public:
120     int at20;
121     CGameMenuItemText();
122     CGameMenuItemText(const char *, int, int, int, int);
123     virtual void Draw(void);
124     //virtual bool Event(CGameMenuEvent &);
125 };
126 
127 class CGameMenuItemTitle : public CGameMenuItem
128 {
129 public:
130     int at20;
131     CGameMenuItemTitle();
132     CGameMenuItemTitle(const char *, int, int, int, int);
133     virtual void Draw(void);
134     //virtual bool Event(CGameMenuEvent &);
135 };
136 
137 class CGameMenuItemZBool : public CGameMenuItem
138 {
139 public:
140     bool at20;
141     const char *at21;
142     const char *at25;
143     void (*at29)(CGameMenuItemZBool *);
144     CGameMenuItemZBool();
145     CGameMenuItemZBool(const char *,int,int,int,int,bool,void (*)(CGameMenuItemZBool *),const char *,const char *);
146     virtual void Draw(void);
147     virtual bool Event(CGameMenuEvent &);
148 };
149 
150 class CGameMenuItemChain : public CGameMenuItem
151 {
152 public:
153     int at20;
154     CGameMenu *at24;
155     int at28;
156     void(*at2c)(CGameMenuItemChain *);
157     int at30;
158     CGameMenuItemChain();
159     CGameMenuItemChain(const char *, int, int, int, int, int, CGameMenu *, int, void(*)(CGameMenuItemChain *), int);
160     virtual void Draw(void);
161     virtual bool Event(CGameMenuEvent &);
162 };
163 
164 class CGameMenuItem7EA1C : public CGameMenuItem
165 {
166 public:
167     int at20; // text align
168     CGameMenu *at24;
169     int at28;
170     void(*at2c)(CGameMenuItem7EA1C *);
171     int at30;
172     IniFile *at34;
173     char at38[16];
174     char at48[16];
175     CGameMenuItem7EA1C();
176     CGameMenuItem7EA1C(const char *a1, int a2, int a3, int a4, int a5, const char *a6, const char *a7, int a8, int a9, void(*a10)(CGameMenuItem7EA1C *), int a11);
177     void Setup(void);
178     virtual void Draw(void);
179     virtual bool Event(CGameMenuEvent &);
180 };
181 
182 class CGameMenuItem7EE34 : public CGameMenuItem
183 {
184 public:
185     int at20;
186     int at24;
187     CGameMenu *at28;
188     CGameMenu *at2c;
189     CGameMenuItem7EE34();
190     CGameMenuItem7EE34(const char *a1, int a2, int a3, int a4, int a5, int a6);
191     void Setup(void);
192     virtual void Draw(void);
193     virtual bool Event(CGameMenuEvent &);
194 };
195 
196 class CGameMenuItemChain7F2F0 : public CGameMenuItemChain
197 {
198 public:
199     int at34;
200     CGameMenuItemChain7F2F0();
201     CGameMenuItemChain7F2F0(char *a1, int a2, int a3, int a4, int a5, int a6, CGameMenu *a7, int a8, void(*a9)(CGameMenuItemChain *), int a10);
202     //virtual void Draw(void);
203     virtual bool Event(CGameMenuEvent &);
204 };
205 
206 class CGameMenuItemBitmap : public CGameMenuItem
207 {
208 public:
209     int at20;
210     CGameMenuItemBitmap();
211     CGameMenuItemBitmap(const char *, int, int, int, int);
212     virtual void Draw(void);
213     virtual bool Event(CGameMenuEvent &);
214 };
215 
216 class CGameMenuItemBitmapLS : public CGameMenuItemBitmap
217 {
218 public:
219     int at24;
220     int at28;
221     CGameMenuItemBitmapLS();
222     CGameMenuItemBitmapLS(const char *, int, int, int, int);
223     virtual void Draw(void);
224     virtual bool Event(CGameMenuEvent &);
225 };
226 
227 class CGameMenuItemKeyList : public CGameMenuItem
228 {
229 public:
230     void(*pCallback)(CGameMenuItemKeyList *);
231     int at24;
232     int nRows;
233     int nTopDelta;
234     int nFocus;
235     int nGameFuncs;
236     bool bScan;
237     CGameMenuItemKeyList();
238     CGameMenuItemKeyList(const char * a1, int a2, int a3, int a4, int a5, int a6, int a7, void(*a8)(CGameMenuItemKeyList *));
239     void Scan(void);
240     virtual void Draw(void);
241     virtual bool Event(CGameMenuEvent &);
242     virtual bool MouseEvent(CGameMenuEvent &);
243 };
244 
245 class CGameMenuItemSlider : public CGameMenuItem
246 {
247 public:
248     int *pValue;
249     int nValue;
250     int nRangeLow;
251     int nRangeHigh;
252     int nStep;
253     void(*pCallback)(CGameMenuItemSlider *);
254     int nSliderTile;
255     int nCursorTile;
256     int nShowValue;
257     CGameMenuItemSlider();
258     CGameMenuItemSlider(const char *_pzText, int _nFont, int _nX, int _nY, int _nWidth, int _nValue, int _nRangeLow, int _nRangeHigh, int _nStep, void(*_pCallback)(CGameMenuItemSlider *), int _nSliderTile, int _nCursorTile, int _nShowValue = kMenuSliderNone);
259     CGameMenuItemSlider(const char *_pzText, int _nFont, int _nX, int _nY, int _nWidth, int *pnValue, int _nRangeLow, int _nRangeHigh, int _nStep, void(*_pCallback)(CGameMenuItemSlider *), int _nSliderTile, int _nCursorTile, int _nShowValue = kMenuSliderNone);
260     virtual void Draw(void);
261     virtual bool Event(CGameMenuEvent &);
262     virtual bool MouseEvent(CGameMenuEvent &);
263 };
264 
265 class CGameMenuItemSliderFloat : public CGameMenuItem
266 {
267 public:
268     float *pValue;
269     float fValue;
270     float fRangeLow;
271     float fRangeHigh;
272     float fStep;
273     void(*pCallback)(CGameMenuItemSliderFloat *);
274     int nSliderTile;
275     int nCursorTile;
276     int nShowValue;
277     CGameMenuItemSliderFloat();
278     CGameMenuItemSliderFloat(const char *_pzText, int _nFont, int _nX, int _nY, int _nWidth, float _fValue, float _fRangeLow, float _fRangeHigh, float _fStep, void(*_pCallback)(CGameMenuItemSliderFloat *), int _nSliderTile, int _nCursorTile, int _nShowValue = kMenuSliderNone);
279     CGameMenuItemSliderFloat(const char *_pzText, int _nFont, int _nX, int _nY, int _nWidth, float *pnValue, float _fRangeLow, float _fRangeHigh, float _fStep, void(*_pCallback)(CGameMenuItemSliderFloat *), int _nSliderTile, int _nCursorTile, int _nShowValue = kMenuSliderNone);
280     virtual void Draw(void);
281     virtual bool Event(CGameMenuEvent &);
282 };
283 
284 class CGameMenuItemZEdit : public CGameMenuItem
285 {
286 public:
287     char *at20;
288     int at24;
289     int at28;
290     void(*at2c)(CGameMenuItemZEdit *, CGameMenuEvent *);
291     char at30;
292     char at31;
293     char at32;
294     CGameMenuItemZEdit();
295     CGameMenuItemZEdit(const char *, int, int, int, int, char *, int, char, void(*)(CGameMenuItemZEdit *, CGameMenuEvent *), int);
296     void AddChar(char);
297     void BackChar(void);
298     virtual void Draw(void);
299     virtual bool Event(CGameMenuEvent &);
300 };
301 
302 class CGameMenuItemZEditBitmap : public CGameMenuItem
303 {
304 public:
305     char *at20;
306     int at24;
307     int at28; // save game slot
308     CGameMenuItemBitmapLS *at2c;
309     void(*at30)(CGameMenuItemZEditBitmap *, CGameMenuEvent *);
310     char bScan;
311     char at35;
312     char at36;
313     char at37;
314     CGameMenuItemZEditBitmap();
315     CGameMenuItemZEditBitmap(char *, int, int, int, int, char *, int, char, void(*)(CGameMenuItemZEditBitmap *, CGameMenuEvent *), int);
316     void AddChar(char);
317     void BackChar(void);
318     virtual void Draw(void);
319     virtual bool Event(CGameMenuEvent &);
320 };
321 
322 class CGameMenuItemQAV : public CGameMenuItem
323 {
324 public:
325     const char *at20;
326     DICTNODE *at24;
327     QAV *at28;
328     int at2c;
329     int at30;
330     bool bWideScreen;
331     bool bClearBackground;
332     CGameMenuItemQAV();
333     CGameMenuItemQAV(const char *, int, int, int, const char *, bool widescreen = false, bool clearbackground = false);
334     virtual void Draw(void);
335     virtual bool Event(CGameMenuEvent &);
336     void Reset(void);
337 };
338 
339 class CGameMenuItemZCycleSelect : public CGameMenuItem
340 {
341 public:
342     void(*m_pCallback)(CGameMenuItemZCycleSelect *);
343     int m_nRows;
344     int m_nTopDelta;
345     int m_nFocus;
346     int m_nItems;
347     int *m_pReturn;
348     const char **m_pzStrings;
349     CGameMenuItemZCycleSelect();
350     CGameMenuItemZCycleSelect(const char *pzText, int nFont, int nX, int nY, int nWidth, int nRows, int nItems, const char **pzStrings, int *pReturn, void(*pCallback)(CGameMenuItemZCycleSelect *));
351     virtual void Draw(void);
352     virtual bool Event(CGameMenuEvent &);
353     virtual bool MouseEvent(CGameMenuEvent &);
354 };
355 
356 
357 class CGameMenuItemZCycle : public CGameMenuItem
358 {
359 public:
360     int m_nItems;
361     int m_nFocus;
362     int m_nAlign;
363     const char *m_pzStrings[kMaxGameCycleItems];
364     char m_zTitle[kMaxTitleLength];
365     void(*m_pCallback)(CGameMenuItemZCycle *);
366     void(*m_pCallbackSelect)(CGameMenuItemZCycleSelect *);
367     bool m_bMenu;
368     int m_nMenuSelectReturn;
369     CGameMenu *m_pMenuSelect;
370     CGameMenuItemTitle *m_pItemSelectTitle;
371     CGameMenuItemZCycleSelect *m_pItemSelect;
372     CGameMenuItemZCycle();
373     CGameMenuItemZCycle(const char *, int, int, int, int, int, void(*)(CGameMenuItemZCycle *), const char **, int, int, bool = false, void(*)(CGameMenuItemZCycleSelect*) = NULL);
374     ~CGameMenuItemZCycle();
375     virtual void Draw(void);
376     virtual bool Event(CGameMenuEvent &);
377     void Add(const char *, bool);
378     void Next(void);
379     void Prev(void);
380     void Clear(void);
381     void SetTextArray(const char **, int, int);
382     void SetTextIndex(int);
383 };
384 
385 class CGameMenuItemYesNoQuit : public CGameMenuItem
386 {
387 public:
388     int at20;
389     int m_nRestart;
390     CGameMenuItemYesNoQuit();
391     CGameMenuItemYesNoQuit(const char *, int, int, int, int, int, int);
392     virtual void Draw(void);
393     virtual bool Event(CGameMenuEvent &);
394 };
395 
396 class CGameMenuItemPicCycle : public CGameMenuItem
397 {
398 public:
399     int m_nItems;
400     int at24;
401     int at28;
402     int at2c;
403     int at30[kMaxPicCycleItems];
404     void(*atb0)(CGameMenuItemPicCycle *);
405     int atb4;
406     CGameMenuItemPicCycle();
407     CGameMenuItemPicCycle(int, int, void(*)(CGameMenuItemPicCycle *), int *, int, int);
408     virtual void Draw(void);
409     virtual bool Event(CGameMenuEvent &);
410     void Add(int, bool);
411     void Next(void);
412     void Prev(void);
413     void Clear(void);
414     void SetPicArray(int *, int, int);
415     void SetPicIndex(int);
416 };
417 
418 class CGameMenuItemPassword : public CGameMenuItem
419 {
420 public:
421     char at20[9];
422     char at29[9];
423     int at32;
424     char at36;
425     int at37;
426     char at3b[32];
427     int at5b;
428     CGameMenuItemZBool *at5f;
429     CGameMenuItemPassword();
430     CGameMenuItemPassword(const char *, int, int, int);
431     virtual void Draw(void);
432     virtual bool Event(CGameMenuEvent &);
433 };
434 
435 class CGameMenuFileSelect : public CGameMenuItem
436 {
437 private:
438     const char *startdir;
439     const char *pattern;
440     char *destination;
441     void (*onFileSelectedEventHandler)();
442     char doPop;
443     BUILDVFS_FIND_REC *findhigh[2];
444     int32_t nTopDelta[2];
445     fnlist_t fnlist;
446     int32_t currentList;
447     bool Select(void);
448     void FileSelectInit(void);
449     void MovementVerify(void);
450     void RemoveFilenameFromDestination(void);
451     void SetDestinationToParentDir(void);
452 public:
453     CGameMenuFileSelect(const char *_pzText, int _nFont, int _x, int _y, int _nWidth, const char *_startdir, const char *_pattern, char *_destination, void(*)() = nullptr, const char doPop = 1);
454     virtual void Draw(void);
455     virtual bool Event(CGameMenuEvent&);
456     virtual bool MouseEvent(CGameMenuEvent &);
457 };
458 
459 
460 class CGameMenu
461 {
462 public:
463     int m_nItems;
464     int m_nFocus;
465     int at8;
466     char atc;
467     CGameMenuItem *pItemList[kMaxGameMenuItems]; // atd
468     CGameMenu();
469     CGameMenu(int);
470     ~CGameMenu();
471     void InitializeItems(CGameMenuEvent &event);
472     void Draw(void);
473     bool Event(CGameMenuEvent &event);
474     void Add(CGameMenuItem *pItem, bool active);
475     void SetFocusItem(int nItem);
476     void SetFocusItem(CGameMenuItem *Item);
477     bool CanSelectItem(int nItem);
478     void FocusPrevItem(void);
479     void FocusNextItem(void);
480     bool IsFocusItem(CGameMenuItem *pItem);
481     bool MouseEvent(CGameMenuEvent &event);
482 };
483 
484 class CGameMenuMgr
485 {
486 public:
487     static bool m_bInitialized;
488     static bool m_bActive;
489     static bool m_bScanning;
490     CGameMenu *pTempMenu;
491     CGameMenu *pActiveMenu;
492     CGameMenu *pMenuStack[8];
493     int nMenuPointer;
494     int32_t m_mouselastactivity;
495     int32_t m_mousewake_watchpoint, m_menuchange_watchpoint;
496     int32_t m_mousecaught;
497     vec2_t m_prevmousepos, m_mousepos, m_mousedownpos;
498     bool m_postPop;
499     CGameMenuMgr();
500     ~CGameMenuMgr();
501     void InitializeMenu(void);
502     void DeInitializeMenu(void);
503     bool Push(CGameMenu *pMenu, int data);
504     void Pop(void);
505     void PostPop(void);
506     void Draw(void);
507     void Clear(void);
508     void Process(void);
509     void Deactivate(void);
510     bool MouseOutsideBounds(vec2_t const * const pos, const int32_t x, const int32_t y, const int32_t width, const int32_t height);
511 };
512 
513 extern CMenuTextMgr gMenuTextMgr;
514 extern CGameMenuMgr gGameMenuMgr;
515