DEADSOFTWARE

GUI: "right align" hack; less empty space in "keybind2"
[d2df-sdl.git] / src / game / g_gui.pas
1 (* Copyright (C) DooM 2D:Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *)
16 {$MODE DELPHI}
17 unit g_gui;
19 interface
21 uses
22 e_graphics, e_input, e_log, g_playermodel, g_basic, MAPSTRUCT, wadreader;
24 const
25 MAINMENU_HEADER_COLOR: TRGB = (R:255; G:255; B:255);
26 MAINMENU_ITEMS_COLOR: TRGB = (R:255; G:255; B:255);
27 MAINMENU_UNACTIVEITEMS_COLOR: TRGB = (R:192; G:192; B:192);
28 MAINMENU_CLICKSOUND = 'MENU_SELECT';
29 MAINMENU_CHANGESOUND = 'MENU_CHANGE';
30 MAINMENU_SPACE = 4;
31 MAINMENU_MARKER1 = 'MAINMENU_MARKER1';
32 MAINMENU_MARKER2 = 'MAINMENU_MARKER2';
33 MAINMENU_MARKERDELAY = 24;
34 WINDOW_CLOSESOUND = 'MENU_CLOSE';
35 MENU_HEADERCOLOR: TRGB = (R:255; G:255; B:255);
36 MENU_ITEMSTEXT_COLOR: TRGB = (R:255; G:255; B:255);
37 MENU_UNACTIVEITEMS_COLOR: TRGB = (R:128; G:128; B:128);
38 MENU_ITEMSCTRL_COLOR: TRGB = (R:255; G:0; B:0);
39 MENU_VSPACE = 2;
40 MENU_HSPACE = 32;
41 MENU_CLICKSOUND = 'MENU_SELECT';
42 MENU_CHANGESOUND = 'MENU_CHANGE';
43 MENU_MARKERDELAY = 24;
44 SCROLL_LEFT = 'SCROLL_LEFT';
45 SCROLL_RIGHT = 'SCROLL_RIGHT';
46 SCROLL_MIDDLE = 'SCROLL_MIDDLE';
47 SCROLL_MARKER = 'SCROLL_MARKER';
48 SCROLL_ADDSOUND = 'SCROLL_ADD';
49 SCROLL_SUBSOUND = 'SCROLL_SUB';
50 EDIT_LEFT = 'EDIT_LEFT';
51 EDIT_RIGHT = 'EDIT_RIGHT';
52 EDIT_MIDDLE = 'EDIT_MIDDLE';
53 EDIT_CURSORCOLOR: TRGB = (R:200; G:0; B:0);
54 EDIT_CURSORLEN = 10;
55 KEYREAD_QUERY = '<...>';
56 KEYREAD_CLEAR = '???';
57 KEYREAD_TIMEOUT = 24;
58 MAPPREVIEW_WIDTH = 8;
59 MAPPREVIEW_HEIGHT = 8;
60 BOX1 = 'BOX1';
61 BOX2 = 'BOX2';
62 BOX3 = 'BOX3';
63 BOX4 = 'BOX4';
64 BOX5 = 'BOX5';
65 BOX6 = 'BOX6';
66 BOX7 = 'BOX7';
67 BOX8 = 'BOX8';
68 BOX9 = 'BOX9';
69 BSCROLL_UPA = 'BSCROLL_UP_A';
70 BSCROLL_UPU = 'BSCROLL_UP_U';
71 BSCROLL_DOWNA = 'BSCROLL_DOWN_A';
72 BSCROLL_DOWNU = 'BSCROLL_DOWN_U';
73 BSCROLL_MIDDLE = 'BSCROLL_MIDDLE';
74 WM_KEYDOWN = 101;
75 WM_CHAR = 102;
76 WM_USER = 110;
78 type
79 TMessage = record
80 Msg: DWORD;
81 wParam: LongInt;
82 lParam: LongInt;
83 end;
85 TFontType = (FONT_TEXTURE, FONT_CHAR);
87 TFont = class(TObject)
88 private
89 ID: DWORD;
90 FScale: Single;
91 FFontType: TFontType;
92 public
93 constructor Create(FontID: DWORD; FontType: TFontType);
94 destructor Destroy; override;
95 procedure Draw(X, Y: Integer; Text: string; R, G, B: Byte);
96 procedure GetTextSize(Text: string; var w, h: Word);
97 property Scale: Single read FScale write FScale;
98 end;
100 TGUIControl = class;
101 TGUIWindow = class;
103 TOnKeyDownEvent = procedure(Key: Byte);
104 TOnKeyDownEventEx = procedure(win: TGUIWindow; Key: Byte);
105 TOnCloseEvent = procedure;
106 TOnShowEvent = procedure;
107 TOnClickEvent = procedure;
108 TOnChangeEvent = procedure(Sender: TGUIControl);
109 TOnEnterEvent = procedure(Sender: TGUIControl);
111 TGUIControl = class
112 private
113 FX, FY: Integer;
114 FEnabled: Boolean;
115 FWindow : TGUIWindow;
116 FName: string;
117 FUserData: Pointer;
118 FRightAlign: Boolean; //HACK! this works only for "normal" menus, only for menu text labels, and generally sux. sorry.
119 FMaxWidth: Integer; //HACK! used for right-aligning labels
120 public
121 constructor Create;
122 procedure OnMessage(var Msg: TMessage); virtual;
123 procedure Update; virtual;
124 procedure Draw; virtual;
125 function GetWidth(): Integer; virtual;
126 function GetHeight(): Integer; virtual;
127 function WantActivationKey (key: LongInt): Boolean; virtual;
128 property X: Integer read FX write FX;
129 property Y: Integer read FY write FY;
130 property Enabled: Boolean read FEnabled write FEnabled;
131 property Name: string read FName write FName;
132 property UserData: Pointer read FUserData write FUserData;
133 property RightAlign: Boolean read FRightAlign write FRightAlign; // for menu
134 end;
136 TGUIWindow = class
137 private
138 FActiveControl: TGUIControl;
139 FDefControl: string;
140 FPrevWindow: TGUIWindow;
141 FName: string;
142 FBackTexture: string;
143 FMainWindow: Boolean;
144 FOnKeyDown: TOnKeyDownEvent;
145 FOnKeyDownEx: TOnKeyDownEventEx;
146 FOnCloseEvent: TOnCloseEvent;
147 FOnShowEvent: TOnShowEvent;
148 FUserData: Pointer;
149 public
150 Childs: array of TGUIControl;
151 constructor Create(Name: string);
152 destructor Destroy; override;
153 function AddChild(Child: TGUIControl): TGUIControl;
154 procedure OnMessage(var Msg: TMessage);
155 procedure Update;
156 procedure Draw;
157 procedure SetActive(Control: TGUIControl);
158 function GetControl(Name: string): TGUIControl;
159 property OnKeyDown: TOnKeyDownEvent read FOnKeyDown write FOnKeyDown;
160 property OnKeyDownEx: TOnKeyDownEventEx read FOnKeyDownEx write FOnKeyDownEx;
161 property OnClose: TOnCloseEvent read FOnCloseEvent write FOnCloseEvent;
162 property OnShow: TOnShowEvent read FOnShowEvent write FOnShowEvent;
163 property Name: string read FName;
164 property DefControl: string read FDefControl write FDefControl;
165 property BackTexture: string read FBackTexture write FBackTexture;
166 property MainWindow: Boolean read FMainWindow write FMainWindow;
167 property UserData: Pointer read FUserData write FUserData;
168 end;
170 TGUITextButton = class(TGUIControl)
171 private
172 FText: string;
173 FColor: TRGB;
174 FFont: TFont;
175 FSound: string;
176 FShowWindow: string;
177 public
178 Proc: procedure;
179 ProcEx: procedure (sender: TGUITextButton);
180 constructor Create(Proc: Pointer; FontID: DWORD; Text: string);
181 destructor Destroy(); override;
182 procedure OnMessage(var Msg: TMessage); override;
183 procedure Update(); override;
184 procedure Draw(); override;
185 function GetWidth(): Integer; override;
186 function GetHeight(): Integer; override;
187 procedure Click(Silent: Boolean = False);
188 property Caption: string read FText write FText;
189 property Color: TRGB read FColor write FColor;
190 property Font: TFont read FFont write FFont;
191 property ShowWindow: string read FShowWindow write FShowWindow;
192 end;
194 TGUILabel = class(TGUIControl)
195 private
196 FText: string;
197 FColor: TRGB;
198 FFont: TFont;
199 FFixedLen: Word;
200 FOnClickEvent: TOnClickEvent;
201 public
202 constructor Create(Text: string; FontID: DWORD);
203 procedure OnMessage(var Msg: TMessage); override;
204 procedure Draw; override;
205 function GetWidth: Integer; override;
206 function GetHeight: Integer; override;
207 property OnClick: TOnClickEvent read FOnClickEvent write FOnClickEvent;
208 property FixedLength: Word read FFixedLen write FFixedLen;
209 property Text: string read FText write FText;
210 property Color: TRGB read FColor write FColor;
211 property Font: TFont read FFont write FFont;
212 end;
214 TGUIScroll = class(TGUIControl)
215 private
216 FValue: Integer;
217 FMax: Word;
218 FLeftID: DWORD;
219 FRightID: DWORD;
220 FMiddleID: DWORD;
221 FMarkerID: DWORD;
222 FOnChangeEvent: TOnChangeEvent;
223 procedure FSetValue(a: Integer);
224 public
225 constructor Create();
226 procedure OnMessage(var Msg: TMessage); override;
227 procedure Update; override;
228 procedure Draw; override;
229 function GetWidth(): Integer; override;
230 property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent;
231 property Max: Word read FMax write FMax;
232 property Value: Integer read FValue write FSetValue;
233 end;
235 TGUISwitch = class(TGUIControl)
236 private
237 FFont: TFont;
238 FItems: array of string;
239 FIndex: Integer;
240 FColor: TRGB;
241 FOnChangeEvent: TOnChangeEvent;
242 public
243 constructor Create(FontID: DWORD);
244 procedure OnMessage(var Msg: TMessage); override;
245 procedure AddItem(Item: string);
246 procedure Update; override;
247 procedure Draw; override;
248 function GetWidth(): Integer; override;
249 function GetText: string;
250 property ItemIndex: Integer read FIndex write FIndex;
251 property Color: TRGB read FColor write FColor;
252 property Font: TFont read FFont write FFont;
253 property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent;
254 end;
256 TGUIEdit = class(TGUIControl)
257 private
258 FFont: TFont;
259 FCaretPos: Integer;
260 FMaxLength: Word;
261 FWidth: Word;
262 FText: string;
263 FColor: TRGB;
264 FOnlyDigits: Boolean;
265 FLeftID: DWORD;
266 FRightID: DWORD;
267 FMiddleID: DWORD;
268 FOnChangeEvent: TOnChangeEvent;
269 FOnEnterEvent: TOnEnterEvent;
270 procedure SetText(Text: string);
271 public
272 constructor Create(FontID: DWORD);
273 procedure OnMessage(var Msg: TMessage); override;
274 procedure Update; override;
275 procedure Draw; override;
276 function GetWidth(): Integer; override;
277 property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent;
278 property OnEnter: TOnEnterEvent read FOnEnterEvent write FOnEnterEvent;
279 property Width: Word read FWidth write FWidth;
280 property MaxLength: Word read FMaxLength write FMaxLength;
281 property OnlyDigits: Boolean read FOnlyDigits write FOnlyDigits;
282 property Text: string read FText write SetText;
283 property Color: TRGB read FColor write FColor;
284 property Font: TFont read FFont write FFont;
285 end;
287 TGUIKeyRead = class(TGUIControl)
288 private
289 FFont: TFont;
290 FColor: TRGB;
291 FKey: Word;
292 FIsQuery: Boolean;
293 public
294 constructor Create(FontID: DWORD);
295 procedure OnMessage(var Msg: TMessage); override;
296 procedure Draw; override;
297 function GetWidth(): Integer; override;
298 function WantActivationKey (key: LongInt): Boolean; override;
299 property Key: Word read FKey write FKey;
300 property Color: TRGB read FColor write FColor;
301 property Font: TFont read FFont write FFont;
302 end;
304 // can hold two keys
305 TGUIKeyRead2 = class(TGUIControl)
306 private
307 FFont: TFont;
308 FFontID: DWORD;
309 FColor: TRGB;
310 FKey0, FKey1: Word; // this should be an array. sorry.
311 FKeyIdx: Integer;
312 FIsQuery: Boolean;
313 FMaxKeyNameWdt: Integer;
314 public
315 constructor Create(FontID: DWORD);
316 procedure OnMessage(var Msg: TMessage); override;
317 procedure Draw; override;
318 function GetWidth(): Integer; override;
319 function WantActivationKey (key: LongInt): Boolean; override;
320 property Key0: Word read FKey0 write FKey0;
321 property Key1: Word read FKey1 write FKey1;
322 property Color: TRGB read FColor write FColor;
323 property Font: TFont read FFont write FFont;
324 end;
326 TGUIModelView = class(TGUIControl)
327 private
328 FModel: TPlayerModel;
329 a: Boolean;
330 public
331 constructor Create;
332 destructor Destroy; override;
333 procedure OnMessage(var Msg: TMessage); override;
334 procedure SetModel(ModelName: string);
335 procedure SetColor(Red, Green, Blue: Byte);
336 procedure NextAnim();
337 procedure NextWeapon();
338 procedure Update; override;
339 procedure Draw; override;
340 property Model: TPlayerModel read FModel;
341 end;
343 TPreviewPanel = record
344 X1, Y1, X2, Y2: Integer;
345 PanelType: Word;
346 end;
348 TGUIMapPreview = class(TGUIControl)
349 private
350 FMapData: array of TPreviewPanel;
351 FMapSize: TPoint;
352 FScale: Single;
353 public
354 constructor Create();
355 destructor Destroy(); override;
356 procedure OnMessage(var Msg: TMessage); override;
357 procedure SetMap(Res: string);
358 procedure ClearMap();
359 procedure Update(); override;
360 procedure Draw(); override;
361 function GetScaleStr: String;
362 end;
364 TGUIImage = class(TGUIControl)
365 private
366 FImageRes: string;
367 FDefaultRes: string;
368 public
369 constructor Create();
370 destructor Destroy(); override;
371 procedure OnMessage(var Msg: TMessage); override;
372 procedure SetImage(Res: string);
373 procedure ClearImage();
374 procedure Update(); override;
375 procedure Draw(); override;
376 property DefaultRes: string read FDefaultRes write FDefaultRes;
377 end;
379 TGUIListBox = class(TGUIControl)
380 private
381 FItems: SArray;
382 FActiveColor: TRGB;
383 FUnActiveColor: TRGB;
384 FFont: TFont;
385 FStartLine: Integer;
386 FIndex: Integer;
387 FWidth: Word;
388 FHeight: Word;
389 FSort: Boolean;
390 FDrawBack: Boolean;
391 FDrawScroll: Boolean;
392 FOnChangeEvent: TOnChangeEvent;
394 procedure FSetItems(Items: SArray);
395 procedure FSetIndex(aIndex: Integer);
397 public
398 constructor Create(FontID: DWORD; Width, Height: Word);
399 procedure OnMessage(var Msg: TMessage); override;
400 procedure Draw(); override;
401 procedure AddItem(Item: String);
402 procedure SelectItem(Item: String);
403 procedure Clear();
404 function GetWidth(): Integer; override;
405 function GetHeight(): Integer; override;
406 function SelectedItem(): String;
408 property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent;
409 property Sort: Boolean read FSort write FSort;
410 property ItemIndex: Integer read FIndex write FSetIndex;
411 property Items: SArray read FItems write FSetItems;
412 property DrawBack: Boolean read FDrawBack write FDrawBack;
413 property DrawScrollBar: Boolean read FDrawScroll write FDrawScroll;
414 property ActiveColor: TRGB read FActiveColor write FActiveColor;
415 property UnActiveColor: TRGB read FUnActiveColor write FUnActiveColor;
416 property Font: TFont read FFont write FFont;
417 end;
419 TGUIFileListBox = class (TGUIListBox)
420 private
421 FBasePath: String;
422 FPath: String;
423 FFileMask: String;
424 FDirs: Boolean;
426 procedure OpenDir(path: String);
428 public
429 procedure OnMessage(var Msg: TMessage); override;
430 procedure SetBase(path: String);
431 function SelectedItem(): String;
432 procedure UpdateFileList();
434 property Dirs: Boolean read FDirs write FDirs;
435 property FileMask: String read FFileMask write FFileMask;
436 property Path: String read FPath;
437 end;
439 TGUIMemo = class(TGUIControl)
440 private
441 FLines: SArray;
442 FFont: TFont;
443 FStartLine: Integer;
444 FWidth: Word;
445 FHeight: Word;
446 FColor: TRGB;
447 FDrawBack: Boolean;
448 FDrawScroll: Boolean;
449 public
450 constructor Create(FontID: DWORD; Width, Height: Word);
451 procedure OnMessage(var Msg: TMessage); override;
452 procedure Draw; override;
453 procedure Clear;
454 function GetWidth(): Integer; override;
455 function GetHeight(): Integer; override;
456 procedure SetText(Text: string);
457 property DrawBack: Boolean read FDrawBack write FDrawBack;
458 property DrawScrollBar: Boolean read FDrawScroll write FDrawScroll;
459 property Color: TRGB read FColor write FColor;
460 property Font: TFont read FFont write FFont;
461 end;
463 TGUIMainMenu = class(TGUIControl)
464 private
465 FButtons: array of TGUITextButton;
466 FHeader: TGUILabel;
467 FIndex: Integer;
468 FFontID: DWORD;
469 FCounter: Byte;
470 FMarkerID1: DWORD;
471 FMarkerID2: DWORD;
472 public
473 constructor Create(FontID: DWORD; Header: string);
474 destructor Destroy; override;
475 procedure OnMessage(var Msg: TMessage); override;
476 function AddButton(fProc: Pointer; Caption: string; ShowWindow: string = ''): TGUITextButton;
477 function GetButton(Name: string): TGUITextButton;
478 procedure EnableButton(Name: string; e: Boolean);
479 procedure AddSpace();
480 procedure Update; override;
481 procedure Draw; override;
482 end;
484 TControlType = class of TGUIControl;
486 PMenuItem = ^TMenuItem;
487 TMenuItem = record
488 Text: TGUILabel;
489 ControlType: TControlType;
490 Control: TGUIControl;
491 end;
493 TGUIMenu = class(TGUIControl)
494 private
495 FItems: array of TMenuItem;
496 FHeader: TGUILabel;
497 FIndex: Integer;
498 FFontID: DWORD;
499 FCounter: Byte;
500 FAlign: Boolean;
501 FLeft: Integer;
502 FYesNo: Boolean;
503 function NewItem(): Integer;
504 public
505 constructor Create(HeaderFont, ItemsFont: DWORD; Header: string);
506 destructor Destroy; override;
507 procedure OnMessage(var Msg: TMessage); override;
508 procedure AddSpace();
509 procedure AddLine(fText: string);
510 procedure AddText(fText: string; MaxWidth: Word);
511 function AddLabel(fText: string): TGUILabel;
512 function AddButton(Proc: Pointer; fText: string; _ShowWindow: string = ''): TGUITextButton;
513 function AddScroll(fText: string): TGUIScroll;
514 function AddSwitch(fText: string): TGUISwitch;
515 function AddEdit(fText: string): TGUIEdit;
516 function AddKeyRead(fText: string): TGUIKeyRead;
517 function AddKeyRead2(fText: string): TGUIKeyRead2;
518 function AddList(fText: string; Width, Height: Word): TGUIListBox;
519 function AddFileList(fText: string; Width, Height: Word): TGUIFileListBox;
520 function AddMemo(fText: string; Width, Height: Word): TGUIMemo;
521 procedure ReAlign();
522 function GetControl(Name: string): TGUIControl;
523 function GetControlsText(Name: string): TGUILabel;
524 procedure Draw; override;
525 procedure Update; override;
526 procedure UpdateIndex();
527 property Align: Boolean read FAlign write FAlign;
528 property Left: Integer read FLeft write FLeft;
529 property YesNo: Boolean read FYesNo write FYesNo;
530 end;
532 var
533 g_GUIWindows: array of TGUIWindow;
534 g_ActiveWindow: TGUIWindow = nil;
536 procedure g_GUI_Init();
537 function g_GUI_AddWindow(Window: TGUIWindow): TGUIWindow;
538 function g_GUI_GetWindow(Name: string): TGUIWindow;
539 procedure g_GUI_ShowWindow(Name: string);
540 procedure g_GUI_HideWindow(PlaySound: Boolean = True);
541 function g_GUI_Destroy(): Boolean;
542 procedure g_GUI_SaveMenuPos();
543 procedure g_GUI_LoadMenuPos();
545 implementation
547 uses
548 GL, GLExt, g_textures, g_sound, SysUtils,
549 g_game, Math, StrUtils, g_player, g_options, MAPREADER,
550 g_map, MAPDEF, g_weapons;
552 var
553 Box: Array [0..8] of DWORD;
554 Saved_Windows: SArray;
556 procedure g_GUI_Init();
557 begin
558 g_Texture_Get(BOX1, Box[0]);
559 g_Texture_Get(BOX2, Box[1]);
560 g_Texture_Get(BOX3, Box[2]);
561 g_Texture_Get(BOX4, Box[3]);
562 g_Texture_Get(BOX5, Box[4]);
563 g_Texture_Get(BOX6, Box[5]);
564 g_Texture_Get(BOX7, Box[6]);
565 g_Texture_Get(BOX8, Box[7]);
566 g_Texture_Get(BOX9, Box[8]);
567 end;
569 function g_GUI_Destroy(): Boolean;
570 var
571 i: Integer;
572 begin
573 Result := (Length(g_GUIWindows) > 0);
575 for i := 0 to High(g_GUIWindows) do
576 g_GUIWindows[i].Free();
578 g_GUIWindows := nil;
579 g_ActiveWindow := nil;
580 end;
582 function g_GUI_AddWindow(Window: TGUIWindow): TGUIWindow;
583 begin
584 SetLength(g_GUIWindows, Length(g_GUIWindows)+1);
585 g_GUIWindows[High(g_GUIWindows)] := Window;
587 Result := Window;
588 end;
590 function g_GUI_GetWindow(Name: string): TGUIWindow;
591 var
592 i: Integer;
593 begin
594 Result := nil;
596 if g_GUIWindows <> nil then
597 for i := 0 to High(g_GUIWindows) do
598 if g_GUIWindows[i].FName = Name then
599 begin
600 Result := g_GUIWindows[i];
601 Break;
602 end;
604 Assert(Result <> nil, 'GUI_Window "'+Name+'" not found');
605 end;
607 procedure g_GUI_ShowWindow(Name: string);
608 var
609 i: Integer;
610 begin
611 if g_GUIWindows = nil then
612 Exit;
614 for i := 0 to High(g_GUIWindows) do
615 if g_GUIWindows[i].FName = Name then
616 begin
617 g_GUIWindows[i].FPrevWindow := g_ActiveWindow;
618 g_ActiveWindow := g_GUIWindows[i];
620 if g_ActiveWindow.MainWindow then
621 g_ActiveWindow.FPrevWindow := nil;
623 if g_ActiveWindow.FDefControl <> '' then
624 g_ActiveWindow.SetActive(g_ActiveWindow.GetControl(g_ActiveWindow.FDefControl))
625 else
626 g_ActiveWindow.SetActive(nil);
628 if @g_ActiveWindow.FOnShowEvent <> nil then
629 g_ActiveWindow.FOnShowEvent();
631 Break;
632 end;
633 end;
635 procedure g_GUI_HideWindow(PlaySound: Boolean = True);
636 begin
637 if g_ActiveWindow <> nil then
638 begin
639 if @g_ActiveWindow.OnClose <> nil then
640 g_ActiveWindow.OnClose();
641 g_ActiveWindow := g_ActiveWindow.FPrevWindow;
642 if PlaySound then
643 g_Sound_PlayEx(WINDOW_CLOSESOUND);
644 end;
645 end;
647 procedure g_GUI_SaveMenuPos();
648 var
649 len: Integer;
650 win: TGUIWindow;
651 begin
652 SetLength(Saved_Windows, 0);
653 win := g_ActiveWindow;
655 while win <> nil do
656 begin
657 len := Length(Saved_Windows);
658 SetLength(Saved_Windows, len + 1);
660 Saved_Windows[len] := win.Name;
662 if win.MainWindow then
663 win := nil
664 else
665 win := win.FPrevWindow;
666 end;
667 end;
669 procedure g_GUI_LoadMenuPos();
670 var
671 i, j, k, len: Integer;
672 ok: Boolean;
673 begin
674 g_ActiveWindow := nil;
675 len := Length(Saved_Windows);
677 if len = 0 then
678 Exit;
680 // Îêíî ñ ãëàâíûì ìåíþ:
681 g_GUI_ShowWindow(Saved_Windows[len-1]);
683 // Íå ïåðåêëþ÷èëîñü (èëè íåêóäà äàëüøå):
684 if (len = 1) or (g_ActiveWindow = nil) then
685 Exit;
687 // Èùåì êíîïêè â îñòàëüíûõ îêíàõ:
688 for k := len-1 downto 1 do
689 begin
690 ok := False;
692 for i := 0 to Length(g_ActiveWindow.Childs)-1 do
693 begin
694 if g_ActiveWindow.Childs[i] is TGUIMainMenu then
695 begin // GUI_MainMenu
696 with TGUIMainMenu(g_ActiveWindow.Childs[i]) do
697 for j := 0 to Length(FButtons)-1 do
698 if FButtons[j].ShowWindow = Saved_Windows[k-1] then
699 begin
700 FButtons[j].Click(True);
701 ok := True;
702 Break;
703 end;
704 end
705 else // GUI_Menu
706 if g_ActiveWindow.Childs[i] is TGUIMenu then
707 with TGUIMenu(g_ActiveWindow.Childs[i]) do
708 for j := 0 to Length(FItems)-1 do
709 if FItems[j].ControlType = TGUITextButton then
710 if TGUITextButton(FItems[j].Control).ShowWindow = Saved_Windows[k-1] then
711 begin
712 TGUITextButton(FItems[j].Control).Click(True);
713 ok := True;
714 Break;
715 end;
717 if ok then
718 Break;
719 end;
721 // Íå ïåðåêëþ÷èëîñü:
722 if (not ok) or
723 (g_ActiveWindow.Name = Saved_Windows[k]) then
724 Break;
725 end;
726 end;
728 procedure DrawBox(X, Y: Integer; Width, Height: Word);
729 begin
730 e_Draw(Box[0], X, Y, 0, False, False);
731 e_DrawFill(Box[1], X+4, Y, Width*4, 1, 0, False, False);
732 e_Draw(Box[2], X+4+Width*16, Y, 0, False, False);
733 e_DrawFill(Box[3], X, Y+4, 1, Height*4, 0, False, False);
734 e_DrawFill(Box[4], X+4, Y+4, Width, Height, 0, False, False);
735 e_DrawFill(Box[5], X+4+Width*16, Y+4, 1, Height*4, 0, False, False);
736 e_Draw(Box[6], X, Y+4+Height*16, 0, False, False);
737 e_DrawFill(Box[7], X+4, Y+4+Height*16, Width*4, 1, 0, False, False);
738 e_Draw(Box[8], X+4+Width*16, Y+4+Height*16, 0, False, False);
739 end;
741 procedure DrawScroll(X, Y: Integer; Height: Word; Up, Down: Boolean);
742 var
743 ID: DWORD;
744 begin
745 if Height < 3 then Exit;
747 if Up then
748 g_Texture_Get(BSCROLL_UPA, ID)
749 else
750 g_Texture_Get(BSCROLL_UPU, ID);
751 e_Draw(ID, X, Y, 0, False, False);
753 if Down then
754 g_Texture_Get(BSCROLL_DOWNA, ID)
755 else
756 g_Texture_Get(BSCROLL_DOWNU, ID);
757 e_Draw(ID, X, Y+(Height-1)*16, 0, False, False);
759 g_Texture_Get(BSCROLL_MIDDLE, ID);
760 e_DrawFill(ID, X, Y+16, 1, Height-2, 0, False, False);
761 end;
763 { TGUIWindow }
765 constructor TGUIWindow.Create(Name: string);
766 begin
767 Childs := nil;
768 FActiveControl := nil;
769 FName := Name;
770 FOnKeyDown := nil;
771 FOnKeyDownEx := nil;
772 FOnCloseEvent := nil;
773 FOnShowEvent := nil;
774 end;
776 destructor TGUIWindow.Destroy;
777 var
778 i: Integer;
779 begin
780 if Childs = nil then
781 Exit;
783 for i := 0 to High(Childs) do
784 Childs[i].Free();
785 end;
787 function TGUIWindow.AddChild(Child: TGUIControl): TGUIControl;
788 begin
789 Child.FWindow := Self;
791 SetLength(Childs, Length(Childs) + 1);
792 Childs[High(Childs)] := Child;
794 Result := Child;
795 end;
797 procedure TGUIWindow.Update;
798 var
799 i: Integer;
800 begin
801 for i := 0 to High(Childs) do
802 if Childs[i] <> nil then Childs[i].Update;
803 end;
805 procedure TGUIWindow.Draw;
806 var
807 i: Integer;
808 ID: DWORD;
809 begin
810 if FBackTexture <> '' then
811 if g_Texture_Get(FBackTexture, ID) then
812 e_DrawSize(ID, 0, 0, 0, False, False, gScreenWidth, gScreenHeight)
813 else
814 e_Clear(GL_COLOR_BUFFER_BIT, 0.5, 0.5, 0.5);
816 for i := 0 to High(Childs) do
817 if Childs[i] <> nil then Childs[i].Draw;
818 end;
820 procedure TGUIWindow.OnMessage(var Msg: TMessage);
821 begin
822 if FActiveControl <> nil then FActiveControl.OnMessage(Msg);
823 if @FOnKeyDown <> nil then FOnKeyDown(Msg.wParam);
824 if @FOnKeyDownEx <> nil then FOnKeyDownEx(self, Msg.wParam);
826 if Msg.Msg = WM_KEYDOWN then
827 if Msg.wParam = IK_ESCAPE then
828 begin
829 g_GUI_HideWindow;
830 Exit;
831 end;
832 end;
834 procedure TGUIWindow.SetActive(Control: TGUIControl);
835 begin
836 FActiveControl := Control;
837 end;
839 function TGUIWindow.GetControl(Name: String): TGUIControl;
840 var
841 i: Integer;
842 begin
843 Result := nil;
845 if Childs <> nil then
846 for i := 0 to High(Childs) do
847 if Childs[i] <> nil then
848 if LowerCase(Childs[i].FName) = LowerCase(Name) then
849 begin
850 Result := Childs[i];
851 Break;
852 end;
854 Assert(Result <> nil, 'Window Control "'+Name+'" not Found!');
855 end;
857 { TGUIControl }
859 constructor TGUIControl.Create();
860 begin
861 FX := 0;
862 FY := 0;
864 FEnabled := True;
865 FRightAlign := false;
866 FMaxWidth := -1;
867 end;
869 procedure TGUIControl.OnMessage(var Msg: TMessage);
870 begin
871 if not FEnabled then
872 Exit;
873 end;
875 procedure TGUIControl.Update();
876 begin
877 end;
879 procedure TGUIControl.Draw();
880 begin
881 end;
883 function TGUIControl.WantActivationKey (key: LongInt): Boolean;
884 begin
885 result := false;
886 end;
888 function TGUIControl.GetWidth(): Integer;
889 begin
890 result := 0;
891 end;
893 function TGUIControl.GetHeight(): Integer;
894 begin
895 result := 0;
896 end;
898 { TGUITextButton }
900 procedure TGUITextButton.Click(Silent: Boolean = False);
901 begin
902 if (FSound <> '') and (not Silent) then g_Sound_PlayEx(FSound);
904 if @Proc <> nil then Proc();
905 if @ProcEx <> nil then ProcEx(self);
907 if FShowWindow <> '' then g_GUI_ShowWindow(FShowWindow);
908 end;
910 constructor TGUITextButton.Create(Proc: Pointer; FontID: DWORD; Text: string);
911 begin
912 inherited Create();
914 Self.Proc := Proc;
915 ProcEx := nil;
917 FFont := TFont.Create(FontID, FONT_CHAR);
919 FText := Text;
920 end;
922 destructor TGUITextButton.Destroy;
923 begin
925 inherited;
926 end;
928 procedure TGUITextButton.Draw;
929 begin
930 FFont.Draw(FX, FY, FText, FColor.R, FColor.G, FColor.B)
931 end;
933 function TGUITextButton.GetHeight: Integer;
934 var
935 w, h: Word;
936 begin
937 FFont.GetTextSize(FText, w, h);
938 Result := h;
939 end;
941 function TGUITextButton.GetWidth: Integer;
942 var
943 w, h: Word;
944 begin
945 FFont.GetTextSize(FText, w, h);
946 Result := w;
947 end;
949 procedure TGUITextButton.OnMessage(var Msg: TMessage);
950 begin
951 if not FEnabled then Exit;
953 inherited;
955 case Msg.Msg of
956 WM_KEYDOWN:
957 case Msg.wParam of
958 IK_RETURN, IK_KPRETURN: Click();
959 end;
960 end;
961 end;
963 procedure TGUITextButton.Update;
964 begin
965 inherited;
966 end;
968 { TFont }
970 constructor TFont.Create(FontID: DWORD; FontType: TFontType);
971 begin
972 ID := FontID;
974 FScale := 1;
975 FFontType := FontType;
976 end;
978 destructor TFont.Destroy;
979 begin
981 inherited;
982 end;
984 procedure TFont.Draw(X, Y: Integer; Text: string; R, G, B: Byte);
985 begin
986 if FFontType = FONT_CHAR then e_CharFont_PrintEx(ID, X, Y, Text, _RGB(R, G, B), FScale)
987 else e_TextureFontPrintEx(X, Y, Text, ID, R, G, B, FScale);
988 end;
990 procedure TFont.GetTextSize(Text: string; var w, h: Word);
991 var
992 cw, ch: Byte;
993 begin
994 if FFontType = FONT_CHAR then e_CharFont_GetSize(ID, Text, w, h)
995 else
996 begin
997 e_TextureFontGetSize(ID, cw, ch);
998 w := cw*Length(Text);
999 h := ch;
1000 end;
1002 w := Round(w*FScale);
1003 h := Round(h*FScale);
1004 end;
1006 { TGUIMainMenu }
1008 function TGUIMainMenu.AddButton(fProc: Pointer; Caption: string; ShowWindow: string = ''): TGUITextButton;
1009 var
1010 a, _x: Integer;
1011 h, hh: Word;
1012 begin
1013 FIndex := 0;
1015 SetLength(FButtons, Length(FButtons)+1);
1016 FButtons[High(FButtons)] := TGUITextButton.Create(fProc, FFontID, Caption);
1017 FButtons[High(FButtons)].ShowWindow := ShowWindow;
1018 with FButtons[High(FButtons)] do
1019 begin
1020 if (fProc <> nil) or (ShowWindow <> '') then FColor := MAINMENU_ITEMS_COLOR
1021 else FColor := MAINMENU_UNACTIVEITEMS_COLOR;
1022 FSound := MAINMENU_CLICKSOUND;
1023 end;
1025 _x := gScreenWidth div 2;
1027 for a := 0 to High(FButtons) do
1028 if FButtons[a] <> nil then
1029 _x := Min(_x, (gScreenWidth div 2)-(FButtons[a].GetWidth div 2));
1031 hh := FHeader.GetHeight;
1033 h := hh*(2+Length(FButtons))+MAINMENU_SPACE*(Length(FButtons)-1);
1034 h := (gScreenHeight div 2)-(h div 2);
1036 with FHeader do
1037 begin
1038 FX := _x;
1039 FY := h;
1040 end;
1042 Inc(h, hh*2);
1044 for a := 0 to High(FButtons) do
1045 begin
1046 if FButtons[a] <> nil then
1047 with FButtons[a] do
1048 begin
1049 FX := _x;
1050 FY := h;
1051 end;
1053 Inc(h, hh+MAINMENU_SPACE);
1054 end;
1056 Result := FButtons[High(FButtons)];
1057 end;
1059 procedure TGUIMainMenu.AddSpace;
1060 begin
1061 SetLength(FButtons, Length(FButtons)+1);
1062 FButtons[High(FButtons)] := nil;
1063 end;
1065 constructor TGUIMainMenu.Create(FontID: DWORD; Header: string);
1066 begin
1067 inherited Create();
1069 FIndex := -1;
1070 FFontID := FontID;
1071 FCounter := MAINMENU_MARKERDELAY;
1073 g_Texture_Get(MAINMENU_MARKER1, FMarkerID1);
1074 g_Texture_Get(MAINMENU_MARKER2, FMarkerID2);
1076 FHeader := TGUILabel.Create(Header, FFontID);
1077 with FHeader do
1078 begin
1079 FColor := MAINMENU_HEADER_COLOR;
1080 FX := (gScreenWidth div 2)-(GetWidth div 2);
1081 FY := (gScreenHeight div 2)-(GetHeight div 2);
1082 end;
1083 end;
1085 destructor TGUIMainMenu.Destroy;
1086 var
1087 a: Integer;
1088 begin
1089 if FButtons <> nil then
1090 for a := 0 to High(FButtons) do
1091 FButtons[a].Free();
1093 FHeader.Free();
1095 inherited;
1096 end;
1098 procedure TGUIMainMenu.Draw;
1099 var
1100 a: Integer;
1101 begin
1102 inherited;
1104 FHeader.Draw;
1106 if FButtons <> nil then
1107 begin
1108 for a := 0 to High(FButtons) do
1109 if FButtons[a] <> nil then FButtons[a].Draw;
1111 if FIndex <> -1 then
1112 e_Draw(FMarkerID1, FButtons[FIndex].FX-48, FButtons[FIndex].FY, 0, True, False);
1113 end;
1114 end;
1116 procedure TGUIMainMenu.EnableButton(Name: string; e: Boolean);
1117 var
1118 a: Integer;
1119 begin
1120 if FButtons = nil then Exit;
1122 for a := 0 to High(FButtons) do
1123 if (FButtons[a] <> nil) and (FButtons[a].Name = Name) then
1124 begin
1125 if e then FButtons[a].FColor := MAINMENU_ITEMS_COLOR
1126 else FButtons[a].FColor := MAINMENU_UNACTIVEITEMS_COLOR;
1127 FButtons[a].Enabled := e;
1128 Break;
1129 end;
1130 end;
1132 function TGUIMainMenu.GetButton(Name: string): TGUITextButton;
1133 var
1134 a: Integer;
1135 begin
1136 Result := nil;
1138 if FButtons = nil then Exit;
1140 for a := 0 to High(FButtons) do
1141 if (FButtons[a] <> nil) and (FButtons[a].Name = Name) then
1142 begin
1143 Result := FButtons[a];
1144 Break;
1145 end;
1146 end;
1148 procedure TGUIMainMenu.OnMessage(var Msg: TMessage);
1149 var
1150 ok: Boolean;
1151 a: Integer;
1152 begin
1153 if not FEnabled then Exit;
1155 inherited;
1157 if FButtons = nil then Exit;
1159 ok := False;
1160 for a := 0 to High(FButtons) do
1161 if FButtons[a] <> nil then
1162 begin
1163 ok := True;
1164 Break;
1165 end;
1167 if not ok then Exit;
1169 case Msg.Msg of
1170 WM_KEYDOWN:
1171 case Msg.wParam of
1172 IK_UP, IK_KPUP:
1173 begin
1174 repeat
1175 Dec(FIndex);
1176 if FIndex < 0 then FIndex := High(FButtons);
1177 until FButtons[FIndex] <> nil;
1179 g_Sound_PlayEx(MENU_CHANGESOUND);
1180 end;
1181 IK_DOWN, IK_KPDOWN:
1182 begin
1183 repeat
1184 Inc(FIndex);
1185 if FIndex > High(FButtons) then FIndex := 0;
1186 until FButtons[FIndex] <> nil;
1188 g_Sound_PlayEx(MENU_CHANGESOUND);
1189 end;
1190 IK_RETURN, IK_KPRETURN: if (FIndex <> -1) and FButtons[FIndex].FEnabled then FButtons[FIndex].Click;
1191 end;
1192 end;
1193 end;
1195 procedure TGUIMainMenu.Update;
1196 var
1197 t: DWORD;
1198 begin
1199 inherited;
1201 if FCounter = 0 then
1202 begin
1203 t := FMarkerID1;
1204 FMarkerID1 := FMarkerID2;
1205 FMarkerID2 := t;
1207 FCounter := MAINMENU_MARKERDELAY;
1208 end else Dec(FCounter);
1209 end;
1211 { TGUILabel }
1213 constructor TGUILabel.Create(Text: string; FontID: DWORD);
1214 begin
1215 inherited Create();
1217 FFont := TFont.Create(FontID, FONT_CHAR);
1219 FText := Text;
1220 FFixedLen := 0;
1221 FOnClickEvent := nil;
1222 end;
1224 procedure TGUILabel.Draw;
1225 var
1226 w, h: Word;
1227 begin
1228 if RightAlign then
1229 begin
1230 FFont.GetTextSize(FText, w, h);
1231 FFont.Draw(FX+FMaxWidth-w, FY, FText, FColor.R, FColor.G, FColor.B);
1232 end
1233 else
1234 begin
1235 FFont.Draw(FX, FY, FText, FColor.R, FColor.G, FColor.B);
1236 end;
1237 end;
1239 function TGUILabel.GetHeight: Integer;
1240 var
1241 w, h: Word;
1242 begin
1243 FFont.GetTextSize(FText, w, h);
1244 Result := h;
1245 end;
1247 function TGUILabel.GetWidth: Integer;
1248 var
1249 w, h: Word;
1250 begin
1251 if FFixedLen = 0 then
1252 FFont.GetTextSize(FText, w, h)
1253 else
1254 w := e_CharFont_GetMaxWidth(FFont.ID)*FFixedLen;
1255 Result := w;
1256 end;
1258 procedure TGUILabel.OnMessage(var Msg: TMessage);
1259 begin
1260 if not FEnabled then Exit;
1262 inherited;
1264 case Msg.Msg of
1265 WM_KEYDOWN:
1266 case Msg.wParam of
1267 IK_RETURN, IK_KPRETURN: if @FOnClickEvent <> nil then FOnClickEvent();
1268 end;
1269 end;
1270 end;
1272 { TGUIMenu }
1274 function TGUIMenu.AddButton(Proc: Pointer; fText: string; _ShowWindow: string = ''): TGUITextButton;
1275 var
1276 i: Integer;
1277 begin
1278 i := NewItem();
1279 with FItems[i] do
1280 begin
1281 Control := TGUITextButton.Create(Proc, FFontID, fText);
1282 with Control as TGUITextButton do
1283 begin
1284 ShowWindow := _ShowWindow;
1285 FColor := MENU_ITEMSCTRL_COLOR;
1286 end;
1288 Text := nil;
1289 ControlType := TGUITextButton;
1291 Result := (Control as TGUITextButton);
1292 end;
1294 if FIndex = -1 then FIndex := i;
1296 ReAlign();
1297 end;
1299 procedure TGUIMenu.AddLine(fText: string);
1300 var
1301 i: Integer;
1302 begin
1303 i := NewItem();
1304 with FItems[i] do
1305 begin
1306 Text := TGUILabel.Create(fText, FFontID);
1307 with Text do
1308 begin
1309 FColor := MENU_ITEMSTEXT_COLOR;
1310 end;
1312 Control := nil;
1313 end;
1315 ReAlign();
1316 end;
1318 procedure TGUIMenu.AddText(fText: string; MaxWidth: Word);
1319 var
1320 a, i: Integer;
1321 l: SArray;
1322 begin
1323 l := GetLines(fText, FFontID, MaxWidth);
1325 if l = nil then Exit;
1327 for a := 0 to High(l) do
1328 begin
1329 i := NewItem();
1330 with FItems[i] do
1331 begin
1332 Text := TGUILabel.Create(l[a], FFontID);
1333 if FYesNo then
1334 begin
1335 with Text do begin FColor := _RGB(255, 0, 0); end;
1336 end
1337 else
1338 begin
1339 with Text do begin FColor := MENU_ITEMSTEXT_COLOR; end;
1340 end;
1342 Control := nil;
1343 end;
1344 end;
1346 ReAlign();
1347 end;
1349 procedure TGUIMenu.AddSpace;
1350 var
1351 i: Integer;
1352 begin
1353 i := NewItem();
1354 with FItems[i] do
1355 begin
1356 Text := nil;
1357 Control := nil;
1358 end;
1360 ReAlign();
1361 end;
1363 constructor TGUIMenu.Create(HeaderFont, ItemsFont: DWORD; Header: string);
1364 begin
1365 inherited Create();
1367 FItems := nil;
1368 FIndex := -1;
1369 FFontID := ItemsFont;
1370 FCounter := MENU_MARKERDELAY;
1371 FAlign := True;
1372 FYesNo := false;
1374 FHeader := TGUILabel.Create(Header, HeaderFont);
1375 with FHeader do
1376 begin
1377 FX := (gScreenWidth div 2)-(GetWidth div 2);
1378 FY := 0;
1379 FColor := MAINMENU_HEADER_COLOR;
1380 end;
1381 end;
1383 destructor TGUIMenu.Destroy;
1384 var
1385 a: Integer;
1386 begin
1387 if FItems <> nil then
1388 for a := 0 to High(FItems) do
1389 with FItems[a] do
1390 begin
1391 Text.Free();
1392 Control.Free();
1393 end;
1395 FItems := nil;
1397 FHeader.Free();
1399 inherited;
1400 end;
1402 procedure TGUIMenu.Draw;
1403 var
1404 a, x, y: Integer;
1405 begin
1406 inherited;
1408 if FHeader <> nil then FHeader.Draw;
1410 if FItems <> nil then
1411 for a := 0 to High(FItems) do
1412 begin
1413 if FItems[a].Text <> nil then FItems[a].Text.Draw;
1414 if FItems[a].Control <> nil then FItems[a].Control.Draw;
1415 end;
1417 if (FIndex <> -1) and (FCounter > MENU_MARKERDELAY div 2) then
1418 begin
1419 x := 0;
1420 y := 0;
1422 if FItems[FIndex].Text <> nil then
1423 begin
1424 x := FItems[FIndex].Text.FX;
1425 y := FItems[FIndex].Text.FY;
1426 //HACK!
1427 if FItems[FIndex].Text.RightAlign then
1428 begin
1429 x := x+FItems[FIndex].Text.FMaxWidth-FItems[FIndex].Text.GetWidth;
1430 end;
1431 end
1432 else if FItems[FIndex].Control <> nil then
1433 begin
1434 x := FItems[FIndex].Control.FX;
1435 y := FItems[FIndex].Control.FY;
1436 end;
1438 x := x-e_CharFont_GetMaxWidth(FFontID);
1440 e_CharFont_PrintEx(FFontID, x, y, #16, _RGB(255, 0, 0));
1441 end;
1442 end;
1444 function TGUIMenu.GetControl(Name: String): TGUIControl;
1445 var
1446 a: Integer;
1447 begin
1448 Result := nil;
1450 if FItems <> nil then
1451 for a := 0 to High(FItems) do
1452 if FItems[a].Control <> nil then
1453 if LowerCase(FItems[a].Control.Name) = LowerCase(Name) then
1454 begin
1455 Result := FItems[a].Control;
1456 Break;
1457 end;
1459 Assert(Result <> nil, 'GUI control "'+Name+'" not found!');
1460 end;
1462 function TGUIMenu.GetControlsText(Name: String): TGUILabel;
1463 var
1464 a: Integer;
1465 begin
1466 Result := nil;
1468 if FItems <> nil then
1469 for a := 0 to High(FItems) do
1470 if FItems[a].Control <> nil then
1471 if LowerCase(FItems[a].Control.Name) = LowerCase(Name) then
1472 begin
1473 Result := FItems[a].Text;
1474 Break;
1475 end;
1477 Assert(Result <> nil, 'GUI control''s text "'+Name+'" not found!');
1478 end;
1480 function TGUIMenu.NewItem: Integer;
1481 begin
1482 SetLength(FItems, Length(FItems)+1);
1483 Result := High(FItems);
1484 end;
1486 procedure TGUIMenu.OnMessage(var Msg: TMessage);
1487 var
1488 ok: Boolean;
1489 a, c: Integer;
1490 begin
1491 if not FEnabled then Exit;
1493 inherited;
1495 if FItems = nil then Exit;
1497 ok := False;
1498 for a := 0 to High(FItems) do
1499 if FItems[a].Control <> nil then
1500 begin
1501 ok := True;
1502 Break;
1503 end;
1505 if not ok then Exit;
1507 if (Msg.Msg = WM_KEYDOWN) and (FIndex <> -1) and (FItems[FIndex].Control <> nil) and
1508 (FItems[FIndex].Control.WantActivationKey(Msg.wParam)) then
1509 begin
1510 FItems[FIndex].Control.OnMessage(Msg);
1511 g_Sound_PlayEx(MENU_CLICKSOUND);
1512 exit;
1513 end;
1515 case Msg.Msg of
1516 WM_KEYDOWN:
1517 begin
1518 case Msg.wParam of
1519 IK_UP, IK_KPUP:
1520 begin
1521 c := 0;
1522 repeat
1523 c := c+1;
1524 if c > Length(FItems) then
1525 begin
1526 FIndex := -1;
1527 Break;
1528 end;
1530 Dec(FIndex);
1531 if FIndex < 0 then FIndex := High(FItems);
1532 until (FItems[FIndex].Control <> nil) and
1533 (FItems[FIndex].Control.Enabled);
1535 FCounter := 0;
1537 g_Sound_PlayEx(MENU_CHANGESOUND);
1538 end;
1540 IK_DOWN, IK_KPDOWN:
1541 begin
1542 c := 0;
1543 repeat
1544 c := c+1;
1545 if c > Length(FItems) then
1546 begin
1547 FIndex := -1;
1548 Break;
1549 end;
1551 Inc(FIndex);
1552 if FIndex > High(FItems) then FIndex := 0;
1553 until (FItems[FIndex].Control <> nil) and
1554 (FItems[FIndex].Control.Enabled);
1556 FCounter := 0;
1558 g_Sound_PlayEx(MENU_CHANGESOUND);
1559 end;
1561 IK_LEFT, IK_RIGHT, IK_KPLEFT, IK_KPRIGHT:
1562 begin
1563 if FIndex <> -1 then
1564 if FItems[FIndex].Control <> nil then
1565 FItems[FIndex].Control.OnMessage(Msg);
1566 end;
1567 IK_RETURN, IK_KPRETURN:
1568 begin
1569 if FIndex <> -1 then
1570 begin
1571 if FItems[FIndex].Control <> nil then FItems[FIndex].Control.OnMessage(Msg);
1572 end;
1573 g_Sound_PlayEx(MENU_CLICKSOUND);
1574 end;
1575 // dirty hacks
1576 IK_Y:
1577 if FYesNo and (length(FItems) > 1) then
1578 begin
1579 Msg.wParam := IK_RETURN; // to register keypress
1580 FIndex := High(FItems)-1;
1581 if FItems[FIndex].Control <> nil then FItems[FIndex].Control.OnMessage(Msg);
1582 end;
1583 IK_N:
1584 if FYesNo and (length(FItems) > 1) then
1585 begin
1586 Msg.wParam := IK_RETURN; // to register keypress
1587 FIndex := High(FItems);
1588 if FItems[FIndex].Control <> nil then FItems[FIndex].Control.OnMessage(Msg);
1589 end;
1590 end;
1591 end;
1592 end;
1593 end;
1595 procedure TGUIMenu.ReAlign();
1596 var
1597 a, tx, cx, w, h: Integer;
1598 cww: array of Integer; // cached widths
1599 maxcww: Integer;
1600 begin
1601 if FItems = nil then Exit;
1603 SetLength(cww, length(FItems));
1604 maxcww := 0;
1605 for a := 0 to High(FItems) do
1606 begin
1607 if FItems[a].Text <> nil then
1608 begin
1609 cww[a] := FItems[a].Text.GetWidth;
1610 if maxcww < cww[a] then maxcww := cww[a];
1611 end;
1612 end;
1614 if not FAlign then
1615 begin
1616 tx := FLeft;
1617 end
1618 else
1619 begin
1620 tx := gScreenWidth;
1621 for a := 0 to High(FItems) do
1622 begin
1623 w := 0;
1624 if FItems[a].Text <> nil then w := FItems[a].Text.GetWidth;
1625 if FItems[a].Control <> nil then
1626 begin
1627 w := w+MENU_HSPACE;
1628 if FItems[a].ControlType = TGUILabel then w := w+(FItems[a].Control as TGUILabel).GetWidth
1629 else if FItems[a].ControlType = TGUITextButton then w := w+(FItems[a].Control as TGUITextButton).GetWidth
1630 else if FItems[a].ControlType = TGUIScroll then w := w+(FItems[a].Control as TGUIScroll).GetWidth
1631 else if FItems[a].ControlType = TGUISwitch then w := w+(FItems[a].Control as TGUISwitch).GetWidth
1632 else if FItems[a].ControlType = TGUIEdit then w := w+(FItems[a].Control as TGUIEdit).GetWidth
1633 else if FItems[a].ControlType = TGUIKeyRead then w := w+(FItems[a].Control as TGUIKeyRead).GetWidth
1634 else if FItems[a].ControlType = TGUIKeyRead2 then w := w+(FItems[a].Control as TGUIKeyRead2).GetWidth
1635 else if FItems[a].ControlType = TGUIListBox then w := w+(FItems[a].Control as TGUIListBox).GetWidth
1636 else if FItems[a].ControlType = TGUIFileListBox then w := w+(FItems[a].Control as TGUIFileListBox).GetWidth
1637 else if FItems[a].ControlType = TGUIMemo then w := w+(FItems[a].Control as TGUIMemo).GetWidth;
1638 end;
1639 tx := Min(tx, (gScreenWidth div 2)-(w div 2));
1640 end;
1641 end;
1643 cx := 0;
1644 for a := 0 to High(FItems) do
1645 begin
1646 with FItems[a] do
1647 begin
1648 if (Text <> nil) and (Control = nil) then Continue;
1649 w := 0;
1650 if Text <> nil then w := tx+Text.GetWidth;
1651 if w > cx then cx := w;
1652 end;
1653 end;
1655 cx := cx+MENU_HSPACE;
1657 h := FHeader.GetHeight*2+MENU_VSPACE*(Length(FItems)-1);
1659 for a := 0 to High(FItems) do
1660 begin
1661 with FItems[a] do
1662 begin
1663 if (ControlType = TGUIListBox) or (ControlType = TGUIFileListBox) then
1664 h := h+(FItems[a].Control as TGUIListBox).GetHeight()
1665 else
1666 h := h+e_CharFont_GetMaxHeight(FFontID);
1667 end;
1668 end;
1670 h := (gScreenHeight div 2)-(h div 2);
1672 with FHeader do
1673 begin
1674 FX := (gScreenWidth div 2)-(GetWidth div 2);
1675 FY := h;
1677 Inc(h, GetHeight*2);
1678 end;
1680 for a := 0 to High(FItems) do
1681 begin
1682 with FItems[a] do
1683 begin
1684 if Text <> nil then
1685 begin
1686 with Text do
1687 begin
1688 FX := tx;
1689 FY := h;
1690 end;
1691 //HACK!
1692 if Text.RightAlign and (length(cww) > a) then
1693 begin
1694 //Text.FX := Text.FX+maxcww;
1695 Text.FMaxWidth := maxcww;
1696 end;
1697 end;
1699 if Control <> nil then
1700 begin
1701 with Control do
1702 begin
1703 if Text <> nil then
1704 begin
1705 FX := cx;
1706 FY := h;
1707 end
1708 else
1709 begin
1710 FX := tx;
1711 FY := h;
1712 end;
1713 end;
1714 end;
1716 if (ControlType = TGUIListBox) or (ControlType = TGUIFileListBox) then Inc(h, (Control as TGUIListBox).GetHeight+MENU_VSPACE)
1717 else if ControlType = TGUIMemo then Inc(h, (Control as TGUIMemo).GetHeight+MENU_VSPACE)
1718 else Inc(h, e_CharFont_GetMaxHeight(FFontID)+MENU_VSPACE);
1719 end;
1720 end;
1722 // another ugly hack
1723 if FYesNo and (length(FItems) > 1) then
1724 begin
1725 w := -1;
1726 for a := High(FItems)-1 to High(FItems) do
1727 begin
1728 if (FItems[a].Control <> nil) and (FItems[a].ControlType = TGUITextButton) then
1729 begin
1730 cx := (FItems[a].Control as TGUITextButton).GetWidth;
1731 if cx > w then w := cx;
1732 end;
1733 end;
1734 if w > 0 then
1735 begin
1736 for a := High(FItems)-1 to High(FItems) do
1737 begin
1738 if (FItems[a].Control <> nil) and (FItems[a].ControlType = TGUITextButton) then
1739 begin
1740 FItems[a].Control.FX := (gScreenWidth-w) div 2;
1741 end;
1742 end;
1743 end;
1744 end;
1745 end;
1747 function TGUIMenu.AddScroll(fText: string): TGUIScroll;
1748 var
1749 i: Integer;
1750 begin
1751 i := NewItem();
1752 with FItems[i] do
1753 begin
1754 Control := TGUIScroll.Create();
1756 Text := TGUILabel.Create(fText, FFontID);
1757 with Text do
1758 begin
1759 FColor := MENU_ITEMSTEXT_COLOR;
1760 end;
1762 ControlType := TGUIScroll;
1764 Result := (Control as TGUIScroll);
1765 end;
1767 if FIndex = -1 then FIndex := i;
1769 ReAlign();
1770 end;
1772 function TGUIMenu.AddSwitch(fText: string): TGUISwitch;
1773 var
1774 i: Integer;
1775 begin
1776 i := NewItem();
1777 with FItems[i] do
1778 begin
1779 Control := TGUISwitch.Create(FFontID);
1780 (Control as TGUISwitch).FColor := MENU_ITEMSCTRL_COLOR;
1782 Text := TGUILabel.Create(fText, FFontID);
1783 with Text do
1784 begin
1785 FColor := MENU_ITEMSTEXT_COLOR;
1786 end;
1788 ControlType := TGUISwitch;
1790 Result := (Control as TGUISwitch);
1791 end;
1793 if FIndex = -1 then FIndex := i;
1795 ReAlign();
1796 end;
1798 function TGUIMenu.AddEdit(fText: string): TGUIEdit;
1799 var
1800 i: Integer;
1801 begin
1802 i := NewItem();
1803 with FItems[i] do
1804 begin
1805 Control := TGUIEdit.Create(FFontID);
1806 with Control as TGUIEdit do
1807 begin
1808 FWindow := Self.FWindow;
1809 FColor := MENU_ITEMSCTRL_COLOR;
1810 end;
1812 if fText = '' then Text := nil else
1813 begin
1814 Text := TGUILabel.Create(fText, FFontID);
1815 Text.FColor := MENU_ITEMSTEXT_COLOR;
1816 end;
1818 ControlType := TGUIEdit;
1820 Result := (Control as TGUIEdit);
1821 end;
1823 if FIndex = -1 then FIndex := i;
1825 ReAlign();
1826 end;
1828 procedure TGUIMenu.Update;
1829 var
1830 a: Integer;
1831 begin
1832 inherited;
1834 if FCounter = 0 then FCounter := MENU_MARKERDELAY else Dec(FCounter);
1836 if FItems <> nil then
1837 for a := 0 to High(FItems) do
1838 if FItems[a].Control <> nil then
1839 (FItems[a].Control as FItems[a].ControlType).Update;
1840 end;
1842 function TGUIMenu.AddKeyRead(fText: string): TGUIKeyRead;
1843 var
1844 i: Integer;
1845 begin
1846 i := NewItem();
1847 with FItems[i] do
1848 begin
1849 Control := TGUIKeyRead.Create(FFontID);
1850 with Control as TGUIKeyRead do
1851 begin
1852 FWindow := Self.FWindow;
1853 FColor := MENU_ITEMSCTRL_COLOR;
1854 end;
1856 Text := TGUILabel.Create(fText, FFontID);
1857 with Text do
1858 begin
1859 FColor := MENU_ITEMSTEXT_COLOR;
1860 end;
1862 ControlType := TGUIKeyRead;
1864 Result := (Control as TGUIKeyRead);
1865 end;
1867 if FIndex = -1 then FIndex := i;
1869 ReAlign();
1870 end;
1872 function TGUIMenu.AddKeyRead2(fText: string): TGUIKeyRead2;
1873 var
1874 i: Integer;
1875 begin
1876 i := NewItem();
1877 with FItems[i] do
1878 begin
1879 Control := TGUIKeyRead2.Create(FFontID);
1880 with Control as TGUIKeyRead2 do
1881 begin
1882 FWindow := Self.FWindow;
1883 FColor := MENU_ITEMSCTRL_COLOR;
1884 end;
1886 Text := TGUILabel.Create(fText, FFontID);
1887 with Text do
1888 begin
1889 FColor := MENU_ITEMSCTRL_COLOR; //MENU_ITEMSTEXT_COLOR;
1890 RightAlign := true;
1891 end;
1893 ControlType := TGUIKeyRead2;
1895 Result := (Control as TGUIKeyRead2);
1896 end;
1898 if FIndex = -1 then FIndex := i;
1900 ReAlign();
1901 end;
1903 function TGUIMenu.AddList(fText: string; Width, Height: Word): TGUIListBox;
1904 var
1905 i: Integer;
1906 begin
1907 i := NewItem();
1908 with FItems[i] do
1909 begin
1910 Control := TGUIListBox.Create(FFontID, Width, Height);
1911 with Control as TGUIListBox do
1912 begin
1913 FWindow := Self.FWindow;
1914 FActiveColor := MENU_ITEMSCTRL_COLOR;
1915 FUnActiveColor := MENU_ITEMSTEXT_COLOR;
1916 end;
1918 Text := TGUILabel.Create(fText, FFontID);
1919 with Text do
1920 begin
1921 FColor := MENU_ITEMSTEXT_COLOR;
1922 end;
1924 ControlType := TGUIListBox;
1926 Result := (Control as TGUIListBox);
1927 end;
1929 if FIndex = -1 then FIndex := i;
1931 ReAlign();
1932 end;
1934 function TGUIMenu.AddFileList(fText: string; Width, Height: Word): TGUIFileListBox;
1935 var
1936 i: Integer;
1937 begin
1938 i := NewItem();
1939 with FItems[i] do
1940 begin
1941 Control := TGUIFileListBox.Create(FFontID, Width, Height);
1942 with Control as TGUIFileListBox do
1943 begin
1944 FWindow := Self.FWindow;
1945 FActiveColor := MENU_ITEMSCTRL_COLOR;
1946 FUnActiveColor := MENU_ITEMSTEXT_COLOR;
1947 end;
1949 if fText = '' then Text := nil else
1950 begin
1951 Text := TGUILabel.Create(fText, FFontID);
1952 Text.FColor := MENU_ITEMSTEXT_COLOR;
1953 end;
1955 ControlType := TGUIFileListBox;
1957 Result := (Control as TGUIFileListBox);
1958 end;
1960 if FIndex = -1 then FIndex := i;
1962 ReAlign();
1963 end;
1965 function TGUIMenu.AddLabel(fText: string): TGUILabel;
1966 var
1967 i: Integer;
1968 begin
1969 i := NewItem();
1970 with FItems[i] do
1971 begin
1972 Control := TGUILabel.Create('', FFontID);
1973 with Control as TGUILabel do
1974 begin
1975 FWindow := Self.FWindow;
1976 FColor := MENU_ITEMSCTRL_COLOR;
1977 end;
1979 Text := TGUILabel.Create(fText, FFontID);
1980 with Text do
1981 begin
1982 FColor := MENU_ITEMSTEXT_COLOR;
1983 end;
1985 ControlType := TGUILabel;
1987 Result := (Control as TGUILabel);
1988 end;
1990 if FIndex = -1 then FIndex := i;
1992 ReAlign();
1993 end;
1995 function TGUIMenu.AddMemo(fText: string; Width, Height: Word): TGUIMemo;
1996 var
1997 i: Integer;
1998 begin
1999 i := NewItem();
2000 with FItems[i] do
2001 begin
2002 Control := TGUIMemo.Create(FFontID, Width, Height);
2003 with Control as TGUIMemo do
2004 begin
2005 FWindow := Self.FWindow;
2006 FColor := MENU_ITEMSTEXT_COLOR;
2007 end;
2009 if fText = '' then Text := nil else
2010 begin
2011 Text := TGUILabel.Create(fText, FFontID);
2012 Text.FColor := MENU_ITEMSTEXT_COLOR;
2013 end;
2015 ControlType := TGUIMemo;
2017 Result := (Control as TGUIMemo);
2018 end;
2020 if FIndex = -1 then FIndex := i;
2022 ReAlign();
2023 end;
2025 procedure TGUIMenu.UpdateIndex();
2026 var
2027 res: Boolean;
2028 begin
2029 res := True;
2031 while res do
2032 begin
2033 if (FIndex < 0) or (FIndex > High(FItems)) then
2034 begin
2035 FIndex := -1;
2036 res := False;
2037 end
2038 else
2039 if FItems[FIndex].Control.Enabled then
2040 res := False
2041 else
2042 Inc(FIndex);
2043 end;
2044 end;
2046 { TGUIScroll }
2048 constructor TGUIScroll.Create;
2049 begin
2050 inherited Create();
2052 FMax := 0;
2053 FOnChangeEvent := nil;
2055 g_Texture_Get(SCROLL_LEFT, FLeftID);
2056 g_Texture_Get(SCROLL_RIGHT, FRightID);
2057 g_Texture_Get(SCROLL_MIDDLE, FMiddleID);
2058 g_Texture_Get(SCROLL_MARKER, FMarkerID);
2059 end;
2061 procedure TGUIScroll.Draw;
2062 var
2063 a: Integer;
2064 begin
2065 inherited;
2067 e_Draw(FLeftID, FX, FY, 0, True, False);
2068 e_Draw(FRightID, FX+8+(FMax+1)*8, FY, 0, True, False);
2070 for a := 0 to FMax do
2071 e_Draw(FMiddleID, FX+8+a*8, FY, 0, True, False);
2073 e_Draw(FMarkerID, FX+8+FValue*8, FY, 0, True, False);
2074 end;
2076 procedure TGUIScroll.FSetValue(a: Integer);
2077 begin
2078 if a > FMax then FValue := FMax else FValue := a;
2079 end;
2081 function TGUIScroll.GetWidth: Integer;
2082 begin
2083 Result := 16+(FMax+1)*8;
2084 end;
2086 procedure TGUIScroll.OnMessage(var Msg: TMessage);
2087 begin
2088 if not FEnabled then Exit;
2090 inherited;
2092 case Msg.Msg of
2093 WM_KEYDOWN:
2094 begin
2095 case Msg.wParam of
2096 IK_LEFT, IK_KPLEFT:
2097 if FValue > 0 then
2098 begin
2099 Dec(FValue);
2100 g_Sound_PlayEx(SCROLL_SUBSOUND);
2101 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
2102 end;
2103 IK_RIGHT, IK_KPRIGHT:
2104 if FValue < FMax then
2105 begin
2106 Inc(FValue);
2107 g_Sound_PlayEx(SCROLL_ADDSOUND);
2108 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
2109 end;
2110 end;
2111 end;
2112 end;
2113 end;
2115 procedure TGUIScroll.Update;
2116 begin
2117 inherited;
2119 end;
2121 { TGUISwitch }
2123 procedure TGUISwitch.AddItem(Item: string);
2124 begin
2125 SetLength(FItems, Length(FItems)+1);
2126 FItems[High(FItems)] := Item;
2128 if FIndex = -1 then FIndex := 0;
2129 end;
2131 constructor TGUISwitch.Create(FontID: DWORD);
2132 begin
2133 inherited Create();
2135 FIndex := -1;
2137 FFont := TFont.Create(FontID, FONT_CHAR);
2138 end;
2140 procedure TGUISwitch.Draw;
2141 begin
2142 inherited;
2144 FFont.Draw(FX, FY, FItems[FIndex], FColor.R, FColor.G, FColor.B);
2145 end;
2147 function TGUISwitch.GetText: string;
2148 begin
2149 if FIndex <> -1 then Result := FItems[FIndex]
2150 else Result := '';
2151 end;
2153 function TGUISwitch.GetWidth: Integer;
2154 var
2155 a: Integer;
2156 w, h: Word;
2157 begin
2158 Result := 0;
2160 if FItems = nil then Exit;
2162 for a := 0 to High(FItems) do
2163 begin
2164 FFont.GetTextSize(FItems[a], w, h);
2165 if w > Result then Result := w;
2166 end;
2167 end;
2169 procedure TGUISwitch.OnMessage(var Msg: TMessage);
2170 begin
2171 if not FEnabled then Exit;
2173 inherited;
2175 if FItems = nil then Exit;
2177 case Msg.Msg of
2178 WM_KEYDOWN:
2179 case Msg.wParam of
2180 IK_RETURN, IK_RIGHT, IK_KPRETURN, IK_KPRIGHT:
2181 begin
2182 if FIndex < High(FItems) then
2183 Inc(FIndex)
2184 else
2185 FIndex := 0;
2187 if @FOnChangeEvent <> nil then
2188 FOnChangeEvent(Self);
2189 end;
2191 IK_LEFT, IK_KPLEFT:
2192 begin
2193 if FIndex > 0 then
2194 Dec(FIndex)
2195 else
2196 FIndex := High(FItems);
2198 if @FOnChangeEvent <> nil then
2199 FOnChangeEvent(Self);
2200 end;
2201 end;
2202 end;
2203 end;
2205 procedure TGUISwitch.Update;
2206 begin
2207 inherited;
2209 end;
2211 { TGUIEdit }
2213 constructor TGUIEdit.Create(FontID: DWORD);
2214 begin
2215 inherited Create();
2217 FFont := TFont.Create(FontID, FONT_CHAR);
2219 FMaxLength := 0;
2220 FWidth := 0;
2222 g_Texture_Get(EDIT_LEFT, FLeftID);
2223 g_Texture_Get(EDIT_RIGHT, FRightID);
2224 g_Texture_Get(EDIT_MIDDLE, FMiddleID);
2225 end;
2227 procedure TGUIEdit.Draw;
2228 var
2229 c, w, h: Word;
2230 begin
2231 inherited;
2233 e_Draw(FLeftID, FX, FY, 0, True, False);
2234 e_Draw(FRightID, FX+8+FWidth*16, FY, 0, True, False);
2236 for c := 0 to FWidth-1 do
2237 e_Draw(FMiddleID, FX+8+c*16, FY, 0, True, False);
2239 FFont.Draw(FX+8, FY, FText, FColor.R, FColor.G, FColor.B);
2241 if FWindow.FActiveControl = Self then
2242 begin
2243 FFont.GetTextSize(Copy(FText, 1, FCaretPos), w, h);
2244 h := e_CharFont_GetMaxHeight(FFont.ID);
2245 e_DrawLine(2, FX+8+w, FY+h-3, FX+8+w+EDIT_CURSORLEN, FY+h-3,
2246 EDIT_CURSORCOLOR.R, EDIT_CURSORCOLOR.G, EDIT_CURSORCOLOR.B);
2247 end;
2248 end;
2250 function TGUIEdit.GetWidth: Integer;
2251 begin
2252 Result := 16+FWidth*16;
2253 end;
2255 procedure TGUIEdit.OnMessage(var Msg: TMessage);
2256 begin
2257 if not FEnabled then Exit;
2259 inherited;
2261 with Msg do
2262 case Msg of
2263 WM_CHAR:
2264 if FOnlyDigits then
2265 begin
2266 if (wParam in [48..57]) and (Chr(wParam) <> '`') then
2267 if Length(Text) < FMaxLength then
2268 begin
2269 Insert(Chr(wParam), FText, FCaretPos + 1);
2270 Inc(FCaretPos);
2271 end;
2272 end
2273 else
2274 begin
2275 if (wParam in [32..255]) and (Chr(wParam) <> '`') then
2276 if Length(Text) < FMaxLength then
2277 begin
2278 Insert(Chr(wParam), FText, FCaretPos + 1);
2279 Inc(FCaretPos);
2280 end;
2281 end;
2282 WM_KEYDOWN:
2283 case wParam of
2284 IK_BACKSPACE:
2285 begin
2286 Delete(FText, FCaretPos, 1);
2287 if FCaretPos > 0 then Dec(FCaretPos);
2288 end;
2289 IK_DELETE: Delete(FText, FCaretPos + 1, 1);
2290 IK_END, IK_KPEND: FCaretPos := Length(FText);
2291 IK_HOME, IK_KPHOME: FCaretPos := 0;
2292 IK_LEFT, IK_KPLEFT: if FCaretPos > 0 then Dec(FCaretPos);
2293 IK_RIGHT, IK_KPRIGHT: if FCaretPos < Length(FText) then Inc(FCaretPos);
2294 IK_RETURN, IK_KPRETURN:
2295 with FWindow do
2296 begin
2297 if FActiveControl <> Self then
2298 begin
2299 SetActive(Self);
2300 if @FOnEnterEvent <> nil then FOnEnterEvent(Self);
2301 end
2302 else
2303 begin
2304 if FDefControl <> '' then SetActive(GetControl(FDefControl))
2305 else SetActive(nil);
2306 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
2307 end;
2308 end;
2309 end;
2310 end;
2311 end;
2313 procedure TGUIEdit.SetText(Text: string);
2314 begin
2315 if Length(Text) > FMaxLength then SetLength(Text, FMaxLength);
2316 FText := Text;
2317 FCaretPos := Length(FText);
2318 end;
2320 procedure TGUIEdit.Update;
2321 begin
2322 inherited;
2323 end;
2325 { TGUIKeyRead }
2327 constructor TGUIKeyRead.Create(FontID: DWORD);
2328 begin
2329 inherited Create();
2330 FKey := 0;
2331 FIsQuery := false;
2333 FFont := TFont.Create(FontID, FONT_CHAR);
2334 end;
2336 procedure TGUIKeyRead.Draw;
2337 begin
2338 inherited;
2340 FFont.Draw(FX, FY, IfThen(FIsQuery, KEYREAD_QUERY, IfThen(FKey <> 0, e_KeyNames[FKey], KEYREAD_CLEAR)),
2341 FColor.R, FColor.G, FColor.B);
2342 end;
2344 function TGUIKeyRead.GetWidth: Integer;
2345 var
2346 a: Byte;
2347 w, h: Word;
2348 begin
2349 Result := 0;
2351 for a := 0 to 255 do
2352 begin
2353 FFont.GetTextSize(e_KeyNames[a], w, h);
2354 Result := Max(Result, w);
2355 end;
2357 FFont.GetTextSize(KEYREAD_QUERY, w, h);
2358 if w > Result then Result := w;
2360 FFont.GetTextSize(KEYREAD_CLEAR, w, h);
2361 if w > Result then Result := w;
2362 end;
2364 function TGUIKeyRead.WantActivationKey (key: LongInt): Boolean;
2365 begin
2366 result :=
2367 (key = IK_BACKSPACE) or
2368 false; // oops
2369 end;
2371 procedure TGUIKeyRead.OnMessage(var Msg: TMessage);
2372 procedure actDefCtl ();
2373 begin
2374 with FWindow do
2375 if FDefControl <> '' then
2376 SetActive(GetControl(FDefControl))
2377 else
2378 SetActive(nil);
2379 end;
2381 begin
2382 inherited;
2384 if not FEnabled then
2385 Exit;
2387 with Msg do
2388 case Msg of
2389 WM_KEYDOWN:
2390 case wParam of
2391 IK_ESCAPE:
2392 begin
2393 if FIsQuery then actDefCtl();
2394 FIsQuery := False;
2395 end;
2396 IK_RETURN, IK_KPRETURN:
2397 begin
2398 if not FIsQuery then
2399 begin
2400 with FWindow do
2401 if FActiveControl <> Self then
2402 SetActive(Self);
2404 FIsQuery := True;
2405 end
2406 else
2407 begin
2408 FKey := IK_ENTER; // <Enter>
2409 FIsQuery := False;
2410 actDefCtl();
2411 end;
2412 end;
2413 IK_BACKSPACE: // clear keybinding if we aren't waiting for a key
2414 begin
2415 if not FIsQuery then
2416 begin
2417 FKey := 0;
2418 actDefCtl();
2419 end;
2420 end;
2421 end;
2423 MESSAGE_DIKEY:
2424 begin
2425 if not FIsQuery and (wParam = IK_BACKSPACE) then
2426 begin
2427 FKey := 0;
2428 actDefCtl();
2429 end
2430 else if FIsQuery and (wParam <> IK_ENTER) and (wParam <> IK_KPRETURN) then // Not <Enter
2431 begin
2432 if e_KeyNames[wParam] <> '' then
2433 FKey := wParam;
2434 FIsQuery := False;
2435 actDefCtl();
2436 end;
2437 end;
2438 end;
2439 end;
2441 { TGUIKeyRead2 }
2443 constructor TGUIKeyRead2.Create(FontID: DWORD);
2444 var
2445 a: Byte;
2446 w, h: Word;
2447 begin
2448 inherited Create();
2450 FKey0 := 0;
2451 FKey1 := 0;
2452 FKeyIdx := 0;
2453 FIsQuery := False;
2455 FFontID := FontID;
2456 FFont := TFont.Create(FontID, FONT_CHAR);
2458 FMaxKeyNameWdt := 0;
2459 for a := 0 to 255 do
2460 begin
2461 FFont.GetTextSize(e_KeyNames[a], w, h);
2462 FMaxKeyNameWdt := Max(FMaxKeyNameWdt, w);
2463 end;
2465 FMaxKeyNameWdt := FMaxKeyNameWdt-(FMaxKeyNameWdt div 3);
2467 FFont.GetTextSize(KEYREAD_QUERY, w, h);
2468 if w > FMaxKeyNameWdt then FMaxKeyNameWdt := w;
2470 FFont.GetTextSize(KEYREAD_CLEAR, w, h);
2471 if w > FMaxKeyNameWdt then FMaxKeyNameWdt := w;
2472 end;
2474 procedure TGUIKeyRead2.Draw;
2475 procedure drawText (idx: Integer);
2476 var
2477 x, y: Integer;
2478 r, g, b: Byte;
2479 kk: DWORD;
2480 begin
2481 if idx = 0 then kk := FKey0 else kk := FKey1;
2482 y := FY;
2483 if idx = 0 then x := FX+8 else x := FX+8+FMaxKeyNameWdt+16;
2484 r := 255;
2485 g := 0;
2486 b := 0;
2487 if FKeyIdx = idx then begin r := 255; g := 255; b := 255; end;
2488 if FIsQuery and (FKeyIdx = idx) then
2489 FFont.Draw(x, y, KEYREAD_QUERY, r, g, b)
2490 else
2491 FFont.Draw(x, y, IfThen(kk <> 0, e_KeyNames[kk], KEYREAD_CLEAR), r, g, b);
2492 end;
2494 begin
2495 inherited;
2497 //FFont.Draw(FX+8, FY, IfThen(FIsQuery and (FKeyIdx = 0), KEYREAD_QUERY, IfThen(FKey0 <> 0, e_KeyNames[FKey0], KEYREAD_CLEAR)), FColor.R, FColor.G, FColor.B);
2498 //FFont.Draw(FX+8+FMaxKeyNameWdt+16, FY, IfThen(FIsQuery and (FKeyIdx = 1), KEYREAD_QUERY, IfThen(FKey1 <> 0, e_KeyNames[FKey1], KEYREAD_CLEAR)), FColor.R, FColor.G, FColor.B);
2499 drawText(0);
2500 drawText(1);
2501 end;
2503 function TGUIKeyRead2.GetWidth: Integer;
2504 begin
2505 Result := FMaxKeyNameWdt*2+8+8+16;
2506 end;
2508 function TGUIKeyRead2.WantActivationKey (key: LongInt): Boolean;
2509 begin
2510 result :=
2511 (key = IK_BACKSPACE) or
2512 (key = IK_LEFT) or (key = IK_RIGHT) or
2513 (key = IK_KPLEFT) or (key = IK_KPRIGHT) or
2514 false; // oops
2515 end;
2517 procedure TGUIKeyRead2.OnMessage(var Msg: TMessage);
2518 procedure actDefCtl ();
2519 begin
2520 with FWindow do
2521 if FDefControl <> '' then
2522 SetActive(GetControl(FDefControl))
2523 else
2524 SetActive(nil);
2525 end;
2527 begin
2528 inherited;
2530 if not FEnabled then
2531 Exit;
2533 with Msg do
2534 case Msg of
2535 WM_KEYDOWN:
2536 case wParam of
2537 IK_ESCAPE:
2538 begin
2539 if FIsQuery then actDefCtl();
2540 FIsQuery := False;
2541 end;
2542 IK_RETURN, IK_KPRETURN:
2543 begin
2544 if not FIsQuery then
2545 begin
2546 with FWindow do
2547 if FActiveControl <> Self then
2548 SetActive(Self);
2550 FIsQuery := True;
2551 end
2552 else
2553 begin
2554 if (FKeyIdx = 0) then FKey0 := IK_ENTER else FKey1 := IK_ENTER; // <Enter>
2555 FIsQuery := False;
2556 actDefCtl();
2557 end;
2558 end;
2559 IK_BACKSPACE: // clear keybinding if we aren't waiting for a key
2560 begin
2561 if not FIsQuery then
2562 begin
2563 if (FKeyIdx = 0) then FKey0 := 0 else FKey1 := 0;
2564 actDefCtl();
2565 end;
2566 end;
2567 IK_LEFT, IK_KPLEFT:
2568 if not FIsQuery then
2569 begin
2570 FKeyIdx := 0;
2571 actDefCtl();
2572 end;
2573 IK_RIGHT, IK_KPRIGHT:
2574 if not FIsQuery then
2575 begin
2576 FKeyIdx := 1;
2577 actDefCtl();
2578 end;
2579 end;
2581 MESSAGE_DIKEY:
2582 begin
2583 if not FIsQuery and (wParam = IK_BACKSPACE) then
2584 begin
2585 if (FKeyIdx = 0) then FKey0 := 0 else FKey1 := 0;
2586 actDefCtl();
2587 end
2588 else if FIsQuery and (wParam <> IK_ENTER) and (wParam <> IK_KPRETURN) then // Not <Enter
2589 begin
2590 if e_KeyNames[wParam] <> '' then
2591 begin
2592 if (FKeyIdx = 0) then FKey0 := wParam else FKey1 := wParam;
2593 end;
2594 FIsQuery := False;
2595 actDefCtl();
2596 end;
2597 end;
2598 end;
2599 end;
2602 { TGUIModelView }
2604 constructor TGUIModelView.Create;
2605 begin
2606 inherited Create();
2608 FModel := nil;
2609 end;
2611 destructor TGUIModelView.Destroy;
2612 begin
2613 FModel.Free();
2615 inherited;
2616 end;
2618 procedure TGUIModelView.Draw;
2619 begin
2620 inherited;
2622 DrawBox(FX, FY, 4, 4);
2624 if FModel <> nil then FModel.Draw(FX+4, FY+4);
2625 end;
2627 procedure TGUIModelView.NextAnim();
2628 begin
2629 if FModel = nil then
2630 Exit;
2632 if FModel.Animation < A_PAIN then
2633 FModel.ChangeAnimation(FModel.Animation+1, True)
2634 else
2635 FModel.ChangeAnimation(A_STAND, True);
2636 end;
2638 procedure TGUIModelView.NextWeapon();
2639 begin
2640 if FModel = nil then
2641 Exit;
2643 if FModel.Weapon < WEAPON_SUPERPULEMET then
2644 FModel.SetWeapon(FModel.Weapon+1)
2645 else
2646 FModel.SetWeapon(WEAPON_KASTET);
2647 end;
2649 procedure TGUIModelView.OnMessage(var Msg: TMessage);
2650 begin
2651 inherited;
2653 end;
2655 procedure TGUIModelView.SetColor(Red, Green, Blue: Byte);
2656 begin
2657 if FModel <> nil then FModel.SetColor(Red, Green, Blue);
2658 end;
2660 procedure TGUIModelView.SetModel(ModelName: string);
2661 begin
2662 FModel.Free();
2664 FModel := g_PlayerModel_Get(ModelName);
2665 end;
2667 procedure TGUIModelView.Update;
2668 begin
2669 inherited;
2671 a := not a;
2672 if a then Exit;
2674 if FModel <> nil then FModel.Update;
2675 end;
2677 { TGUIMapPreview }
2679 constructor TGUIMapPreview.Create();
2680 begin
2681 inherited Create();
2682 ClearMap;
2683 end;
2685 destructor TGUIMapPreview.Destroy();
2686 begin
2687 ClearMap;
2688 inherited;
2689 end;
2691 procedure TGUIMapPreview.Draw();
2692 var
2693 a: Integer;
2694 r, g, b: Byte;
2695 begin
2696 inherited;
2698 DrawBox(FX, FY, MAPPREVIEW_WIDTH, MAPPREVIEW_HEIGHT);
2700 if (FMapSize.X <= 0) or (FMapSize.Y <= 0) then
2701 Exit;
2703 e_DrawFillQuad(FX+4, FY+4,
2704 FX+4 + Trunc(FMapSize.X / FScale) - 1,
2705 FY+4 + Trunc(FMapSize.Y / FScale) - 1,
2706 32, 32, 32, 0);
2708 if FMapData <> nil then
2709 for a := 0 to High(FMapData) do
2710 with FMapData[a] do
2711 begin
2712 if X1 > MAPPREVIEW_WIDTH*16 then Continue;
2713 if Y1 > MAPPREVIEW_HEIGHT*16 then Continue;
2715 if X2 < 0 then Continue;
2716 if Y2 < 0 then Continue;
2718 if X2 > MAPPREVIEW_WIDTH*16 then X2 := MAPPREVIEW_WIDTH*16;
2719 if Y2 > MAPPREVIEW_HEIGHT*16 then Y2 := MAPPREVIEW_HEIGHT*16;
2721 if X1 < 0 then X1 := 0;
2722 if Y1 < 0 then Y1 := 0;
2724 case PanelType of
2725 PANEL_WALL:
2726 begin
2727 r := 255;
2728 g := 255;
2729 b := 255;
2730 end;
2731 PANEL_CLOSEDOOR:
2732 begin
2733 r := 255;
2734 g := 255;
2735 b := 0;
2736 end;
2737 PANEL_WATER:
2738 begin
2739 r := 0;
2740 g := 0;
2741 b := 192;
2742 end;
2743 PANEL_ACID1:
2744 begin
2745 r := 0;
2746 g := 176;
2747 b := 0;
2748 end;
2749 PANEL_ACID2:
2750 begin
2751 r := 176;
2752 g := 0;
2753 b := 0;
2754 end;
2755 else
2756 begin
2757 r := 128;
2758 g := 128;
2759 b := 128;
2760 end;
2761 end;
2763 if ((X2-X1) > 0) and ((Y2-Y1) > 0) then
2764 e_DrawFillQuad(FX+4 + X1, FY+4 + Y1,
2765 FX+4 + X2 - 1, FY+4 + Y2 - 1, r, g, b, 0);
2766 end;
2767 end;
2769 procedure TGUIMapPreview.OnMessage(var Msg: TMessage);
2770 begin
2771 inherited;
2773 end;
2775 procedure TGUIMapPreview.SetMap(Res: string);
2776 var
2777 WAD: TWADFile;
2778 MapReader: TMapReader_1;
2779 panels: TPanelsRec1Array;
2780 header: TMapHeaderRec_1;
2781 a: Integer;
2782 FileName: string;
2783 Data: Pointer;
2784 Len: Integer;
2785 rX, rY: Single;
2786 begin
2787 FileName := g_ExtractWadName(Res);
2789 WAD := TWADFile.Create();
2790 if not WAD.ReadFile(FileName) then
2791 begin
2792 WAD.Free();
2793 Exit;
2794 end;
2796 //k8: ignores path again
2797 if not WAD.GetMapResource(g_ExtractFileName(Res), Data, Len) then
2798 begin
2799 WAD.Free();
2800 Exit;
2801 end;
2803 WAD.Free();
2805 MapReader := TMapReader_1.Create();
2807 if not MapReader.LoadMap(Data) then
2808 begin
2809 FreeMem(Data);
2810 MapReader.Free();
2811 FMapSize.X := 0;
2812 FMapSize.Y := 0;
2813 FScale := 0.0;
2814 FMapData := nil;
2815 Exit;
2816 end;
2818 FreeMem(Data);
2820 panels := MapReader.GetPanels();
2821 header := MapReader.GetMapHeader();
2823 FMapSize.X := header.Width div 16;
2824 FMapSize.Y := header.Height div 16;
2826 rX := Ceil(header.Width / (MAPPREVIEW_WIDTH*256.0));
2827 rY := Ceil(header.Height / (MAPPREVIEW_HEIGHT*256.0));
2828 FScale := max(rX, rY);
2830 FMapData := nil;
2832 if panels <> nil then
2833 for a := 0 to High(panels) do
2834 if WordBool(panels[a].PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or
2835 PANEL_STEP or PANEL_WATER or
2836 PANEL_ACID1 or PANEL_ACID2)) then
2837 begin
2838 SetLength(FMapData, Length(FMapData)+1);
2839 with FMapData[High(FMapData)] do
2840 begin
2841 X1 := panels[a].X div 16;
2842 Y1 := panels[a].Y div 16;
2844 X2 := (panels[a].X + panels[a].Width) div 16;
2845 Y2 := (panels[a].Y + panels[a].Height) div 16;
2847 X1 := Trunc(X1/FScale + 0.5);
2848 Y1 := Trunc(Y1/FScale + 0.5);
2849 X2 := Trunc(X2/FScale + 0.5);
2850 Y2 := Trunc(Y2/FScale + 0.5);
2852 if (X1 <> X2) or (Y1 <> Y2) then
2853 begin
2854 if X1 = X2 then
2855 X2 := X2 + 1;
2856 if Y1 = Y2 then
2857 Y2 := Y2 + 1;
2858 end;
2860 PanelType := panels[a].PanelType;
2861 end;
2862 end;
2864 panels := nil;
2866 MapReader.Free();
2867 end;
2869 procedure TGUIMapPreview.ClearMap();
2870 begin
2871 SetLength(FMapData, 0);
2872 FMapData := nil;
2873 FMapSize.X := 0;
2874 FMapSize.Y := 0;
2875 FScale := 0.0;
2876 end;
2878 procedure TGUIMapPreview.Update();
2879 begin
2880 inherited;
2882 end;
2884 function TGUIMapPreview.GetScaleStr(): String;
2885 begin
2886 if FScale > 0.0 then
2887 begin
2888 Result := FloatToStrF(FScale*16.0, ffFixed, 3, 3);
2889 while (Result[Length(Result)] = '0') do
2890 Delete(Result, Length(Result), 1);
2891 if (Result[Length(Result)] = ',') or (Result[Length(Result)] = '.') then
2892 Delete(Result, Length(Result), 1);
2893 Result := '1 : ' + Result;
2894 end
2895 else
2896 Result := '';
2897 end;
2899 { TGUIListBox }
2901 procedure TGUIListBox.AddItem(Item: string);
2902 begin
2903 SetLength(FItems, Length(FItems)+1);
2904 FItems[High(FItems)] := Item;
2906 if FSort then g_Basic.Sort(FItems);
2907 end;
2909 procedure TGUIListBox.Clear();
2910 begin
2911 FItems := nil;
2913 FStartLine := 0;
2914 FIndex := -1;
2915 end;
2917 constructor TGUIListBox.Create(FontID: DWORD; Width, Height: Word);
2918 begin
2919 inherited Create();
2921 FFont := TFont.Create(FontID, FONT_CHAR);
2923 FWidth := Width;
2924 FHeight := Height;
2925 FIndex := -1;
2926 FOnChangeEvent := nil;
2927 FDrawBack := True;
2928 FDrawScroll := True;
2929 end;
2931 procedure TGUIListBox.Draw;
2932 var
2933 w2, h2: Word;
2934 a: Integer;
2935 s: string;
2936 begin
2937 inherited;
2939 if FDrawBack then DrawBox(FX, FY, FWidth+1, FHeight);
2940 if FDrawScroll then
2941 DrawScroll(FX+4+FWidth*16, FY+4, FHeight, (FStartLine > 0) and (FItems <> nil),
2942 (FStartLine+FHeight-1 < High(FItems)) and (FItems <> nil));
2944 if FItems <> nil then
2945 for a := FStartLine to Min(High(FItems), FStartLine+FHeight-1) do
2946 begin
2947 s := Items[a];
2949 FFont.GetTextSize(s, w2, h2);
2950 while (Length(s) > 0) and (w2 > FWidth*16) do
2951 begin
2952 SetLength(s, Length(s)-1);
2953 FFont.GetTextSize(s, w2, h2);
2954 end;
2956 if a = FIndex then
2957 FFont.Draw(FX+4, FY+4+(a-FStartLine)*16, s, FActiveColor.R, FActiveColor.G, FActiveColor.B)
2958 else
2959 FFont.Draw(FX+4, FY+4+(a-FStartLine)*16, s, FUnActiveColor.R, FUnActiveColor.G, FUnActiveColor.B);
2960 end;
2961 end;
2963 function TGUIListBox.GetHeight: Integer;
2964 begin
2965 Result := 8+FHeight*16;
2966 end;
2968 function TGUIListBox.GetWidth: Integer;
2969 begin
2970 Result := 8+(FWidth+1)*16;
2971 end;
2973 procedure TGUIListBox.OnMessage(var Msg: TMessage);
2974 var
2975 a: Integer;
2976 begin
2977 if not FEnabled then Exit;
2979 inherited;
2981 if FItems = nil then Exit;
2983 with Msg do
2984 case Msg of
2985 WM_KEYDOWN:
2986 case wParam of
2987 IK_HOME, IK_KPHOME:
2988 begin
2989 FIndex := 0;
2990 FStartLine := 0;
2991 end;
2992 IK_END, IK_KPEND:
2993 begin
2994 FIndex := High(FItems);
2995 FStartLine := Max(High(FItems)-FHeight+1, 0);
2996 end;
2997 IK_UP, IK_LEFT, IK_KPUP, IK_KPLEFT:
2998 if FIndex > 0 then
2999 begin
3000 Dec(FIndex);
3001 if FIndex < FStartLine then Dec(FStartLine);
3002 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
3003 end;
3004 IK_DOWN, IK_RIGHT, IK_KPDOWN, IK_KPRIGHT:
3005 if FIndex < High(FItems) then
3006 begin
3007 Inc(FIndex);
3008 if FIndex > FStartLine+FHeight-1 then Inc(FStartLine);
3009 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
3010 end;
3011 IK_RETURN, IK_KPRETURN:
3012 with FWindow do
3013 begin
3014 if FActiveControl <> Self then SetActive(Self)
3015 else
3016 if FDefControl <> '' then SetActive(GetControl(FDefControl))
3017 else SetActive(nil);
3018 end;
3019 end;
3020 WM_CHAR:
3021 for a := 0 to High(FItems) do
3022 if (Length(FItems[a]) > 0) and (LowerCase(FItems[a][1]) = LowerCase(Chr(wParam))) then
3023 begin
3024 FIndex := a;
3025 FStartLine := Min(Max(FIndex-1, 0), Length(FItems)-FHeight);
3026 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
3027 Break;
3028 end;
3029 end;
3030 end;
3032 function TGUIListBox.SelectedItem(): String;
3033 begin
3034 Result := '';
3036 if (FIndex < 0) or (FItems = nil) or
3037 (FIndex > High(FItems)) then
3038 Exit;
3040 Result := FItems[FIndex];
3041 end;
3043 procedure TGUIListBox.FSetItems(Items: SArray);
3044 begin
3045 if FItems <> nil then
3046 FItems := nil;
3048 FItems := Items;
3050 FStartLine := 0;
3051 FIndex := -1;
3053 if FSort then g_Basic.Sort(FItems);
3054 end;
3056 procedure TGUIListBox.SelectItem(Item: String);
3057 var
3058 a: Integer;
3059 begin
3060 if FItems = nil then
3061 Exit;
3063 FIndex := 0;
3064 Item := LowerCase(Item);
3066 for a := 0 to High(FItems) do
3067 if LowerCase(FItems[a]) = Item then
3068 begin
3069 FIndex := a;
3070 Break;
3071 end;
3073 if FIndex < FHeight then
3074 FStartLine := 0
3075 else
3076 FStartLine := Min(FIndex, Length(FItems)-FHeight);
3077 end;
3079 procedure TGUIListBox.FSetIndex(aIndex: Integer);
3080 begin
3081 if FItems = nil then
3082 Exit;
3084 if (aIndex < 0) or (aIndex > High(FItems)) then
3085 Exit;
3087 FIndex := aIndex;
3089 if FIndex <= FHeight then
3090 FStartLine := 0
3091 else
3092 FStartLine := Min(FIndex, Length(FItems)-FHeight);
3093 end;
3095 { TGUIFileListBox }
3097 procedure TGUIFileListBox.OnMessage(var Msg: TMessage);
3098 var
3099 a: Integer;
3100 begin
3101 if not FEnabled then
3102 Exit;
3104 if FItems = nil then
3105 Exit;
3107 with Msg do
3108 case Msg of
3109 WM_KEYDOWN:
3110 case wParam of
3111 IK_HOME, IK_KPHOME:
3112 begin
3113 FIndex := 0;
3114 FStartLine := 0;
3115 if @FOnChangeEvent <> nil then
3116 FOnChangeEvent(Self);
3117 end;
3119 IK_END, IK_KPEND:
3120 begin
3121 FIndex := High(FItems);
3122 FStartLine := Max(High(FItems)-FHeight+1, 0);
3123 if @FOnChangeEvent <> nil then
3124 FOnChangeEvent(Self);
3125 end;
3127 IK_PAGEUP, IK_KPPAGEUP:
3128 begin
3129 if FIndex > FHeight then
3130 FIndex := FIndex-FHeight
3131 else
3132 FIndex := 0;
3134 if FStartLine > FHeight then
3135 FStartLine := FStartLine-FHeight
3136 else
3137 FStartLine := 0;
3138 end;
3140 IK_PAGEDN, IK_KPPAGEDN:
3141 begin
3142 if FIndex < High(FItems)-FHeight then
3143 FIndex := FIndex+FHeight
3144 else
3145 FIndex := High(FItems);
3147 if FStartLine < High(FItems)-FHeight then
3148 FStartLine := FStartLine+FHeight
3149 else
3150 FStartLine := High(FItems)-FHeight+1;
3151 end;
3153 IK_UP, IK_LEFT, IK_KPUP, IK_KPLEFT:
3154 if FIndex > 0 then
3155 begin
3156 Dec(FIndex);
3157 if FIndex < FStartLine then
3158 Dec(FStartLine);
3159 if @FOnChangeEvent <> nil then
3160 FOnChangeEvent(Self);
3161 end;
3163 IK_DOWN, IK_RIGHT, IK_KPDOWN, IK_KPRIGHT:
3164 if FIndex < High(FItems) then
3165 begin
3166 Inc(FIndex);
3167 if FIndex > FStartLine+FHeight-1 then
3168 Inc(FStartLine);
3169 if @FOnChangeEvent <> nil then
3170 FOnChangeEvent(Self);
3171 end;
3173 IK_RETURN, IK_KPRETURN:
3174 with FWindow do
3175 begin
3176 if FActiveControl <> Self then
3177 SetActive(Self)
3178 else
3179 begin
3180 if FItems[FIndex][1] = #29 then // Ïàïêà
3181 begin
3182 OpenDir(FPath+Copy(FItems[FIndex], 2, 255));
3183 FIndex := 0;
3184 Exit;
3185 end;
3187 if FDefControl <> '' then
3188 SetActive(GetControl(FDefControl))
3189 else
3190 SetActive(nil);
3191 end;
3192 end;
3193 end;
3195 WM_CHAR:
3196 for a := 0 to High(FItems) do
3197 if ( (Length(FItems[a]) > 0) and
3198 (LowerCase(FItems[a][1]) = LowerCase(Chr(wParam))) ) or
3199 ( (Length(FItems[a]) > 1) and
3200 (FItems[a][1] = #29) and // Ïàïêà
3201 (LowerCase(FItems[a][2]) = LowerCase(Chr(wParam))) ) then
3202 begin
3203 FIndex := a;
3204 FStartLine := Min(Max(FIndex-1, 0), Length(FItems)-FHeight);
3205 if @FOnChangeEvent <> nil then
3206 FOnChangeEvent(Self);
3207 Break;
3208 end;
3209 end;
3210 end;
3212 procedure TGUIFileListBox.OpenDir(path: String);
3213 var
3214 SR: TSearchRec;
3215 i: Integer;
3216 sm, sc: string;
3217 begin
3218 Clear();
3220 path := IncludeTrailingPathDelimiter(path);
3221 path := ExpandFileName(path);
3223 // Êàòàëîãè:
3224 if FDirs then
3225 begin
3226 if FindFirst(path+'*', faDirectory, SR) = 0 then
3227 repeat
3228 if not LongBool(SR.Attr and faDirectory) then
3229 Continue;
3230 if (SR.Name = '.') or
3231 ((SR.Name = '..') and (path = ExpandFileName(FBasePath))) then
3232 Continue;
3234 AddItem(#1 + SR.Name);
3235 until FindNext(SR) <> 0;
3237 FindClose(SR);
3238 end;
3240 // Ôàéëû:
3241 sm := FFileMask;
3242 while sm <> '' do
3243 begin
3244 i := Pos('|', sm);
3245 if i = 0 then i := length(sm)+1;
3246 sc := Copy(sm, 1, i-1);
3247 Delete(sm, 1, i);
3248 if FindFirst(path+sc, faAnyFile, SR) = 0 then repeat AddItem(SR.Name); until FindNext(SR) <> 0;
3249 FindClose(SR);
3250 end;
3252 for i := 0 to High(FItems) do
3253 if FItems[i][1] = #1 then
3254 FItems[i][1] := #29;
3256 FPath := path;
3257 end;
3259 procedure TGUIFileListBox.SetBase(path: String);
3260 begin
3261 FBasePath := path;
3262 OpenDir(FBasePath);
3263 end;
3265 function TGUIFileListBox.SelectedItem(): String;
3266 begin
3267 Result := '';
3269 if (FIndex = -1) or (FItems = nil) or
3270 (FIndex > High(FItems)) or
3271 (FItems[FIndex][1] = '/') or
3272 (FItems[FIndex][1] = '\') then
3273 Exit;
3275 Result := FPath + FItems[FIndex];
3276 end;
3278 procedure TGUIFileListBox.UpdateFileList();
3279 var
3280 fn: String;
3281 begin
3282 if (FIndex = -1) or (FItems = nil) or
3283 (FIndex > High(FItems)) or
3284 (FItems[FIndex][1] = '/') or
3285 (FItems[FIndex][1] = '\') then
3286 fn := ''
3287 else
3288 fn := FItems[FIndex];
3290 OpenDir(FPath);
3292 if fn <> '' then
3293 SelectItem(fn);
3294 end;
3296 { TGUIMemo }
3298 procedure TGUIMemo.Clear;
3299 begin
3300 FLines := nil;
3301 FStartLine := 0;
3302 end;
3304 constructor TGUIMemo.Create(FontID: DWORD; Width, Height: Word);
3305 begin
3306 inherited Create();
3308 FFont := TFont.Create(FontID, FONT_CHAR);
3310 FWidth := Width;
3311 FHeight := Height;
3312 FDrawBack := True;
3313 FDrawScroll := True;
3314 end;
3316 procedure TGUIMemo.Draw;
3317 var
3318 a: Integer;
3319 begin
3320 inherited;
3322 if FDrawBack then DrawBox(FX, FY, FWidth+1, FHeight);
3323 if FDrawScroll then
3324 DrawScroll(FX+4+FWidth*16, FY+4, FHeight, (FStartLine > 0) and (FLines <> nil),
3325 (FStartLine+FHeight-1 < High(FLines)) and (FLines <> nil));
3327 if FLines <> nil then
3328 for a := FStartLine to Min(High(FLines), FStartLine+FHeight-1) do
3329 FFont.Draw(FX+4, FY+4+(a-FStartLine)*16, FLines[a], FColor.R, FColor.G, FColor.B);
3330 end;
3332 function TGUIMemo.GetHeight: Integer;
3333 begin
3334 Result := 8+FHeight*16;
3335 end;
3337 function TGUIMemo.GetWidth: Integer;
3338 begin
3339 Result := 8+(FWidth+1)*16;
3340 end;
3342 procedure TGUIMemo.OnMessage(var Msg: TMessage);
3343 begin
3344 if not FEnabled then Exit;
3346 inherited;
3348 if FLines = nil then Exit;
3350 with Msg do
3351 case Msg of
3352 WM_KEYDOWN:
3353 case wParam of
3354 IK_UP, IK_LEFT, IK_KPUP, IK_KPLEFT:
3355 if FStartLine > 0 then
3356 Dec(FStartLine);
3357 IK_DOWN, IK_RIGHT, IK_KPDOWN, IK_KPRIGHT:
3358 if FStartLine < Length(FLines)-FHeight then
3359 Inc(FStartLine);
3360 IK_RETURN, IK_KPRETURN:
3361 with FWindow do
3362 begin
3363 if FActiveControl <> Self then
3364 begin
3365 SetActive(Self);
3366 {FStartLine := 0;}
3367 end
3368 else
3369 if FDefControl <> '' then SetActive(GetControl(FDefControl))
3370 else SetActive(nil);
3371 end;
3372 end;
3373 end;
3374 end;
3376 procedure TGUIMemo.SetText(Text: string);
3377 begin
3378 FStartLine := 0;
3379 FLines := GetLines(Text, FFont.ID, FWidth*16);
3380 end;
3382 { TGUIimage }
3384 procedure TGUIimage.ClearImage();
3385 begin
3386 if FImageRes = '' then Exit;
3388 g_Texture_Delete(FImageRes);
3389 FImageRes := '';
3390 end;
3392 constructor TGUIimage.Create();
3393 begin
3394 inherited Create();
3396 FImageRes := '';
3397 end;
3399 destructor TGUIimage.Destroy();
3400 begin
3401 inherited;
3402 end;
3404 procedure TGUIimage.Draw();
3405 var
3406 ID: DWORD;
3407 begin
3408 inherited;
3410 if FImageRes = '' then
3411 begin
3412 if g_Texture_Get(FDefaultRes, ID) then e_Draw(ID, FX, FY, 0, True, False);
3413 end
3414 else
3415 if g_Texture_Get(FImageRes, ID) then e_Draw(ID, FX, FY, 0, True, False);
3416 end;
3418 procedure TGUIimage.OnMessage(var Msg: TMessage);
3419 begin
3420 inherited;
3421 end;
3423 procedure TGUIimage.SetImage(Res: string);
3424 begin
3425 ClearImage();
3427 if g_Texture_CreateWADEx(Res, Res) then FImageRes := Res;
3428 end;
3430 procedure TGUIimage.Update();
3431 begin
3432 inherited;
3433 end;
3435 end.