DEADSOFTWARE

gui: "yes/no" menu refactored to ease further changes
[d2df-sdl.git] / src / game / g_gui.pas
1 unit g_gui;
3 interface
5 uses
6 e_graphics, e_input, g_playermodel, g_basic, MAPSTRUCT, WADEDITOR;
8 const
9 MAINMENU_HEADER_COLOR: TRGB = (R:255; G:255; B:255);
10 MAINMENU_ITEMS_COLOR: TRGB = (R:255; G:255; B:255);
11 MAINMENU_UNACTIVEITEMS_COLOR: TRGB = (R:192; G:192; B:192);
12 MAINMENU_CLICKSOUND = 'MENU_SELECT';
13 MAINMENU_CHANGESOUND = 'MENU_CHANGE';
14 MAINMENU_SPACE = 4;
15 MAINMENU_MARKER1 = 'MAINMENU_MARKER1';
16 MAINMENU_MARKER2 = 'MAINMENU_MARKER2';
17 MAINMENU_MARKERDELAY = 24;
18 WINDOW_CLOSESOUND = 'MENU_CLOSE';
19 MENU_HEADERCOLOR: TRGB = (R:255; G:255; B:255);
20 MENU_ITEMSTEXT_COLOR: TRGB = (R:255; G:255; B:255);
21 MENU_UNACTIVEITEMS_COLOR: TRGB = (R:128; G:128; B:128);
22 MENU_ITEMSCTRL_COLOR: TRGB = (R:255; G:0; B:0);
23 MENU_VSPACE = 2;
24 MENU_HSPACE = 32;
25 MENU_CLICKSOUND = 'MENU_SELECT';
26 MENU_CHANGESOUND = 'MENU_CHANGE';
27 MENU_MARKERDELAY = 24;
28 SCROLL_LEFT = 'SCROLL_LEFT';
29 SCROLL_RIGHT = 'SCROLL_RIGHT';
30 SCROLL_MIDDLE = 'SCROLL_MIDDLE';
31 SCROLL_MARKER = 'SCROLL_MARKER';
32 SCROLL_ADDSOUND = 'SCROLL_ADD';
33 SCROLL_SUBSOUND = 'SCROLL_SUB';
34 EDIT_LEFT = 'EDIT_LEFT';
35 EDIT_RIGHT = 'EDIT_RIGHT';
36 EDIT_MIDDLE = 'EDIT_MIDDLE';
37 EDIT_CURSORCOLOR: TRGB = (R:200; G:0; B:0);
38 EDIT_CURSORLEN = 10;
39 KEYREAD_QUERY = '<...>';
40 KEYREAD_CLEAR = '???';
41 KEYREAD_TIMEOUT = 24;
42 MAPPREVIEW_WIDTH = 8;
43 MAPPREVIEW_HEIGHT = 8;
44 BOX1 = 'BOX1';
45 BOX2 = 'BOX2';
46 BOX3 = 'BOX3';
47 BOX4 = 'BOX4';
48 BOX5 = 'BOX5';
49 BOX6 = 'BOX6';
50 BOX7 = 'BOX7';
51 BOX8 = 'BOX8';
52 BOX9 = 'BOX9';
53 BSCROLL_UPA = 'BSCROLL_UP_A';
54 BSCROLL_UPU = 'BSCROLL_UP_U';
55 BSCROLL_DOWNA = 'BSCROLL_DOWN_A';
56 BSCROLL_DOWNU = 'BSCROLL_DOWN_U';
57 BSCROLL_MIDDLE = 'BSCROLL_MIDDLE';
58 WM_KEYDOWN = 101;
59 WM_CHAR = 102;
60 WM_USER = 110;
62 type
63 TMessage = record
64 Msg: DWORD;
65 wParam: LongInt;
66 lParam: LongInt;
67 end;
69 TFontType = (FONT_TEXTURE, FONT_CHAR);
71 TFont = class(TObject)
72 private
73 ID: DWORD;
74 FScale: Single;
75 FFontType: TFontType;
76 public
77 constructor Create(FontID: DWORD; FontType: TFontType);
78 destructor Destroy; override;
79 procedure Draw(X, Y: Integer; Text: string; R, G, B: Byte);
80 procedure GetTextSize(Text: string; var w, h: Word);
81 property Scale: Single read FScale write FScale;
82 end;
84 TGUIControl = class;
85 TGUIWindow = class;
87 TOnKeyDownEvent = procedure(Key: Byte);
88 TOnKeyDownEventEx = procedure(win: TGUIWindow; Key: Byte);
89 TOnCloseEvent = procedure;
90 TOnShowEvent = procedure;
91 TOnClickEvent = procedure;
92 TOnChangeEvent = procedure(Sender: TGUIControl);
93 TOnEnterEvent = procedure(Sender: TGUIControl);
95 TGUIControl = class
96 private
97 FX, FY: Integer;
98 FEnabled: Boolean;
99 FWindow : TGUIWindow;
100 FName: string;
101 public
102 constructor Create;
103 procedure OnMessage(var Msg: TMessage); virtual;
104 procedure Update; virtual;
105 procedure Draw; virtual;
106 property X: Integer read FX write FX;
107 property Y: Integer read FY write FY;
108 property Enabled: Boolean read FEnabled write FEnabled;
109 property Name: string read FName write FName;
110 end;
112 TGUIWindow = class
113 private
114 FActiveControl: TGUIControl;
115 FDefControl: string;
116 FPrevWindow: TGUIWindow;
117 FName: string;
118 FBackTexture: string;
119 FMainWindow: Boolean;
120 FOnKeyDown: TOnKeyDownEvent;
121 FOnKeyDownEx: TOnKeyDownEventEx;
122 FOnCloseEvent: TOnCloseEvent;
123 FOnShowEvent: TOnShowEvent;
124 FUserData: Pointer;
125 public
126 Childs: array of TGUIControl;
127 constructor Create(Name: string);
128 destructor Destroy; override;
129 function AddChild(Child: TGUIControl): TGUIControl;
130 procedure OnMessage(var Msg: TMessage);
131 procedure Update;
132 procedure Draw;
133 procedure SetActive(Control: TGUIControl);
134 function GetControl(Name: string): TGUIControl;
135 property OnKeyDown: TOnKeyDownEvent read FOnKeyDown write FOnKeyDown;
136 property OnKeyDownEx: TOnKeyDownEventEx read FOnKeyDownEx write FOnKeyDownEx;
137 property OnClose: TOnCloseEvent read FOnCloseEvent write FOnCloseEvent;
138 property OnShow: TOnShowEvent read FOnShowEvent write FOnShowEvent;
139 property Name: string read FName;
140 property DefControl: string read FDefControl write FDefControl;
141 property BackTexture: string read FBackTexture write FBackTexture;
142 property MainWindow: Boolean read FMainWindow write FMainWindow;
143 property UserData: Pointer read FUserData write FUserData;
144 end;
146 TGUITextButton = class(TGUIControl)
147 private
148 FText: string;
149 FColor: TRGB;
150 FFont: TFont;
151 FSound: string;
152 FShowWindow: string;
153 public
154 Proc: procedure;
155 constructor Create(Proc: Pointer; FontID: DWORD; Text: string);
156 destructor Destroy(); override;
157 procedure OnMessage(var Msg: TMessage); override;
158 procedure Update(); override;
159 procedure Draw(); override;
160 function GetWidth(): Integer;
161 function GetHeight(): Integer;
162 procedure Click(Silent: Boolean = False);
163 property Caption: string read FText write FText;
164 property Color: TRGB read FColor write FColor;
165 property Font: TFont read FFont write FFont;
166 property ShowWindow: string read FShowWindow write FShowWindow;
167 end;
169 TGUILabel = class(TGUIControl)
170 private
171 FText: string;
172 FColor: TRGB;
173 FFont: TFont;
174 FFixedLen: Word;
175 FOnClickEvent: TOnClickEvent;
176 public
177 constructor Create(Text: string; FontID: DWORD);
178 procedure OnMessage(var Msg: TMessage); override;
179 procedure Draw; override;
180 function GetWidth: Integer;
181 function GetHeight: Integer;
182 property OnClick: TOnClickEvent read FOnClickEvent write FOnClickEvent;
183 property FixedLength: Word read FFixedLen write FFixedLen;
184 property Text: string read FText write FText;
185 property Color: TRGB read FColor write FColor;
186 property Font: TFont read FFont write FFont;
187 end;
189 TGUIScroll = class(TGUIControl)
190 private
191 FValue: Integer;
192 FMax: Word;
193 FLeftID: DWORD;
194 FRightID: DWORD;
195 FMiddleID: DWORD;
196 FMarkerID: DWORD;
197 FOnChangeEvent: TOnChangeEvent;
198 procedure FSetValue(a: Integer);
199 public
200 constructor Create();
201 procedure OnMessage(var Msg: TMessage); override;
202 procedure Update; override;
203 procedure Draw; override;
204 function GetWidth(): Word;
205 property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent;
206 property Max: Word read FMax write FMax;
207 property Value: Integer read FValue write FSetValue;
208 end;
210 TGUISwitch = class(TGUIControl)
211 private
212 FFont: TFont;
213 FItems: array of string;
214 FIndex: Integer;
215 FColor: TRGB;
216 FOnChangeEvent: TOnChangeEvent;
217 public
218 constructor Create(FontID: DWORD);
219 procedure OnMessage(var Msg: TMessage); override;
220 procedure AddItem(Item: string);
221 procedure Update; override;
222 procedure Draw; override;
223 function GetWidth(): Word;
224 function GetText: string;
225 property ItemIndex: Integer read FIndex write FIndex;
226 property Color: TRGB read FColor write FColor;
227 property Font: TFont read FFont write FFont;
228 property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent;
229 end;
231 TGUIEdit = class(TGUIControl)
232 private
233 FFont: TFont;
234 FCaretPos: Integer;
235 FMaxLength: Word;
236 FWidth: Word;
237 FText: string;
238 FColor: TRGB;
239 FOnlyDigits: Boolean;
240 FLeftID: DWORD;
241 FRightID: DWORD;
242 FMiddleID: DWORD;
243 FOnChangeEvent: TOnChangeEvent;
244 FOnEnterEvent: TOnEnterEvent;
245 procedure SetText(Text: string);
246 public
247 constructor Create(FontID: DWORD);
248 procedure OnMessage(var Msg: TMessage); override;
249 procedure Update; override;
250 procedure Draw; override;
251 function GetWidth(): Word;
252 property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent;
253 property OnEnter: TOnEnterEvent read FOnEnterEvent write FOnEnterEvent;
254 property Width: Word read FWidth write FWidth;
255 property MaxLength: Word read FMaxLength write FMaxLength;
256 property OnlyDigits: Boolean read FOnlyDigits write FOnlyDigits;
257 property Text: string read FText write SetText;
258 property Color: TRGB read FColor write FColor;
259 property Font: TFont read FFont write FFont;
260 end;
262 TGUIKeyRead = class(TGUIControl)
263 private
264 FFont: TFont;
265 FColor: TRGB;
266 FKey: Word;
267 FIsQuery: Boolean;
268 public
269 constructor Create(FontID: DWORD);
270 procedure OnMessage(var Msg: TMessage); override;
271 procedure Draw; override;
272 function GetWidth(): Word;
273 property Key: Word read FKey write FKey;
274 property Color: TRGB read FColor write FColor;
275 property Font: TFont read FFont write FFont;
276 end;
278 TGUIModelView = class(TGUIControl)
279 private
280 FModel: TPlayerModel;
281 a: Boolean;
282 public
283 constructor Create;
284 destructor Destroy; override;
285 procedure OnMessage(var Msg: TMessage); override;
286 procedure SetModel(ModelName: string);
287 procedure SetColor(Red, Green, Blue: Byte);
288 procedure NextAnim();
289 procedure NextWeapon();
290 procedure Update; override;
291 procedure Draw; override;
292 property Model: TPlayerModel read FModel;
293 end;
295 TPreviewPanel = record
296 X1, Y1, X2, Y2: Integer;
297 PanelType: Word;
298 end;
300 TGUIMapPreview = class(TGUIControl)
301 private
302 FMapData: array of TPreviewPanel;
303 FMapSize: TPoint;
304 FScale: Single;
305 public
306 constructor Create();
307 destructor Destroy(); override;
308 procedure OnMessage(var Msg: TMessage); override;
309 procedure SetMap(Res: string);
310 procedure ClearMap();
311 procedure Update(); override;
312 procedure Draw(); override;
313 function GetScaleStr: String;
314 end;
316 TGUIImage = class(TGUIControl)
317 private
318 FImageRes: string;
319 FDefaultRes: string;
320 public
321 constructor Create();
322 destructor Destroy(); override;
323 procedure OnMessage(var Msg: TMessage); override;
324 procedure SetImage(Res: string);
325 procedure ClearImage();
326 procedure Update(); override;
327 procedure Draw(); override;
328 property DefaultRes: string read FDefaultRes write FDefaultRes;
329 end;
331 TGUIListBox = class(TGUIControl)
332 private
333 FItems: SArray;
334 FActiveColor: TRGB;
335 FUnActiveColor: TRGB;
336 FFont: TFont;
337 FStartLine: Integer;
338 FIndex: Integer;
339 FWidth: Word;
340 FHeight: Word;
341 FSort: Boolean;
342 FDrawBack: Boolean;
343 FDrawScroll: Boolean;
344 FOnChangeEvent: TOnChangeEvent;
346 procedure FSetItems(Items: SArray);
347 procedure FSetIndex(aIndex: Integer);
349 public
350 constructor Create(FontID: DWORD; Width, Height: Word);
351 procedure OnMessage(var Msg: TMessage); override;
352 procedure Draw(); override;
353 procedure AddItem(Item: String);
354 procedure SelectItem(Item: String);
355 procedure Clear();
356 function GetWidth(): Word;
357 function GetHeight(): Word;
358 function SelectedItem(): String;
360 property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent;
361 property Sort: Boolean read FSort write FSort;
362 property ItemIndex: Integer read FIndex write FSetIndex;
363 property Items: SArray read FItems write FSetItems;
364 property DrawBack: Boolean read FDrawBack write FDrawBack;
365 property DrawScrollBar: Boolean read FDrawScroll write FDrawScroll;
366 property ActiveColor: TRGB read FActiveColor write FActiveColor;
367 property UnActiveColor: TRGB read FUnActiveColor write FUnActiveColor;
368 property Font: TFont read FFont write FFont;
369 end;
371 TGUIFileListBox = class (TGUIListBox)
372 private
373 FBasePath: String;
374 FPath: String;
375 FFileMask: String;
376 FDirs: Boolean;
378 procedure OpenDir(path: String);
380 public
381 procedure OnMessage(var Msg: TMessage); override;
382 procedure SetBase(path: String);
383 function SelectedItem(): String;
384 procedure UpdateFileList();
386 property Dirs: Boolean read FDirs write FDirs;
387 property FileMask: String read FFileMask write FFileMask;
388 property Path: String read FPath;
389 end;
391 TGUIMemo = class(TGUIControl)
392 private
393 FLines: SArray;
394 FFont: TFont;
395 FStartLine: Integer;
396 FWidth: Word;
397 FHeight: Word;
398 FColor: TRGB;
399 FDrawBack: Boolean;
400 FDrawScroll: Boolean;
401 public
402 constructor Create(FontID: DWORD; Width, Height: Word);
403 procedure OnMessage(var Msg: TMessage); override;
404 procedure Draw; override;
405 procedure Clear;
406 function GetWidth(): Word;
407 function GetHeight(): Word;
408 procedure SetText(Text: string);
409 property DrawBack: Boolean read FDrawBack write FDrawBack;
410 property DrawScrollBar: Boolean read FDrawScroll write FDrawScroll;
411 property Color: TRGB read FColor write FColor;
412 property Font: TFont read FFont write FFont;
413 end;
415 TGUIMainMenu = class(TGUIControl)
416 private
417 FButtons: array of TGUITextButton;
418 FHeader: TGUILabel;
419 FIndex: Integer;
420 FFontID: DWORD;
421 FCounter: Byte;
422 FMarkerID1: DWORD;
423 FMarkerID2: DWORD;
424 public
425 constructor Create(FontID: DWORD; Header: string);
426 destructor Destroy; override;
427 procedure OnMessage(var Msg: TMessage); override;
428 function AddButton(fProc: Pointer; Caption: string; ShowWindow: string = ''): TGUITextButton;
429 function GetButton(Name: string): TGUITextButton;
430 procedure EnableButton(Name: string; e: Boolean);
431 procedure AddSpace();
432 procedure Update; override;
433 procedure Draw; override;
434 end;
436 TControlType = class of TGUIControl;
438 PMenuItem = ^TMenuItem;
439 TMenuItem = record
440 Text: TGUILabel;
441 ControlType: TControlType;
442 Control: TGUIControl;
443 end;
445 TGUIMenu = class(TGUIControl)
446 private
447 FItems: array of TMenuItem;
448 FHeader: TGUILabel;
449 FIndex: Integer;
450 FFontID: DWORD;
451 FCounter: Byte;
452 FAlign: Boolean;
453 FLeft: Integer;
454 function NewItem(): Integer;
455 public
456 constructor Create(HeaderFont, ItemsFont: DWORD; Header: string);
457 destructor Destroy; override;
458 procedure OnMessage(var Msg: TMessage); override;
459 procedure AddSpace();
460 procedure AddLine(fText: string);
461 procedure AddText(fText: string; MaxWidth: Word);
462 function AddLabel(fText: string): TGUILabel;
463 function AddButton(Proc: Pointer; fText: string; _ShowWindow: string = ''): TGUITextButton;
464 function AddScroll(fText: string): TGUIScroll;
465 function AddSwitch(fText: string): TGUISwitch;
466 function AddEdit(fText: string): TGUIEdit;
467 function AddKeyRead(fText: string): TGUIKeyRead;
468 function AddList(fText: string; Width, Height: Word): TGUIListBox;
469 function AddFileList(fText: string; Width, Height: Word): TGUIFileListBox;
470 function AddMemo(fText: string; Width, Height: Word): TGUIMemo;
471 procedure ReAlign();
472 function GetControl(Name: string): TGUIControl;
473 function GetControlsText(Name: string): TGUILabel;
474 procedure Draw; override;
475 procedure Update; override;
476 procedure UpdateIndex();
477 property Align: Boolean read FAlign write FAlign;
478 property Left: Integer read FLeft write FLeft;
479 end;
481 var
482 g_GUIWindows: array of TGUIWindow;
483 g_ActiveWindow: TGUIWindow = nil;
485 procedure g_GUI_Init();
486 function g_GUI_AddWindow(Window: TGUIWindow): TGUIWindow;
487 function g_GUI_GetWindow(Name: string): TGUIWindow;
488 procedure g_GUI_ShowWindow(Name: string);
489 procedure g_GUI_HideWindow(PlaySound: Boolean = True);
490 function g_GUI_Destroy(): Boolean;
491 procedure g_GUI_SaveMenuPos();
492 procedure g_GUI_LoadMenuPos();
494 implementation
496 uses
497 GL, GLExt, g_textures, g_sound, SysUtils,
498 g_game, Math, StrUtils, g_player, g_options, MAPREADER,
499 g_map, MAPDEF, g_weapons;
501 var
502 Box: Array [0..8] of DWORD;
503 Saved_Windows: SArray;
505 procedure g_GUI_Init();
506 begin
507 g_Texture_Get(BOX1, Box[0]);
508 g_Texture_Get(BOX2, Box[1]);
509 g_Texture_Get(BOX3, Box[2]);
510 g_Texture_Get(BOX4, Box[3]);
511 g_Texture_Get(BOX5, Box[4]);
512 g_Texture_Get(BOX6, Box[5]);
513 g_Texture_Get(BOX7, Box[6]);
514 g_Texture_Get(BOX8, Box[7]);
515 g_Texture_Get(BOX9, Box[8]);
516 end;
518 function g_GUI_Destroy(): Boolean;
519 var
520 i: Integer;
521 begin
522 Result := (Length(g_GUIWindows) > 0);
524 for i := 0 to High(g_GUIWindows) do
525 g_GUIWindows[i].Free();
527 g_GUIWindows := nil;
528 g_ActiveWindow := nil;
529 end;
531 function g_GUI_AddWindow(Window: TGUIWindow): TGUIWindow;
532 begin
533 SetLength(g_GUIWindows, Length(g_GUIWindows)+1);
534 g_GUIWindows[High(g_GUIWindows)] := Window;
536 Result := Window;
537 end;
539 function g_GUI_GetWindow(Name: string): TGUIWindow;
540 var
541 i: Integer;
542 begin
543 Result := nil;
545 if g_GUIWindows <> nil then
546 for i := 0 to High(g_GUIWindows) do
547 if g_GUIWindows[i].FName = Name then
548 begin
549 Result := g_GUIWindows[i];
550 Break;
551 end;
553 Assert(Result <> nil, 'GUI_Window "'+Name+'" not found');
554 end;
556 procedure g_GUI_ShowWindow(Name: string);
557 var
558 i: Integer;
559 begin
560 if g_GUIWindows = nil then
561 Exit;
563 for i := 0 to High(g_GUIWindows) do
564 if g_GUIWindows[i].FName = Name then
565 begin
566 g_GUIWindows[i].FPrevWindow := g_ActiveWindow;
567 g_ActiveWindow := g_GUIWindows[i];
569 if g_ActiveWindow.MainWindow then
570 g_ActiveWindow.FPrevWindow := nil;
572 if g_ActiveWindow.FDefControl <> '' then
573 g_ActiveWindow.SetActive(g_ActiveWindow.GetControl(g_ActiveWindow.FDefControl))
574 else
575 g_ActiveWindow.SetActive(nil);
577 if @g_ActiveWindow.FOnShowEvent <> nil then
578 g_ActiveWindow.FOnShowEvent();
580 Break;
581 end;
582 end;
584 procedure g_GUI_HideWindow(PlaySound: Boolean = True);
585 begin
586 if g_ActiveWindow <> nil then
587 begin
588 if @g_ActiveWindow.OnClose <> nil then
589 g_ActiveWindow.OnClose();
590 g_ActiveWindow := g_ActiveWindow.FPrevWindow;
591 if PlaySound then
592 g_Sound_PlayEx(WINDOW_CLOSESOUND);
593 end;
594 end;
596 procedure g_GUI_SaveMenuPos();
597 var
598 len: Integer;
599 win: TGUIWindow;
600 begin
601 SetLength(Saved_Windows, 0);
602 win := g_ActiveWindow;
604 while win <> nil do
605 begin
606 len := Length(Saved_Windows);
607 SetLength(Saved_Windows, len + 1);
609 Saved_Windows[len] := win.Name;
611 if win.MainWindow then
612 win := nil
613 else
614 win := win.FPrevWindow;
615 end;
616 end;
618 procedure g_GUI_LoadMenuPos();
619 var
620 i, j, k, len: Integer;
621 ok: Boolean;
622 begin
623 g_ActiveWindow := nil;
624 len := Length(Saved_Windows);
626 if len = 0 then
627 Exit;
629 // Îêíî ñ ãëàâíûì ìåíþ:
630 g_GUI_ShowWindow(Saved_Windows[len-1]);
632 // Íå ïåðåêëþ÷èëîñü (èëè íåêóäà äàëüøå):
633 if (len = 1) or (g_ActiveWindow = nil) then
634 Exit;
636 // Èùåì êíîïêè â îñòàëüíûõ îêíàõ:
637 for k := len-1 downto 1 do
638 begin
639 ok := False;
641 for i := 0 to Length(g_ActiveWindow.Childs)-1 do
642 begin
643 if g_ActiveWindow.Childs[i] is TGUIMainMenu then
644 begin // GUI_MainMenu
645 with TGUIMainMenu(g_ActiveWindow.Childs[i]) do
646 for j := 0 to Length(FButtons)-1 do
647 if FButtons[j].ShowWindow = Saved_Windows[k-1] then
648 begin
649 FButtons[j].Click(True);
650 ok := True;
651 Break;
652 end;
653 end
654 else // GUI_Menu
655 if g_ActiveWindow.Childs[i] is TGUIMenu then
656 with TGUIMenu(g_ActiveWindow.Childs[i]) do
657 for j := 0 to Length(FItems)-1 do
658 if FItems[j].ControlType = TGUITextButton then
659 if TGUITextButton(FItems[j].Control).ShowWindow = Saved_Windows[k-1] then
660 begin
661 TGUITextButton(FItems[j].Control).Click(True);
662 ok := True;
663 Break;
664 end;
666 if ok then
667 Break;
668 end;
670 // Íå ïåðåêëþ÷èëîñü:
671 if (not ok) or
672 (g_ActiveWindow.Name = Saved_Windows[k]) then
673 Break;
674 end;
675 end;
677 procedure DrawBox(X, Y: Integer; Width, Height: Word);
678 begin
679 e_Draw(Box[0], X, Y, 0, False, False);
680 e_DrawFill(Box[1], X+4, Y, Width*4, 1, 0, False, False);
681 e_Draw(Box[2], X+4+Width*16, Y, 0, False, False);
682 e_DrawFill(Box[3], X, Y+4, 1, Height*4, 0, False, False);
683 e_DrawFill(Box[4], X+4, Y+4, Width, Height, 0, False, False);
684 e_DrawFill(Box[5], X+4+Width*16, Y+4, 1, Height*4, 0, False, False);
685 e_Draw(Box[6], X, Y+4+Height*16, 0, False, False);
686 e_DrawFill(Box[7], X+4, Y+4+Height*16, Width*4, 1, 0, False, False);
687 e_Draw(Box[8], X+4+Width*16, Y+4+Height*16, 0, False, False);
688 end;
690 procedure DrawScroll(X, Y: Integer; Height: Word; Up, Down: Boolean);
691 var
692 ID: DWORD;
693 begin
694 if Height < 3 then Exit;
696 if Up then
697 g_Texture_Get(BSCROLL_UPA, ID)
698 else
699 g_Texture_Get(BSCROLL_UPU, ID);
700 e_Draw(ID, X, Y, 0, False, False);
702 if Down then
703 g_Texture_Get(BSCROLL_DOWNA, ID)
704 else
705 g_Texture_Get(BSCROLL_DOWNU, ID);
706 e_Draw(ID, X, Y+(Height-1)*16, 0, False, False);
708 g_Texture_Get(BSCROLL_MIDDLE, ID);
709 e_DrawFill(ID, X, Y+16, 1, Height-2, 0, False, False);
710 end;
712 { TGUIWindow }
714 constructor TGUIWindow.Create(Name: string);
715 begin
716 Childs := nil;
717 FActiveControl := nil;
718 FName := Name;
719 FOnKeyDown := nil;
720 FOnKeyDownEx := nil;
721 FOnCloseEvent := nil;
722 FOnShowEvent := nil;
723 end;
725 destructor TGUIWindow.Destroy;
726 var
727 i: Integer;
728 begin
729 if Childs = nil then
730 Exit;
732 for i := 0 to High(Childs) do
733 Childs[i].Free();
734 end;
736 function TGUIWindow.AddChild(Child: TGUIControl): TGUIControl;
737 begin
738 Child.FWindow := Self;
740 SetLength(Childs, Length(Childs) + 1);
741 Childs[High(Childs)] := Child;
743 Result := Child;
744 end;
746 procedure TGUIWindow.Update;
747 var
748 i: Integer;
749 begin
750 for i := 0 to High(Childs) do
751 if Childs[i] <> nil then Childs[i].Update;
752 end;
754 procedure TGUIWindow.Draw;
755 var
756 i: Integer;
757 ID: DWORD;
758 begin
759 if FBackTexture <> '' then
760 if g_Texture_Get(FBackTexture, ID) then
761 e_DrawSize(ID, 0, 0, 0, False, False, gScreenWidth, gScreenHeight)
762 else
763 e_Clear(GL_COLOR_BUFFER_BIT, 0.5, 0.5, 0.5);
765 for i := 0 to High(Childs) do
766 if Childs[i] <> nil then Childs[i].Draw;
767 end;
769 procedure TGUIWindow.OnMessage(var Msg: TMessage);
770 begin
771 if FActiveControl <> nil then FActiveControl.OnMessage(Msg);
772 if @FOnKeyDown <> nil then FOnKeyDown(Msg.wParam);
773 if @FOnKeyDownEx <> nil then FOnKeyDownEx(self, Msg.wParam);
775 if Msg.Msg = WM_KEYDOWN then
776 if Msg.wParam = IK_ESCAPE then
777 begin
778 g_GUI_HideWindow;
779 Exit;
780 end;
781 end;
783 procedure TGUIWindow.SetActive(Control: TGUIControl);
784 begin
785 FActiveControl := Control;
786 end;
788 function TGUIWindow.GetControl(Name: String): TGUIControl;
789 var
790 i: Integer;
791 begin
792 Result := nil;
794 if Childs <> nil then
795 for i := 0 to High(Childs) do
796 if Childs[i] <> nil then
797 if LowerCase(Childs[i].FName) = LowerCase(Name) then
798 begin
799 Result := Childs[i];
800 Break;
801 end;
803 Assert(Result <> nil, 'Window Control "'+Name+'" not Found!');
804 end;
806 { TGUIControl }
808 constructor TGUIControl.Create();
809 begin
810 FX := 0;
811 FY := 0;
813 FEnabled := True;
814 end;
816 procedure TGUIControl.OnMessage(var Msg: TMessage);
817 begin
818 if not FEnabled then
819 Exit;
820 end;
822 procedure TGUIControl.Update();
823 begin
825 end;
827 procedure TGUIControl.Draw();
828 begin
830 end;
832 { TGUITextButton }
834 procedure TGUITextButton.Click(Silent: Boolean = False);
835 begin
836 if (FSound <> '') and (not Silent) then
837 g_Sound_PlayEx(FSound);
839 if @Proc <> nil then
840 Proc();
841 if FShowWindow <> '' then
842 g_GUI_ShowWindow(FShowWindow);
843 end;
845 constructor TGUITextButton.Create(Proc: Pointer; FontID: DWORD; Text: string);
846 begin
847 inherited Create();
849 Self.Proc := Proc;
851 FFont := TFont.Create(FontID, FONT_CHAR);
853 FText := Text;
854 end;
856 destructor TGUITextButton.Destroy;
857 begin
859 inherited;
860 end;
862 procedure TGUITextButton.Draw;
863 begin
864 FFont.Draw(FX, FY, FText, FColor.R, FColor.G, FColor.B)
865 end;
867 function TGUITextButton.GetHeight: Integer;
868 var
869 w, h: Word;
870 begin
871 FFont.GetTextSize(FText, w, h);
872 Result := h;
873 end;
875 function TGUITextButton.GetWidth: Integer;
876 var
877 w, h: Word;
878 begin
879 FFont.GetTextSize(FText, w, h);
880 Result := w;
881 end;
883 procedure TGUITextButton.OnMessage(var Msg: TMessage);
884 begin
885 if not FEnabled then Exit;
887 inherited;
889 case Msg.Msg of
890 WM_KEYDOWN:
891 case Msg.wParam of
892 IK_RETURN, IK_KPRETURN: Click();
893 end;
894 end;
895 end;
897 procedure TGUITextButton.Update;
898 begin
899 inherited;
900 end;
902 { TFont }
904 constructor TFont.Create(FontID: DWORD; FontType: TFontType);
905 begin
906 ID := FontID;
908 FScale := 1;
909 FFontType := FontType;
910 end;
912 destructor TFont.Destroy;
913 begin
915 inherited;
916 end;
918 procedure TFont.Draw(X, Y: Integer; Text: string; R, G, B: Byte);
919 begin
920 if FFontType = FONT_CHAR then e_CharFont_PrintEx(ID, X, Y, Text, _RGB(R, G, B), FScale)
921 else e_TextureFontPrintEx(X, Y, Text, ID, R, G, B, FScale);
922 end;
924 procedure TFont.GetTextSize(Text: string; var w, h: Word);
925 var
926 cw, ch: Byte;
927 begin
928 if FFontType = FONT_CHAR then e_CharFont_GetSize(ID, Text, w, h)
929 else
930 begin
931 e_TextureFontGetSize(ID, cw, ch);
932 w := cw*Length(Text);
933 h := ch;
934 end;
936 w := Round(w*FScale);
937 h := Round(h*FScale);
938 end;
940 { TGUIMainMenu }
942 function TGUIMainMenu.AddButton(fProc: Pointer; Caption: string; ShowWindow: string = ''): TGUITextButton;
943 var
944 a, _x: Integer;
945 h, hh: Word;
946 begin
947 FIndex := 0;
949 SetLength(FButtons, Length(FButtons)+1);
950 FButtons[High(FButtons)] := TGUITextButton.Create(fProc, FFontID, Caption);
951 FButtons[High(FButtons)].ShowWindow := ShowWindow;
952 with FButtons[High(FButtons)] do
953 begin
954 if (fProc <> nil) or (ShowWindow <> '') then FColor := MAINMENU_ITEMS_COLOR
955 else FColor := MAINMENU_UNACTIVEITEMS_COLOR;
956 FSound := MAINMENU_CLICKSOUND;
957 end;
959 _x := gScreenWidth div 2;
961 for a := 0 to High(FButtons) do
962 if FButtons[a] <> nil then
963 _x := Min(_x, (gScreenWidth div 2)-(FButtons[a].GetWidth div 2));
965 hh := FHeader.GetHeight;
967 h := hh*(2+Length(FButtons))+MAINMENU_SPACE*(Length(FButtons)-1);
968 h := (gScreenHeight div 2)-(h div 2);
970 with FHeader do
971 begin
972 FX := _x;
973 FY := h;
974 end;
976 Inc(h, hh*2);
978 for a := 0 to High(FButtons) do
979 begin
980 if FButtons[a] <> nil then
981 with FButtons[a] do
982 begin
983 FX := _x;
984 FY := h;
985 end;
987 Inc(h, hh+MAINMENU_SPACE);
988 end;
990 Result := FButtons[High(FButtons)];
991 end;
993 procedure TGUIMainMenu.AddSpace;
994 begin
995 SetLength(FButtons, Length(FButtons)+1);
996 FButtons[High(FButtons)] := nil;
997 end;
999 constructor TGUIMainMenu.Create(FontID: DWORD; Header: string);
1000 begin
1001 inherited Create();
1003 FIndex := -1;
1004 FFontID := FontID;
1005 FCounter := MAINMENU_MARKERDELAY;
1007 g_Texture_Get(MAINMENU_MARKER1, FMarkerID1);
1008 g_Texture_Get(MAINMENU_MARKER2, FMarkerID2);
1010 FHeader := TGUILabel.Create(Header, FFontID);
1011 with FHeader do
1012 begin
1013 FColor := MAINMENU_HEADER_COLOR;
1014 FX := (gScreenWidth div 2)-(GetWidth div 2);
1015 FY := (gScreenHeight div 2)-(GetHeight div 2);
1016 end;
1017 end;
1019 destructor TGUIMainMenu.Destroy;
1020 var
1021 a: Integer;
1022 begin
1023 if FButtons <> nil then
1024 for a := 0 to High(FButtons) do
1025 FButtons[a].Free();
1027 FHeader.Free();
1029 inherited;
1030 end;
1032 procedure TGUIMainMenu.Draw;
1033 var
1034 a: Integer;
1035 begin
1036 inherited;
1038 FHeader.Draw;
1040 if FButtons <> nil then
1041 begin
1042 for a := 0 to High(FButtons) do
1043 if FButtons[a] <> nil then FButtons[a].Draw;
1045 if FIndex <> -1 then
1046 e_Draw(FMarkerID1, FButtons[FIndex].FX-48, FButtons[FIndex].FY, 0, True, False);
1047 end;
1048 end;
1050 procedure TGUIMainMenu.EnableButton(Name: string; e: Boolean);
1051 var
1052 a: Integer;
1053 begin
1054 if FButtons = nil then Exit;
1056 for a := 0 to High(FButtons) do
1057 if (FButtons[a] <> nil) and (FButtons[a].Name = Name) then
1058 begin
1059 if e then FButtons[a].FColor := MAINMENU_ITEMS_COLOR
1060 else FButtons[a].FColor := MAINMENU_UNACTIVEITEMS_COLOR;
1061 FButtons[a].Enabled := e;
1062 Break;
1063 end;
1064 end;
1066 function TGUIMainMenu.GetButton(Name: string): TGUITextButton;
1067 var
1068 a: Integer;
1069 begin
1070 Result := nil;
1072 if FButtons = nil then Exit;
1074 for a := 0 to High(FButtons) do
1075 if (FButtons[a] <> nil) and (FButtons[a].Name = Name) then
1076 begin
1077 Result := FButtons[a];
1078 Break;
1079 end;
1080 end;
1082 procedure TGUIMainMenu.OnMessage(var Msg: TMessage);
1083 var
1084 ok: Boolean;
1085 a: Integer;
1086 begin
1087 if not FEnabled then Exit;
1089 inherited;
1091 if FButtons = nil then Exit;
1093 ok := False;
1094 for a := 0 to High(FButtons) do
1095 if FButtons[a] <> nil then
1096 begin
1097 ok := True;
1098 Break;
1099 end;
1101 if not ok then Exit;
1103 case Msg.Msg of
1104 WM_KEYDOWN:
1105 case Msg.wParam of
1106 IK_UP, IK_KPUP:
1107 begin
1108 repeat
1109 Dec(FIndex);
1110 if FIndex < 0 then FIndex := High(FButtons);
1111 until FButtons[FIndex] <> nil;
1113 g_Sound_PlayEx(MENU_CHANGESOUND);
1114 end;
1115 IK_DOWN, IK_KPDOWN:
1116 begin
1117 repeat
1118 Inc(FIndex);
1119 if FIndex > High(FButtons) then FIndex := 0;
1120 until FButtons[FIndex] <> nil;
1122 g_Sound_PlayEx(MENU_CHANGESOUND);
1123 end;
1124 IK_RETURN, IK_KPRETURN: if (FIndex <> -1) and FButtons[FIndex].FEnabled then FButtons[FIndex].Click;
1125 end;
1126 end;
1127 end;
1129 procedure TGUIMainMenu.Update;
1130 var
1131 t: DWORD;
1132 begin
1133 inherited;
1135 if FCounter = 0 then
1136 begin
1137 t := FMarkerID1;
1138 FMarkerID1 := FMarkerID2;
1139 FMarkerID2 := t;
1141 FCounter := MAINMENU_MARKERDELAY;
1142 end else Dec(FCounter);
1143 end;
1145 { TGUILabel }
1147 constructor TGUILabel.Create(Text: string; FontID: DWORD);
1148 begin
1149 inherited Create();
1151 FFont := TFont.Create(FontID, FONT_CHAR);
1153 FText := Text;
1154 FFixedLen := 0;
1155 FOnClickEvent := nil;
1156 end;
1158 procedure TGUILabel.Draw;
1159 begin
1160 FFont.Draw(FX, FY, FText, FColor.R, FColor.G, FColor.B);
1161 end;
1163 function TGUILabel.GetHeight: Integer;
1164 var
1165 w, h: Word;
1166 begin
1167 FFont.GetTextSize(FText, w, h);
1168 Result := h;
1169 end;
1171 function TGUILabel.GetWidth: Integer;
1172 var
1173 w, h: Word;
1174 begin
1175 if FFixedLen = 0 then
1176 FFont.GetTextSize(FText, w, h)
1177 else
1178 w := e_CharFont_GetMaxWidth(FFont.ID)*FFixedLen;
1179 Result := w;
1180 end;
1182 procedure TGUILabel.OnMessage(var Msg: TMessage);
1183 begin
1184 if not FEnabled then Exit;
1186 inherited;
1188 case Msg.Msg of
1189 WM_KEYDOWN:
1190 case Msg.wParam of
1191 IK_RETURN, IK_KPRETURN: if @FOnClickEvent <> nil then FOnClickEvent();
1192 end;
1193 end;
1194 end;
1196 { TGUIMenu }
1198 function TGUIMenu.AddButton(Proc: Pointer; fText: string; _ShowWindow: string = ''): TGUITextButton;
1199 var
1200 i: Integer;
1201 begin
1202 i := NewItem();
1203 with FItems[i] do
1204 begin
1205 Control := TGUITextButton.Create(Proc, FFontID, fText);
1206 with Control as TGUITextButton do
1207 begin
1208 ShowWindow := _ShowWindow;
1209 FColor := MENU_ITEMSCTRL_COLOR;
1210 end;
1212 Text := nil;
1213 ControlType := TGUITextButton;
1215 Result := (Control as TGUITextButton);
1216 end;
1218 if FIndex = -1 then FIndex := i;
1220 ReAlign();
1221 end;
1223 procedure TGUIMenu.AddLine(fText: string);
1224 var
1225 i: Integer;
1226 begin
1227 i := NewItem();
1228 with FItems[i] do
1229 begin
1230 Text := TGUILabel.Create(fText, FFontID);
1231 with Text do
1232 begin
1233 FColor := MENU_ITEMSTEXT_COLOR;
1234 end;
1236 Control := nil;
1237 end;
1239 ReAlign();
1240 end;
1242 procedure TGUIMenu.AddText(fText: string; MaxWidth: Word);
1243 var
1244 a, i: Integer;
1245 l: SArray;
1246 begin
1247 l := GetLines(fText, FFontID, MaxWidth);
1249 if l = nil then Exit;
1251 for a := 0 to High(l) do
1252 begin
1253 i := NewItem();
1254 with FItems[i] do
1255 begin
1256 Text := TGUILabel.Create(l[a], FFontID);
1257 with Text do
1258 begin
1259 FColor := MENU_ITEMSTEXT_COLOR;
1260 end;
1262 Control := nil;
1263 end;
1264 end;
1266 ReAlign();
1267 end;
1269 procedure TGUIMenu.AddSpace;
1270 var
1271 i: Integer;
1272 begin
1273 i := NewItem();
1274 with FItems[i] do
1275 begin
1276 Text := nil;
1277 Control := nil;
1278 end;
1280 ReAlign();
1281 end;
1283 constructor TGUIMenu.Create(HeaderFont, ItemsFont: DWORD; Header: string);
1284 begin
1285 inherited Create();
1287 FItems := nil;
1288 FIndex := -1;
1289 FFontID := ItemsFont;
1290 FCounter := MENU_MARKERDELAY;
1291 FAlign := True;
1293 FHeader := TGUILabel.Create(Header, HeaderFont);
1294 with FHeader do
1295 begin
1296 FX := (gScreenWidth div 2)-(GetWidth div 2);
1297 FY := 0;
1298 FColor := MAINMENU_HEADER_COLOR;
1299 end;
1300 end;
1302 destructor TGUIMenu.Destroy;
1303 var
1304 a: Integer;
1305 begin
1306 if FItems <> nil then
1307 for a := 0 to High(FItems) do
1308 with FItems[a] do
1309 begin
1310 Text.Free();
1311 Control.Free();
1312 end;
1314 FItems := nil;
1316 FHeader.Free();
1318 inherited;
1319 end;
1321 procedure TGUIMenu.Draw;
1322 var
1323 a, x, y: Integer;
1324 begin
1325 inherited;
1327 if FHeader <> nil then FHeader.Draw;
1329 if FItems <> nil then
1330 for a := 0 to High(FItems) do
1331 begin
1332 if FItems[a].Text <> nil then FItems[a].Text.Draw;
1333 if FItems[a].Control <> nil then FItems[a].Control.Draw;
1334 end;
1336 if (FIndex <> -1) and (FCounter > MENU_MARKERDELAY div 2) then
1337 begin
1338 x := 0;
1339 y := 0;
1341 if FItems[FIndex].Text <> nil then
1342 begin
1343 x := FItems[FIndex].Text.FX;
1344 y := FItems[FIndex].Text.FY;
1345 end
1346 else if FItems[FIndex].Control <> nil then
1347 begin
1348 x := FItems[FIndex].Control.FX;
1349 y := FItems[FIndex].Control.FY;
1350 end;
1352 x := x-e_CharFont_GetMaxWidth(FFontID);
1354 e_CharFont_PrintEx(FFontID, x, y, #16, _RGB(255, 0, 0));
1355 end;
1356 end;
1358 function TGUIMenu.GetControl(Name: String): TGUIControl;
1359 var
1360 a: Integer;
1361 begin
1362 Result := nil;
1364 if FItems <> nil then
1365 for a := 0 to High(FItems) do
1366 if FItems[a].Control <> nil then
1367 if LowerCase(FItems[a].Control.Name) = LowerCase(Name) then
1368 begin
1369 Result := FItems[a].Control;
1370 Break;
1371 end;
1373 Assert(Result <> nil, 'GUI control "'+Name+'" not found!');
1374 end;
1376 function TGUIMenu.GetControlsText(Name: String): TGUILabel;
1377 var
1378 a: Integer;
1379 begin
1380 Result := nil;
1382 if FItems <> nil then
1383 for a := 0 to High(FItems) do
1384 if FItems[a].Control <> nil then
1385 if LowerCase(FItems[a].Control.Name) = LowerCase(Name) then
1386 begin
1387 Result := FItems[a].Text;
1388 Break;
1389 end;
1391 Assert(Result <> nil, 'GUI control''s text "'+Name+'" not found!');
1392 end;
1394 function TGUIMenu.NewItem: Integer;
1395 begin
1396 SetLength(FItems, Length(FItems)+1);
1397 Result := High(FItems);
1398 end;
1400 procedure TGUIMenu.OnMessage(var Msg: TMessage);
1401 var
1402 ok: Boolean;
1403 a, c: Integer;
1404 begin
1405 if not FEnabled then Exit;
1407 inherited;
1409 if FItems = nil then Exit;
1411 ok := False;
1412 for a := 0 to High(FItems) do
1413 if FItems[a].Control <> nil then
1414 begin
1415 ok := True;
1416 Break;
1417 end;
1419 if not ok then Exit;
1421 case Msg.Msg of
1422 WM_KEYDOWN:
1423 begin
1424 case Msg.wParam of
1425 IK_UP, IK_KPUP:
1426 begin
1427 c := 0;
1428 repeat
1429 c := c+1;
1430 if c > Length(FItems) then
1431 begin
1432 FIndex := -1;
1433 Break;
1434 end;
1436 Dec(FIndex);
1437 if FIndex < 0 then FIndex := High(FItems);
1438 until (FItems[FIndex].Control <> nil) and
1439 (FItems[FIndex].Control.Enabled);
1441 FCounter := 0;
1443 g_Sound_PlayEx(MENU_CHANGESOUND);
1444 end;
1446 IK_DOWN, IK_KPDOWN:
1447 begin
1448 c := 0;
1449 repeat
1450 c := c+1;
1451 if c > Length(FItems) then
1452 begin
1453 FIndex := -1;
1454 Break;
1455 end;
1457 Inc(FIndex);
1458 if FIndex > High(FItems) then FIndex := 0;
1459 until (FItems[FIndex].Control <> nil) and
1460 (FItems[FIndex].Control.Enabled);
1462 FCounter := 0;
1464 g_Sound_PlayEx(MENU_CHANGESOUND);
1465 end;
1467 IK_LEFT, IK_RIGHT, IK_KPLEFT, IK_KPRIGHT:
1468 begin
1469 if FIndex <> -1 then
1470 if FItems[FIndex].Control <> nil then
1471 FItems[FIndex].Control.OnMessage(Msg);
1472 end;
1473 IK_RETURN, IK_KPRETURN:
1474 begin
1475 if FIndex <> -1 then
1476 if FItems[FIndex].Control <> nil then
1477 FItems[FIndex].Control.OnMessage(Msg);
1479 g_Sound_PlayEx(MENU_CLICKSOUND);
1480 end;
1481 end;
1482 end;
1483 end;
1484 end;
1486 procedure TGUIMenu.ReAlign();
1487 var
1488 a, tx, cx, w, h: Integer;
1489 begin
1490 if FItems = nil then Exit;
1492 if not FAlign then tx := FLeft else
1493 begin
1494 tx := gScreenWidth;
1495 for a := 0 to High(FItems) do
1496 begin
1497 w := 0;
1498 if FItems[a].Text <> nil then w := FItems[a].Text.GetWidth;
1499 if FItems[a].Control <> nil then
1500 begin
1501 w := w+MENU_HSPACE;
1503 if FItems[a].ControlType = TGUILabel then
1504 w := w+(FItems[a].Control as TGUILabel).GetWidth
1505 else if FItems[a].ControlType = TGUITextButton then
1506 w := w+(FItems[a].Control as TGUITextButton).GetWidth
1507 else if FItems[a].ControlType = TGUIScroll then
1508 w := w+(FItems[a].Control as TGUIScroll).GetWidth
1509 else if FItems[a].ControlType = TGUISwitch then
1510 w := w+(FItems[a].Control as TGUISwitch).GetWidth
1511 else if FItems[a].ControlType = TGUIEdit then
1512 w := w+(FItems[a].Control as TGUIEdit).GetWidth
1513 else if FItems[a].ControlType = TGUIKeyRead then
1514 w := w+(FItems[a].Control as TGUIKeyRead).GetWidth
1515 else if (FItems[a].ControlType = TGUIListBox) then
1516 w := w+(FItems[a].Control as TGUIListBox).GetWidth
1517 else if (FItems[a].ControlType = TGUIFileListBox) then
1518 w := w+(FItems[a].Control as TGUIFileListBox).GetWidth
1519 else if FItems[a].ControlType = TGUIMemo then
1520 w := w+(FItems[a].Control as TGUIMemo).GetWidth;
1521 end;
1523 tx := Min(tx, (gScreenWidth div 2)-(w div 2));
1524 end;
1525 end;
1527 cx := 0;
1528 for a := 0 to High(FItems) do
1529 with FItems[a] do
1530 begin
1531 if (Text <> nil) and (Control = nil) then Continue;
1533 w := 0;
1534 if Text <> nil then w := tx+Text.GetWidth;
1536 if w > cx then cx := w;
1537 end;
1539 cx := cx+MENU_HSPACE;
1541 h := FHeader.GetHeight*2+MENU_VSPACE*(Length(FItems)-1);
1543 for a := 0 to High(FItems) do
1544 with FItems[a] do
1545 begin
1546 if (ControlType = TGUIListBox) or (ControlType = TGUIFileListBox) then
1547 h := h+(FItems[a].Control as TGUIListBox).GetHeight()
1548 else
1549 h := h+e_CharFont_GetMaxHeight(FFontID);
1550 end;
1552 h := (gScreenHeight div 2)-(h div 2);
1554 with FHeader do
1555 begin
1556 FX := (gScreenWidth div 2)-(GetWidth div 2);
1557 FY := h;
1559 Inc(h, GetHeight*2);
1560 end;
1562 for a := 0 to High(FItems) do
1563 with FItems[a] do
1564 begin
1565 if Text <> nil then
1566 with Text do
1567 begin
1568 FX := tx;
1569 FY := h;
1570 end;
1572 if Control <> nil then
1573 with Control do
1574 if Text <> nil then
1575 begin
1576 FX := cx;
1577 FY := h;
1578 end
1579 else
1580 begin
1581 FX := tx;
1582 FY := h;
1583 end;
1585 if (ControlType = TGUIListBox) or (ControlType = TGUIFileListBox) then
1586 Inc(h, (Control as TGUIListBox).GetHeight+MENU_VSPACE)
1587 else if ControlType = TGUIMemo then
1588 Inc(h, (Control as TGUIMemo).GetHeight+MENU_VSPACE)
1589 else
1590 Inc(h, e_CharFont_GetMaxHeight(FFontID)+MENU_VSPACE);
1591 end;
1592 end;
1594 function TGUIMenu.AddScroll(fText: string): TGUIScroll;
1595 var
1596 i: Integer;
1597 begin
1598 i := NewItem();
1599 with FItems[i] do
1600 begin
1601 Control := TGUIScroll.Create();
1603 Text := TGUILabel.Create(fText, FFontID);
1604 with Text do
1605 begin
1606 FColor := MENU_ITEMSTEXT_COLOR;
1607 end;
1609 ControlType := TGUIScroll;
1611 Result := (Control as TGUIScroll);
1612 end;
1614 if FIndex = -1 then FIndex := i;
1616 ReAlign();
1617 end;
1619 function TGUIMenu.AddSwitch(fText: string): TGUISwitch;
1620 var
1621 i: Integer;
1622 begin
1623 i := NewItem();
1624 with FItems[i] do
1625 begin
1626 Control := TGUISwitch.Create(FFontID);
1627 (Control as TGUISwitch).FColor := MENU_ITEMSCTRL_COLOR;
1629 Text := TGUILabel.Create(fText, FFontID);
1630 with Text do
1631 begin
1632 FColor := MENU_ITEMSTEXT_COLOR;
1633 end;
1635 ControlType := TGUISwitch;
1637 Result := (Control as TGUISwitch);
1638 end;
1640 if FIndex = -1 then FIndex := i;
1642 ReAlign();
1643 end;
1645 function TGUIMenu.AddEdit(fText: string): TGUIEdit;
1646 var
1647 i: Integer;
1648 begin
1649 i := NewItem();
1650 with FItems[i] do
1651 begin
1652 Control := TGUIEdit.Create(FFontID);
1653 with Control as TGUIEdit do
1654 begin
1655 FWindow := Self.FWindow;
1656 FColor := MENU_ITEMSCTRL_COLOR;
1657 end;
1659 if fText = '' then Text := nil else
1660 begin
1661 Text := TGUILabel.Create(fText, FFontID);
1662 Text.FColor := MENU_ITEMSTEXT_COLOR;
1663 end;
1665 ControlType := TGUIEdit;
1667 Result := (Control as TGUIEdit);
1668 end;
1670 if FIndex = -1 then FIndex := i;
1672 ReAlign();
1673 end;
1675 procedure TGUIMenu.Update;
1676 var
1677 a: Integer;
1678 begin
1679 inherited;
1681 if FCounter = 0 then FCounter := MENU_MARKERDELAY else Dec(FCounter);
1683 if FItems <> nil then
1684 for a := 0 to High(FItems) do
1685 if FItems[a].Control <> nil then
1686 (FItems[a].Control as FItems[a].ControlType).Update;
1687 end;
1689 function TGUIMenu.AddKeyRead(fText: string): TGUIKeyRead;
1690 var
1691 i: Integer;
1692 begin
1693 i := NewItem();
1694 with FItems[i] do
1695 begin
1696 Control := TGUIKeyRead.Create(FFontID);
1697 with Control as TGUIKeyRead do
1698 begin
1699 FWindow := Self.FWindow;
1700 FColor := MENU_ITEMSCTRL_COLOR;
1701 end;
1703 Text := TGUILabel.Create(fText, FFontID);
1704 with Text do
1705 begin
1706 FColor := MENU_ITEMSTEXT_COLOR;
1707 end;
1709 ControlType := TGUIKeyRead;
1711 Result := (Control as TGUIKeyRead);
1712 end;
1714 if FIndex = -1 then FIndex := i;
1716 ReAlign();
1717 end;
1719 function TGUIMenu.AddList(fText: string; Width, Height: Word): TGUIListBox;
1720 var
1721 i: Integer;
1722 begin
1723 i := NewItem();
1724 with FItems[i] do
1725 begin
1726 Control := TGUIListBox.Create(FFontID, Width, Height);
1727 with Control as TGUIListBox do
1728 begin
1729 FWindow := Self.FWindow;
1730 FActiveColor := MENU_ITEMSCTRL_COLOR;
1731 FUnActiveColor := MENU_ITEMSTEXT_COLOR;
1732 end;
1734 Text := TGUILabel.Create(fText, FFontID);
1735 with Text do
1736 begin
1737 FColor := MENU_ITEMSTEXT_COLOR;
1738 end;
1740 ControlType := TGUIListBox;
1742 Result := (Control as TGUIListBox);
1743 end;
1745 if FIndex = -1 then FIndex := i;
1747 ReAlign();
1748 end;
1750 function TGUIMenu.AddFileList(fText: string; Width, Height: Word): TGUIFileListBox;
1751 var
1752 i: Integer;
1753 begin
1754 i := NewItem();
1755 with FItems[i] do
1756 begin
1757 Control := TGUIFileListBox.Create(FFontID, Width, Height);
1758 with Control as TGUIFileListBox do
1759 begin
1760 FWindow := Self.FWindow;
1761 FActiveColor := MENU_ITEMSCTRL_COLOR;
1762 FUnActiveColor := MENU_ITEMSTEXT_COLOR;
1763 end;
1765 if fText = '' then Text := nil else
1766 begin
1767 Text := TGUILabel.Create(fText, FFontID);
1768 Text.FColor := MENU_ITEMSTEXT_COLOR;
1769 end;
1771 ControlType := TGUIFileListBox;
1773 Result := (Control as TGUIFileListBox);
1774 end;
1776 if FIndex = -1 then FIndex := i;
1778 ReAlign();
1779 end;
1781 function TGUIMenu.AddLabel(fText: string): TGUILabel;
1782 var
1783 i: Integer;
1784 begin
1785 i := NewItem();
1786 with FItems[i] do
1787 begin
1788 Control := TGUILabel.Create('', FFontID);
1789 with Control as TGUILabel do
1790 begin
1791 FWindow := Self.FWindow;
1792 FColor := MENU_ITEMSCTRL_COLOR;
1793 end;
1795 Text := TGUILabel.Create(fText, FFontID);
1796 with Text do
1797 begin
1798 FColor := MENU_ITEMSTEXT_COLOR;
1799 end;
1801 ControlType := TGUILabel;
1803 Result := (Control as TGUILabel);
1804 end;
1806 if FIndex = -1 then FIndex := i;
1808 ReAlign();
1809 end;
1811 function TGUIMenu.AddMemo(fText: string; Width, Height: Word): TGUIMemo;
1812 var
1813 i: Integer;
1814 begin
1815 i := NewItem();
1816 with FItems[i] do
1817 begin
1818 Control := TGUIMemo.Create(FFontID, Width, Height);
1819 with Control as TGUIMemo do
1820 begin
1821 FWindow := Self.FWindow;
1822 FColor := MENU_ITEMSTEXT_COLOR;
1823 end;
1825 if fText = '' then Text := nil else
1826 begin
1827 Text := TGUILabel.Create(fText, FFontID);
1828 Text.FColor := MENU_ITEMSTEXT_COLOR;
1829 end;
1831 ControlType := TGUIMemo;
1833 Result := (Control as TGUIMemo);
1834 end;
1836 if FIndex = -1 then FIndex := i;
1838 ReAlign();
1839 end;
1841 procedure TGUIMenu.UpdateIndex();
1842 var
1843 res: Boolean;
1844 begin
1845 res := True;
1847 while res do
1848 begin
1849 if (FIndex < 0) or (FIndex > High(FItems)) then
1850 begin
1851 FIndex := -1;
1852 res := False;
1853 end
1854 else
1855 if FItems[FIndex].Control.Enabled then
1856 res := False
1857 else
1858 Inc(FIndex);
1859 end;
1860 end;
1862 { TGUIScroll }
1864 constructor TGUIScroll.Create;
1865 begin
1866 inherited Create();
1868 FMax := 0;
1869 FOnChangeEvent := nil;
1871 g_Texture_Get(SCROLL_LEFT, FLeftID);
1872 g_Texture_Get(SCROLL_RIGHT, FRightID);
1873 g_Texture_Get(SCROLL_MIDDLE, FMiddleID);
1874 g_Texture_Get(SCROLL_MARKER, FMarkerID);
1875 end;
1877 procedure TGUIScroll.Draw;
1878 var
1879 a: Integer;
1880 begin
1881 inherited;
1883 e_Draw(FLeftID, FX, FY, 0, True, False);
1884 e_Draw(FRightID, FX+8+(FMax+1)*8, FY, 0, True, False);
1886 for a := 0 to FMax do
1887 e_Draw(FMiddleID, FX+8+a*8, FY, 0, True, False);
1889 e_Draw(FMarkerID, FX+8+FValue*8, FY, 0, True, False);
1890 end;
1892 procedure TGUIScroll.FSetValue(a: Integer);
1893 begin
1894 if a > FMax then FValue := FMax else FValue := a;
1895 end;
1897 function TGUIScroll.GetWidth: Word;
1898 begin
1899 Result := 16+(FMax+1)*8;
1900 end;
1902 procedure TGUIScroll.OnMessage(var Msg: TMessage);
1903 begin
1904 if not FEnabled then Exit;
1906 inherited;
1908 case Msg.Msg of
1909 WM_KEYDOWN:
1910 begin
1911 case Msg.wParam of
1912 IK_LEFT, IK_KPLEFT:
1913 if FValue > 0 then
1914 begin
1915 Dec(FValue);
1916 g_Sound_PlayEx(SCROLL_SUBSOUND);
1917 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
1918 end;
1919 IK_RIGHT, IK_KPRIGHT:
1920 if FValue < FMax then
1921 begin
1922 Inc(FValue);
1923 g_Sound_PlayEx(SCROLL_ADDSOUND);
1924 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
1925 end;
1926 end;
1927 end;
1928 end;
1929 end;
1931 procedure TGUIScroll.Update;
1932 begin
1933 inherited;
1935 end;
1937 { TGUISwitch }
1939 procedure TGUISwitch.AddItem(Item: string);
1940 begin
1941 SetLength(FItems, Length(FItems)+1);
1942 FItems[High(FItems)] := Item;
1944 if FIndex = -1 then FIndex := 0;
1945 end;
1947 constructor TGUISwitch.Create(FontID: DWORD);
1948 begin
1949 inherited Create();
1951 FIndex := -1;
1953 FFont := TFont.Create(FontID, FONT_CHAR);
1954 end;
1956 procedure TGUISwitch.Draw;
1957 begin
1958 inherited;
1960 FFont.Draw(FX, FY, FItems[FIndex], FColor.R, FColor.G, FColor.B);
1961 end;
1963 function TGUISwitch.GetText: string;
1964 begin
1965 if FIndex <> -1 then Result := FItems[FIndex]
1966 else Result := '';
1967 end;
1969 function TGUISwitch.GetWidth: Word;
1970 var
1971 a: Integer;
1972 w, h: Word;
1973 begin
1974 Result := 0;
1976 if FItems = nil then Exit;
1978 for a := 0 to High(FItems) do
1979 begin
1980 FFont.GetTextSize(FItems[a], w, h);
1981 if w > Result then Result := w;
1982 end;
1983 end;
1985 procedure TGUISwitch.OnMessage(var Msg: TMessage);
1986 begin
1987 if not FEnabled then Exit;
1989 inherited;
1991 if FItems = nil then Exit;
1993 case Msg.Msg of
1994 WM_KEYDOWN:
1995 case Msg.wParam of
1996 IK_RETURN, IK_RIGHT, IK_KPRETURN, IK_KPRIGHT:
1997 begin
1998 if FIndex < High(FItems) then
1999 Inc(FIndex)
2000 else
2001 FIndex := 0;
2003 if @FOnChangeEvent <> nil then
2004 FOnChangeEvent(Self);
2005 end;
2007 IK_LEFT, IK_KPLEFT:
2008 begin
2009 if FIndex > 0 then
2010 Dec(FIndex)
2011 else
2012 FIndex := High(FItems);
2014 if @FOnChangeEvent <> nil then
2015 FOnChangeEvent(Self);
2016 end;
2017 end;
2018 end;
2019 end;
2021 procedure TGUISwitch.Update;
2022 begin
2023 inherited;
2025 end;
2027 { TGUIEdit }
2029 constructor TGUIEdit.Create(FontID: DWORD);
2030 begin
2031 inherited Create();
2033 FFont := TFont.Create(FontID, FONT_CHAR);
2035 FMaxLength := 0;
2036 FWidth := 0;
2038 g_Texture_Get(EDIT_LEFT, FLeftID);
2039 g_Texture_Get(EDIT_RIGHT, FRightID);
2040 g_Texture_Get(EDIT_MIDDLE, FMiddleID);
2041 end;
2043 procedure TGUIEdit.Draw;
2044 var
2045 c, w, h: Word;
2046 begin
2047 inherited;
2049 e_Draw(FLeftID, FX, FY, 0, True, False);
2050 e_Draw(FRightID, FX+8+FWidth*16, FY, 0, True, False);
2052 for c := 0 to FWidth-1 do
2053 e_Draw(FMiddleID, FX+8+c*16, FY, 0, True, False);
2055 FFont.Draw(FX+8, FY, FText, FColor.R, FColor.G, FColor.B);
2057 if FWindow.FActiveControl = Self then
2058 begin
2059 FFont.GetTextSize(Copy(FText, 1, FCaretPos), w, h);
2060 h := e_CharFont_GetMaxHeight(FFont.ID);
2061 e_DrawLine(2, FX+8+w, FY+h-3, FX+8+w+EDIT_CURSORLEN, FY+h-3,
2062 EDIT_CURSORCOLOR.R, EDIT_CURSORCOLOR.G, EDIT_CURSORCOLOR.B);
2063 end;
2064 end;
2066 function TGUIEdit.GetWidth: Word;
2067 begin
2068 Result := 16+FWidth*16;
2069 end;
2071 procedure TGUIEdit.OnMessage(var Msg: TMessage);
2072 begin
2073 if not FEnabled then Exit;
2075 inherited;
2077 with Msg do
2078 case Msg of
2079 WM_CHAR:
2080 if FOnlyDigits then
2081 begin
2082 if (wParam in [48..57]) and (Chr(wParam) <> '`') then
2083 if Length(Text) < FMaxLength then
2084 begin
2085 Insert(Chr(wParam), FText, FCaretPos + 1);
2086 Inc(FCaretPos);
2087 end;
2088 end
2089 else
2090 begin
2091 if (wParam in [32..255]) and (Chr(wParam) <> '`') then
2092 if Length(Text) < FMaxLength then
2093 begin
2094 Insert(Chr(wParam), FText, FCaretPos + 1);
2095 Inc(FCaretPos);
2096 end;
2097 end;
2098 WM_KEYDOWN:
2099 case wParam of
2100 IK_BACKSPACE:
2101 begin
2102 Delete(FText, FCaretPos, 1);
2103 if FCaretPos > 0 then Dec(FCaretPos);
2104 end;
2105 IK_DELETE: Delete(FText, FCaretPos + 1, 1);
2106 IK_END, IK_KPEND: FCaretPos := Length(FText);
2107 IK_HOME, IK_KPHOME: FCaretPos := 0;
2108 IK_LEFT, IK_KPLEFT: if FCaretPos > 0 then Dec(FCaretPos);
2109 IK_RIGHT, IK_KPRIGHT: if FCaretPos < Length(FText) then Inc(FCaretPos);
2110 IK_RETURN, IK_KPRETURN:
2111 with FWindow do
2112 begin
2113 if FActiveControl <> Self then
2114 begin
2115 SetActive(Self);
2116 if @FOnEnterEvent <> nil then FOnEnterEvent(Self);
2117 end
2118 else
2119 begin
2120 if FDefControl <> '' then SetActive(GetControl(FDefControl))
2121 else SetActive(nil);
2122 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
2123 end;
2124 end;
2125 end;
2126 end;
2127 end;
2129 procedure TGUIEdit.SetText(Text: string);
2130 begin
2131 if Length(Text) > FMaxLength then SetLength(Text, FMaxLength);
2132 FText := Text;
2133 FCaretPos := Length(FText);
2134 end;
2136 procedure TGUIEdit.Update;
2137 begin
2138 inherited;
2139 end;
2141 { TGUIKeyRead }
2143 constructor TGUIKeyRead.Create(FontID: DWORD);
2144 begin
2145 inherited Create();
2147 FFont := TFont.Create(FontID, FONT_CHAR);
2148 end;
2150 procedure TGUIKeyRead.Draw;
2151 begin
2152 inherited;
2154 FFont.Draw(FX, FY, IfThen(FIsQuery, KEYREAD_QUERY, IfThen(FKey <> 0, e_KeyNames[FKey], KEYREAD_CLEAR)),
2155 FColor.R, FColor.G, FColor.B);
2156 end;
2158 function TGUIKeyRead.GetWidth: Word;
2159 var
2160 a: Byte;
2161 w, h: Word;
2162 begin
2163 Result := 0;
2165 for a := 0 to 255 do
2166 begin
2167 FFont.GetTextSize(e_KeyNames[a], w, h);
2168 Result := Max(Result, w);
2169 end;
2171 FFont.GetTextSize(KEYREAD_QUERY, w, h);
2172 if w > Result then Result := w;
2174 FFont.GetTextSize(KEYREAD_CLEAR, w, h);
2175 if w > Result then Result := w;
2176 end;
2178 procedure TGUIKeyRead.OnMessage(var Msg: TMessage);
2179 begin
2180 inherited;
2182 if not FEnabled then
2183 Exit;
2185 with Msg do
2186 case Msg of
2187 WM_KEYDOWN:
2188 case wParam of
2189 IK_ESCAPE:
2190 begin
2191 if FIsQuery then
2192 with FWindow do
2193 if FDefControl <> '' then
2194 SetActive(GetControl(FDefControl))
2195 else
2196 SetActive(nil);
2198 FIsQuery := False;
2199 end;
2200 IK_RETURN, IK_KPRETURN:
2201 begin
2202 if not FIsQuery then
2203 begin
2204 with FWindow do
2205 if FActiveControl <> Self then
2206 SetActive(Self);
2208 FIsQuery := True;
2209 end
2210 else
2211 begin
2212 FKey := IK_ENTER; // <Enter>
2213 FIsQuery := False;
2215 with FWindow do
2216 if FDefControl <> '' then
2217 SetActive(GetControl(FDefControl))
2218 else
2219 SetActive(nil);
2220 end;
2221 end;
2222 end;
2224 MESSAGE_DIKEY:
2225 if FIsQuery and (wParam <> IK_ENTER) and (wParam <> IK_KPRETURN) then // Not <Enter
2226 begin
2227 if e_KeyNames[wParam] <> '' then
2228 FKey := wParam;
2229 FIsQuery := False;
2231 with FWindow do
2232 if FDefControl <> '' then
2233 SetActive(GetControl(FDefControl))
2234 else
2235 SetActive(nil);
2236 end;
2237 end;
2238 end;
2240 { TGUIModelView }
2242 constructor TGUIModelView.Create;
2243 begin
2244 inherited Create();
2246 FModel := nil;
2247 end;
2249 destructor TGUIModelView.Destroy;
2250 begin
2251 FModel.Free();
2253 inherited;
2254 end;
2256 procedure TGUIModelView.Draw;
2257 begin
2258 inherited;
2260 DrawBox(FX, FY, 4, 4);
2262 if FModel <> nil then FModel.Draw(FX+4, FY+4);
2263 end;
2265 procedure TGUIModelView.NextAnim();
2266 begin
2267 if FModel = nil then
2268 Exit;
2270 if FModel.Animation < A_PAIN then
2271 FModel.ChangeAnimation(FModel.Animation+1, True)
2272 else
2273 FModel.ChangeAnimation(A_STAND, True);
2274 end;
2276 procedure TGUIModelView.NextWeapon();
2277 begin
2278 if FModel = nil then
2279 Exit;
2281 if FModel.Weapon < WEAPON_SUPERPULEMET then
2282 FModel.SetWeapon(FModel.Weapon+1)
2283 else
2284 FModel.SetWeapon(WEAPON_KASTET);
2285 end;
2287 procedure TGUIModelView.OnMessage(var Msg: TMessage);
2288 begin
2289 inherited;
2291 end;
2293 procedure TGUIModelView.SetColor(Red, Green, Blue: Byte);
2294 begin
2295 if FModel <> nil then FModel.SetColor(Red, Green, Blue);
2296 end;
2298 procedure TGUIModelView.SetModel(ModelName: string);
2299 begin
2300 FModel.Free();
2302 FModel := g_PlayerModel_Get(ModelName);
2303 end;
2305 procedure TGUIModelView.Update;
2306 begin
2307 inherited;
2309 a := not a;
2310 if a then Exit;
2312 if FModel <> nil then FModel.Update;
2313 end;
2315 { TGUIMapPreview }
2317 constructor TGUIMapPreview.Create();
2318 begin
2319 inherited Create();
2320 ClearMap;
2321 end;
2323 destructor TGUIMapPreview.Destroy();
2324 begin
2325 ClearMap;
2326 inherited;
2327 end;
2329 procedure TGUIMapPreview.Draw();
2330 var
2331 a: Integer;
2332 r, g, b: Byte;
2333 begin
2334 inherited;
2336 DrawBox(FX, FY, MAPPREVIEW_WIDTH, MAPPREVIEW_HEIGHT);
2338 if (FMapSize.X <= 0) or (FMapSize.Y <= 0) then
2339 Exit;
2341 e_DrawFillQuad(FX+4, FY+4,
2342 FX+4 + Trunc(FMapSize.X / FScale) - 1,
2343 FY+4 + Trunc(FMapSize.Y / FScale) - 1,
2344 32, 32, 32, 0);
2346 if FMapData <> nil then
2347 for a := 0 to High(FMapData) do
2348 with FMapData[a] do
2349 begin
2350 if X1 > MAPPREVIEW_WIDTH*16 then Continue;
2351 if Y1 > MAPPREVIEW_HEIGHT*16 then Continue;
2353 if X2 < 0 then Continue;
2354 if Y2 < 0 then Continue;
2356 if X2 > MAPPREVIEW_WIDTH*16 then X2 := MAPPREVIEW_WIDTH*16;
2357 if Y2 > MAPPREVIEW_HEIGHT*16 then Y2 := MAPPREVIEW_HEIGHT*16;
2359 if X1 < 0 then X1 := 0;
2360 if Y1 < 0 then Y1 := 0;
2362 case PanelType of
2363 PANEL_WALL:
2364 begin
2365 r := 255;
2366 g := 255;
2367 b := 255;
2368 end;
2369 PANEL_CLOSEDOOR:
2370 begin
2371 r := 255;
2372 g := 255;
2373 b := 0;
2374 end;
2375 PANEL_WATER:
2376 begin
2377 r := 0;
2378 g := 0;
2379 b := 192;
2380 end;
2381 PANEL_ACID1:
2382 begin
2383 r := 0;
2384 g := 176;
2385 b := 0;
2386 end;
2387 PANEL_ACID2:
2388 begin
2389 r := 176;
2390 g := 0;
2391 b := 0;
2392 end;
2393 else
2394 begin
2395 r := 128;
2396 g := 128;
2397 b := 128;
2398 end;
2399 end;
2401 if ((X2-X1) > 0) and ((Y2-Y1) > 0) then
2402 e_DrawFillQuad(FX+4 + X1, FY+4 + Y1,
2403 FX+4 + X2 - 1, FY+4 + Y2 - 1, r, g, b, 0);
2404 end;
2405 end;
2407 procedure TGUIMapPreview.OnMessage(var Msg: TMessage);
2408 begin
2409 inherited;
2411 end;
2413 procedure TGUIMapPreview.SetMap(Res: string);
2414 var
2415 WAD: TWADEditor_1;
2416 MapReader: TMapReader_1;
2417 panels: TPanelsRec1Array;
2418 header: TMapHeaderRec_1;
2419 a: Integer;
2420 FileName, SectionName, ResName: string;
2421 Data: Pointer;
2422 Len: Integer;
2423 rX, rY: Single;
2424 begin
2425 g_ProcessResourceStr(Res, FileName, SectionName, ResName);
2427 WAD := TWADEditor_1.Create();
2428 if not WAD.ReadFile(FileName) then
2429 begin
2430 WAD.Free();
2431 Exit;
2432 end;
2434 if not WAD.GetResource('', ResName, Data, Len) then
2435 begin
2436 WAD.Free();
2437 Exit;
2438 end;
2440 WAD.Free();
2442 MapReader := TMapReader_1.Create();
2444 if not MapReader.LoadMap(Data) then
2445 begin
2446 FreeMem(Data);
2447 MapReader.Free();
2448 FMapSize.X := 0;
2449 FMapSize.Y := 0;
2450 FScale := 0.0;
2451 FMapData := nil;
2452 Exit;
2453 end;
2455 FreeMem(Data);
2457 panels := MapReader.GetPanels();
2458 header := MapReader.GetMapHeader();
2460 FMapSize.X := header.Width div 16;
2461 FMapSize.Y := header.Height div 16;
2463 rX := Ceil(header.Width / (MAPPREVIEW_WIDTH*256.0));
2464 rY := Ceil(header.Height / (MAPPREVIEW_HEIGHT*256.0));
2465 FScale := max(rX, rY);
2467 FMapData := nil;
2469 if panels <> nil then
2470 for a := 0 to High(panels) do
2471 if WordBool(panels[a].PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or
2472 PANEL_STEP or PANEL_WATER or
2473 PANEL_ACID1 or PANEL_ACID2)) then
2474 begin
2475 SetLength(FMapData, Length(FMapData)+1);
2476 with FMapData[High(FMapData)] do
2477 begin
2478 X1 := panels[a].X div 16;
2479 Y1 := panels[a].Y div 16;
2481 X2 := (panels[a].X + panels[a].Width) div 16;
2482 Y2 := (panels[a].Y + panels[a].Height) div 16;
2484 X1 := Trunc(X1/FScale + 0.5);
2485 Y1 := Trunc(Y1/FScale + 0.5);
2486 X2 := Trunc(X2/FScale + 0.5);
2487 Y2 := Trunc(Y2/FScale + 0.5);
2489 if (X1 <> X2) or (Y1 <> Y2) then
2490 begin
2491 if X1 = X2 then
2492 X2 := X2 + 1;
2493 if Y1 = Y2 then
2494 Y2 := Y2 + 1;
2495 end;
2497 PanelType := panels[a].PanelType;
2498 end;
2499 end;
2501 panels := nil;
2503 MapReader.Free();
2504 end;
2506 procedure TGUIMapPreview.ClearMap();
2507 begin
2508 SetLength(FMapData, 0);
2509 FMapData := nil;
2510 FMapSize.X := 0;
2511 FMapSize.Y := 0;
2512 FScale := 0.0;
2513 end;
2515 procedure TGUIMapPreview.Update();
2516 begin
2517 inherited;
2519 end;
2521 function TGUIMapPreview.GetScaleStr(): String;
2522 begin
2523 if FScale > 0.0 then
2524 begin
2525 Result := FloatToStrF(FScale*16.0, ffFixed, 3, 3);
2526 while (Result[Length(Result)] = '0') do
2527 Delete(Result, Length(Result), 1);
2528 if (Result[Length(Result)] = ',') or (Result[Length(Result)] = '.') then
2529 Delete(Result, Length(Result), 1);
2530 Result := '1 : ' + Result;
2531 end
2532 else
2533 Result := '';
2534 end;
2536 { TGUIListBox }
2538 procedure TGUIListBox.AddItem(Item: string);
2539 begin
2540 SetLength(FItems, Length(FItems)+1);
2541 FItems[High(FItems)] := Item;
2543 if FSort then g_Basic.Sort(FItems);
2544 end;
2546 procedure TGUIListBox.Clear();
2547 begin
2548 FItems := nil;
2550 FStartLine := 0;
2551 FIndex := -1;
2552 end;
2554 constructor TGUIListBox.Create(FontID: DWORD; Width, Height: Word);
2555 begin
2556 inherited Create();
2558 FFont := TFont.Create(FontID, FONT_CHAR);
2560 FWidth := Width;
2561 FHeight := Height;
2562 FIndex := -1;
2563 FOnChangeEvent := nil;
2564 FDrawBack := True;
2565 FDrawScroll := True;
2566 end;
2568 procedure TGUIListBox.Draw;
2569 var
2570 w2, h2: Word;
2571 a: Integer;
2572 s: string;
2573 begin
2574 inherited;
2576 if FDrawBack then DrawBox(FX, FY, FWidth+1, FHeight);
2577 if FDrawScroll then
2578 DrawScroll(FX+4+FWidth*16, FY+4, FHeight, (FStartLine > 0) and (FItems <> nil),
2579 (FStartLine+FHeight-1 < High(FItems)) and (FItems <> nil));
2581 if FItems <> nil then
2582 for a := FStartLine to Min(High(FItems), FStartLine+FHeight-1) do
2583 begin
2584 s := Items[a];
2586 FFont.GetTextSize(s, w2, h2);
2587 while (Length(s) > 0) and (w2 > FWidth*16) do
2588 begin
2589 SetLength(s, Length(s)-1);
2590 FFont.GetTextSize(s, w2, h2);
2591 end;
2593 if a = FIndex then
2594 FFont.Draw(FX+4, FY+4+(a-FStartLine)*16, s, FActiveColor.R, FActiveColor.G, FActiveColor.B)
2595 else
2596 FFont.Draw(FX+4, FY+4+(a-FStartLine)*16, s, FUnActiveColor.R, FUnActiveColor.G, FUnActiveColor.B);
2597 end;
2598 end;
2600 function TGUIListBox.GetHeight: Word;
2601 begin
2602 Result := 8+FHeight*16;
2603 end;
2605 function TGUIListBox.GetWidth: Word;
2606 begin
2607 Result := 8+(FWidth+1)*16;
2608 end;
2610 procedure TGUIListBox.OnMessage(var Msg: TMessage);
2611 var
2612 a: Integer;
2613 begin
2614 if not FEnabled then Exit;
2616 inherited;
2618 if FItems = nil then Exit;
2620 with Msg do
2621 case Msg of
2622 WM_KEYDOWN:
2623 case wParam of
2624 IK_HOME, IK_KPHOME:
2625 begin
2626 FIndex := 0;
2627 FStartLine := 0;
2628 end;
2629 IK_END, IK_KPEND:
2630 begin
2631 FIndex := High(FItems);
2632 FStartLine := Max(High(FItems)-FHeight+1, 0);
2633 end;
2634 IK_UP, IK_LEFT, IK_KPUP, IK_KPLEFT:
2635 if FIndex > 0 then
2636 begin
2637 Dec(FIndex);
2638 if FIndex < FStartLine then Dec(FStartLine);
2639 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
2640 end;
2641 IK_DOWN, IK_RIGHT, IK_KPDOWN, IK_KPRIGHT:
2642 if FIndex < High(FItems) then
2643 begin
2644 Inc(FIndex);
2645 if FIndex > FStartLine+FHeight-1 then Inc(FStartLine);
2646 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
2647 end;
2648 IK_RETURN, IK_KPRETURN:
2649 with FWindow do
2650 begin
2651 if FActiveControl <> Self then SetActive(Self)
2652 else
2653 if FDefControl <> '' then SetActive(GetControl(FDefControl))
2654 else SetActive(nil);
2655 end;
2656 end;
2657 WM_CHAR:
2658 for a := 0 to High(FItems) do
2659 if (Length(FItems[a]) > 0) and (LowerCase(FItems[a][1]) = LowerCase(Chr(wParam))) then
2660 begin
2661 FIndex := a;
2662 FStartLine := Min(Max(FIndex-1, 0), Length(FItems)-FHeight);
2663 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
2664 Break;
2665 end;
2666 end;
2667 end;
2669 function TGUIListBox.SelectedItem(): String;
2670 begin
2671 Result := '';
2673 if (FIndex < 0) or (FItems = nil) or
2674 (FIndex > High(FItems)) then
2675 Exit;
2677 Result := FItems[FIndex];
2678 end;
2680 procedure TGUIListBox.FSetItems(Items: SArray);
2681 begin
2682 if FItems <> nil then
2683 FItems := nil;
2685 FItems := Items;
2687 FStartLine := 0;
2688 FIndex := -1;
2690 if FSort then g_Basic.Sort(FItems);
2691 end;
2693 procedure TGUIListBox.SelectItem(Item: String);
2694 var
2695 a: Integer;
2696 begin
2697 if FItems = nil then
2698 Exit;
2700 FIndex := 0;
2701 Item := LowerCase(Item);
2703 for a := 0 to High(FItems) do
2704 if LowerCase(FItems[a]) = Item then
2705 begin
2706 FIndex := a;
2707 Break;
2708 end;
2710 if FIndex < FHeight then
2711 FStartLine := 0
2712 else
2713 FStartLine := Min(FIndex, Length(FItems)-FHeight);
2714 end;
2716 procedure TGUIListBox.FSetIndex(aIndex: Integer);
2717 begin
2718 if FItems = nil then
2719 Exit;
2721 if (aIndex < 0) or (aIndex > High(FItems)) then
2722 Exit;
2724 FIndex := aIndex;
2726 if FIndex <= FHeight then
2727 FStartLine := 0
2728 else
2729 FStartLine := Min(FIndex, Length(FItems)-FHeight);
2730 end;
2732 { TGUIFileListBox }
2734 procedure TGUIFileListBox.OnMessage(var Msg: TMessage);
2735 var
2736 a: Integer;
2737 begin
2738 if not FEnabled then
2739 Exit;
2741 if FItems = nil then
2742 Exit;
2744 with Msg do
2745 case Msg of
2746 WM_KEYDOWN:
2747 case wParam of
2748 IK_HOME, IK_KPHOME:
2749 begin
2750 FIndex := 0;
2751 FStartLine := 0;
2752 if @FOnChangeEvent <> nil then
2753 FOnChangeEvent(Self);
2754 end;
2756 IK_END, IK_KPEND:
2757 begin
2758 FIndex := High(FItems);
2759 FStartLine := Max(High(FItems)-FHeight+1, 0);
2760 if @FOnChangeEvent <> nil then
2761 FOnChangeEvent(Self);
2762 end;
2764 IK_PAGEUP, IK_KPPAGEUP:
2765 begin
2766 if FIndex > FHeight then
2767 FIndex := FIndex-FHeight
2768 else
2769 FIndex := 0;
2771 if FStartLine > FHeight then
2772 FStartLine := FStartLine-FHeight
2773 else
2774 FStartLine := 0;
2775 end;
2777 IK_PAGEDN, IK_KPPAGEDN:
2778 begin
2779 if FIndex < High(FItems)-FHeight then
2780 FIndex := FIndex+FHeight
2781 else
2782 FIndex := High(FItems);
2784 if FStartLine < High(FItems)-FHeight then
2785 FStartLine := FStartLine+FHeight
2786 else
2787 FStartLine := High(FItems)-FHeight+1;
2788 end;
2790 IK_UP, IK_LEFT, IK_KPUP, IK_KPLEFT:
2791 if FIndex > 0 then
2792 begin
2793 Dec(FIndex);
2794 if FIndex < FStartLine then
2795 Dec(FStartLine);
2796 if @FOnChangeEvent <> nil then
2797 FOnChangeEvent(Self);
2798 end;
2800 IK_DOWN, IK_RIGHT, IK_KPDOWN, IK_KPRIGHT:
2801 if FIndex < High(FItems) then
2802 begin
2803 Inc(FIndex);
2804 if FIndex > FStartLine+FHeight-1 then
2805 Inc(FStartLine);
2806 if @FOnChangeEvent <> nil then
2807 FOnChangeEvent(Self);
2808 end;
2810 IK_RETURN, IK_KPRETURN:
2811 with FWindow do
2812 begin
2813 if FActiveControl <> Self then
2814 SetActive(Self)
2815 else
2816 begin
2817 if FItems[FIndex][1] = #29 then // Ïàïêà
2818 begin
2819 OpenDir(FPath+Copy(FItems[FIndex], 2, 255));
2820 FIndex := 0;
2821 Exit;
2822 end;
2824 if FDefControl <> '' then
2825 SetActive(GetControl(FDefControl))
2826 else
2827 SetActive(nil);
2828 end;
2829 end;
2830 end;
2832 WM_CHAR:
2833 for a := 0 to High(FItems) do
2834 if ( (Length(FItems[a]) > 0) and
2835 (LowerCase(FItems[a][1]) = LowerCase(Chr(wParam))) ) or
2836 ( (Length(FItems[a]) > 1) and
2837 (FItems[a][1] = #29) and // Ïàïêà
2838 (LowerCase(FItems[a][2]) = LowerCase(Chr(wParam))) ) then
2839 begin
2840 FIndex := a;
2841 FStartLine := Min(Max(FIndex-1, 0), Length(FItems)-FHeight);
2842 if @FOnChangeEvent <> nil then
2843 FOnChangeEvent(Self);
2844 Break;
2845 end;
2846 end;
2847 end;
2849 procedure TGUIFileListBox.OpenDir(path: String);
2850 var
2851 SR: TSearchRec;
2852 i: Integer;
2853 sm, sc: string;
2854 begin
2855 Clear();
2857 path := IncludeTrailingPathDelimiter(path);
2858 path := ExpandFileName(path);
2860 // Êàòàëîãè:
2861 if FDirs then
2862 begin
2863 if FindFirst(path+'*', faDirectory, SR) = 0 then
2864 repeat
2865 if not LongBool(SR.Attr and faDirectory) then
2866 Continue;
2867 if (SR.Name = '.') or
2868 ((SR.Name = '..') and (path = ExpandFileName(FBasePath))) then
2869 Continue;
2871 AddItem(#1 + SR.Name);
2872 until FindNext(SR) <> 0;
2874 FindClose(SR);
2875 end;
2877 // Ôàéëû:
2878 sm := FFileMask;
2879 while sm <> '' do
2880 begin
2881 i := Pos('|', sm);
2882 if i = 0 then i := length(sm)+1;
2883 sc := Copy(sm, 1, i-1);
2884 Delete(sm, 1, i);
2885 if FindFirst(path+sc, faAnyFile, SR) = 0 then repeat AddItem(SR.Name); until FindNext(SR) <> 0;
2886 FindClose(SR);
2887 end;
2889 for i := 0 to High(FItems) do
2890 if FItems[i][1] = #1 then
2891 FItems[i][1] := #29;
2893 FPath := path;
2894 end;
2896 procedure TGUIFileListBox.SetBase(path: String);
2897 begin
2898 FBasePath := path;
2899 OpenDir(FBasePath);
2900 end;
2902 function TGUIFileListBox.SelectedItem(): String;
2903 begin
2904 Result := '';
2906 if (FIndex = -1) or (FItems = nil) or
2907 (FIndex > High(FItems)) or
2908 (FItems[FIndex][1] = '/') or
2909 (FItems[FIndex][1] = '\') then
2910 Exit;
2912 Result := FPath + FItems[FIndex];
2913 end;
2915 procedure TGUIFileListBox.UpdateFileList();
2916 var
2917 fn: String;
2918 begin
2919 if (FIndex = -1) or (FItems = nil) or
2920 (FIndex > High(FItems)) or
2921 (FItems[FIndex][1] = '/') or
2922 (FItems[FIndex][1] = '\') then
2923 fn := ''
2924 else
2925 fn := FItems[FIndex];
2927 OpenDir(FPath);
2929 if fn <> '' then
2930 SelectItem(fn);
2931 end;
2933 { TGUIMemo }
2935 procedure TGUIMemo.Clear;
2936 begin
2937 FLines := nil;
2938 FStartLine := 0;
2939 end;
2941 constructor TGUIMemo.Create(FontID: DWORD; Width, Height: Word);
2942 begin
2943 inherited Create();
2945 FFont := TFont.Create(FontID, FONT_CHAR);
2947 FWidth := Width;
2948 FHeight := Height;
2949 FDrawBack := True;
2950 FDrawScroll := True;
2951 end;
2953 procedure TGUIMemo.Draw;
2954 var
2955 a: Integer;
2956 begin
2957 inherited;
2959 if FDrawBack then DrawBox(FX, FY, FWidth+1, FHeight);
2960 if FDrawScroll then
2961 DrawScroll(FX+4+FWidth*16, FY+4, FHeight, (FStartLine > 0) and (FLines <> nil),
2962 (FStartLine+FHeight-1 < High(FLines)) and (FLines <> nil));
2964 if FLines <> nil then
2965 for a := FStartLine to Min(High(FLines), FStartLine+FHeight-1) do
2966 FFont.Draw(FX+4, FY+4+(a-FStartLine)*16, FLines[a], FColor.R, FColor.G, FColor.B);
2967 end;
2969 function TGUIMemo.GetHeight: Word;
2970 begin
2971 Result := 8+FHeight*16;
2972 end;
2974 function TGUIMemo.GetWidth: Word;
2975 begin
2976 Result := 8+(FWidth+1)*16;
2977 end;
2979 procedure TGUIMemo.OnMessage(var Msg: TMessage);
2980 begin
2981 if not FEnabled then Exit;
2983 inherited;
2985 if FLines = nil then Exit;
2987 with Msg do
2988 case Msg of
2989 WM_KEYDOWN:
2990 case wParam of
2991 IK_UP, IK_LEFT, IK_KPUP, IK_KPLEFT:
2992 if FStartLine > 0 then
2993 Dec(FStartLine);
2994 IK_DOWN, IK_RIGHT, IK_KPDOWN, IK_KPRIGHT:
2995 if FStartLine < Length(FLines)-FHeight then
2996 Inc(FStartLine);
2997 IK_RETURN, IK_KPRETURN:
2998 with FWindow do
2999 begin
3000 if FActiveControl <> Self then
3001 begin
3002 SetActive(Self);
3003 {FStartLine := 0;}
3004 end
3005 else
3006 if FDefControl <> '' then SetActive(GetControl(FDefControl))
3007 else SetActive(nil);
3008 end;
3009 end;
3010 end;
3011 end;
3013 procedure TGUIMemo.SetText(Text: string);
3014 begin
3015 FStartLine := 0;
3016 FLines := GetLines(Text, FFont.ID, FWidth*16);
3017 end;
3019 { TGUIimage }
3021 procedure TGUIimage.ClearImage();
3022 begin
3023 if FImageRes = '' then Exit;
3025 g_Texture_Delete(FImageRes);
3026 FImageRes := '';
3027 end;
3029 constructor TGUIimage.Create();
3030 begin
3031 inherited Create();
3033 FImageRes := '';
3034 end;
3036 destructor TGUIimage.Destroy();
3037 begin
3038 inherited;
3039 end;
3041 procedure TGUIimage.Draw();
3042 var
3043 ID: DWORD;
3044 begin
3045 inherited;
3047 if FImageRes = '' then
3048 begin
3049 if g_Texture_Get(FDefaultRes, ID) then e_Draw(ID, FX, FY, 0, True, False);
3050 end
3051 else
3052 if g_Texture_Get(FImageRes, ID) then e_Draw(ID, FX, FY, 0, True, False);
3053 end;
3055 procedure TGUIimage.OnMessage(var Msg: TMessage);
3056 begin
3057 inherited;
3058 end;
3060 procedure TGUIimage.SetImage(Res: string);
3061 begin
3062 ClearImage();
3064 if g_Texture_CreateWADEx(Res, Res) then FImageRes := Res;
3065 end;
3067 procedure TGUIimage.Update();
3068 begin
3069 inherited;
3070 end;
3072 end.