DEADSOFTWARE

7acbf0b101213d9203f4c9562aa20bf4c868523c
[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;
86 TOnKeyDownEvent = procedure(Key: Byte);
87 TOnCloseEvent = procedure;
88 TOnShowEvent = procedure;
89 TOnClickEvent = procedure;
90 TOnChangeEvent = procedure(Sender: TGUIControl);
91 TOnEnterEvent = procedure(Sender: TGUIControl);
93 TGUIWindow = class;
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 FOnCloseEvent: TOnCloseEvent;
122 FOnShowEvent: TOnShowEvent;
123 public
124 Childs: array of TGUIControl;
125 constructor Create(Name: string);
126 destructor Destroy; override;
127 function AddChild(Child: TGUIControl): TGUIControl;
128 procedure OnMessage(var Msg: TMessage);
129 procedure Update;
130 procedure Draw;
131 procedure SetActive(Control: TGUIControl);
132 function GetControl(Name: string): TGUIControl;
133 property OnKeyDown: TOnKeyDownEvent read FOnKeyDown write FOnKeyDown;
134 property OnClose: TOnCloseEvent read FOnCloseEvent write FOnCloseEvent;
135 property OnShow: TOnShowEvent read FOnShowEvent write FOnShowEvent;
136 property Name: string read FName;
137 property DefControl: string read FDefControl write FDefControl;
138 property BackTexture: string read FBackTexture write FBackTexture;
139 property MainWindow: Boolean read FMainWindow write FMainWindow;
140 end;
142 TGUITextButton = class(TGUIControl)
143 private
144 FText: string;
145 FColor: TRGB;
146 FFont: TFont;
147 FSound: string;
148 FShowWindow: string;
149 public
150 Proc: procedure;
151 constructor Create(Proc: Pointer; FontID: DWORD; Text: string);
152 destructor Destroy(); override;
153 procedure OnMessage(var Msg: TMessage); override;
154 procedure Update(); override;
155 procedure Draw(); override;
156 function GetWidth(): Integer;
157 function GetHeight(): Integer;
158 procedure Click(Silent: Boolean = False);
159 property Caption: string read FText write FText;
160 property Color: TRGB read FColor write FColor;
161 property Font: TFont read FFont write FFont;
162 property ShowWindow: string read FShowWindow write FShowWindow;
163 end;
165 TGUILabel = class(TGUIControl)
166 private
167 FText: string;
168 FColor: TRGB;
169 FFont: TFont;
170 FFixedLen: Word;
171 FOnClickEvent: TOnClickEvent;
172 public
173 constructor Create(Text: string; FontID: DWORD);
174 procedure OnMessage(var Msg: TMessage); override;
175 procedure Draw; override;
176 function GetWidth: Integer;
177 function GetHeight: Integer;
178 property OnClick: TOnClickEvent read FOnClickEvent write FOnClickEvent;
179 property FixedLength: Word read FFixedLen write FFixedLen;
180 property Text: string read FText write FText;
181 property Color: TRGB read FColor write FColor;
182 property Font: TFont read FFont write FFont;
183 end;
185 TGUIScroll = class(TGUIControl)
186 private
187 FValue: Integer;
188 FMax: Word;
189 FLeftID: DWORD;
190 FRightID: DWORD;
191 FMiddleID: DWORD;
192 FMarkerID: DWORD;
193 FOnChangeEvent: TOnChangeEvent;
194 procedure FSetValue(a: Integer);
195 public
196 constructor Create();
197 procedure OnMessage(var Msg: TMessage); override;
198 procedure Update; override;
199 procedure Draw; override;
200 function GetWidth(): Word;
201 property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent;
202 property Max: Word read FMax write FMax;
203 property Value: Integer read FValue write FSetValue;
204 end;
206 TGUISwitch = class(TGUIControl)
207 private
208 FFont: TFont;
209 FItems: array of string;
210 FIndex: Integer;
211 FColor: TRGB;
212 FOnChangeEvent: TOnChangeEvent;
213 public
214 constructor Create(FontID: DWORD);
215 procedure OnMessage(var Msg: TMessage); override;
216 procedure AddItem(Item: string);
217 procedure Update; override;
218 procedure Draw; override;
219 function GetWidth(): Word;
220 function GetText: string;
221 property ItemIndex: Integer read FIndex write FIndex;
222 property Color: TRGB read FColor write FColor;
223 property Font: TFont read FFont write FFont;
224 property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent;
225 end;
227 TGUIEdit = class(TGUIControl)
228 private
229 FFont: TFont;
230 FCaretPos: Integer;
231 FMaxLength: Word;
232 FWidth: Word;
233 FText: string;
234 FColor: TRGB;
235 FOnlyDigits: Boolean;
236 FLeftID: DWORD;
237 FRightID: DWORD;
238 FMiddleID: DWORD;
239 FOnChangeEvent: TOnChangeEvent;
240 FOnEnterEvent: TOnEnterEvent;
241 procedure SetText(Text: string);
242 public
243 constructor Create(FontID: DWORD);
244 procedure OnMessage(var Msg: TMessage); override;
245 procedure Update; override;
246 procedure Draw; override;
247 function GetWidth(): Word;
248 property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent;
249 property OnEnter: TOnEnterEvent read FOnEnterEvent write FOnEnterEvent;
250 property Width: Word read FWidth write FWidth;
251 property MaxLength: Word read FMaxLength write FMaxLength;
252 property OnlyDigits: Boolean read FOnlyDigits write FOnlyDigits;
253 property Text: string read FText write SetText;
254 property Color: TRGB read FColor write FColor;
255 property Font: TFont read FFont write FFont;
256 end;
258 TGUIKeyRead = class(TGUIControl)
259 private
260 FFont: TFont;
261 FColor: TRGB;
262 FKey: Word;
263 FIsQuery: Boolean;
264 public
265 constructor Create(FontID: DWORD);
266 procedure OnMessage(var Msg: TMessage); override;
267 procedure Draw; override;
268 function GetWidth(): Word;
269 property Key: Word read FKey write FKey;
270 property Color: TRGB read FColor write FColor;
271 property Font: TFont read FFont write FFont;
272 end;
274 TGUIModelView = class(TGUIControl)
275 private
276 FModel: TPlayerModel;
277 a: Boolean;
278 public
279 constructor Create;
280 destructor Destroy; override;
281 procedure OnMessage(var Msg: TMessage); override;
282 procedure SetModel(ModelName: string);
283 procedure SetColor(Red, Green, Blue: Byte);
284 procedure NextAnim();
285 procedure NextWeapon();
286 procedure Update; override;
287 procedure Draw; override;
288 property Model: TPlayerModel read FModel;
289 end;
291 TPreviewPanel = record
292 X1, Y1, X2, Y2: Integer;
293 PanelType: Word;
294 end;
296 TGUIMapPreview = class(TGUIControl)
297 private
298 FMapData: array of TPreviewPanel;
299 FMapSize: TPoint;
300 FScale: Single;
301 public
302 constructor Create();
303 destructor Destroy(); override;
304 procedure OnMessage(var Msg: TMessage); override;
305 procedure SetMap(Res: string);
306 procedure ClearMap();
307 procedure Update(); override;
308 procedure Draw(); override;
309 function GetScaleStr: String;
310 end;
312 TGUIImage = class(TGUIControl)
313 private
314 FImageRes: string;
315 FDefaultRes: string;
316 public
317 constructor Create();
318 destructor Destroy(); override;
319 procedure OnMessage(var Msg: TMessage); override;
320 procedure SetImage(Res: string);
321 procedure ClearImage();
322 procedure Update(); override;
323 procedure Draw(); override;
324 property DefaultRes: string read FDefaultRes write FDefaultRes;
325 end;
327 TGUIListBox = class(TGUIControl)
328 private
329 FItems: SArray;
330 FActiveColor: TRGB;
331 FUnActiveColor: TRGB;
332 FFont: TFont;
333 FStartLine: Integer;
334 FIndex: Integer;
335 FWidth: Word;
336 FHeight: Word;
337 FSort: Boolean;
338 FDrawBack: Boolean;
339 FDrawScroll: Boolean;
340 FOnChangeEvent: TOnChangeEvent;
342 procedure FSetItems(Items: SArray);
343 procedure FSetIndex(aIndex: Integer);
345 public
346 constructor Create(FontID: DWORD; Width, Height: Word);
347 procedure OnMessage(var Msg: TMessage); override;
348 procedure Draw(); override;
349 procedure AddItem(Item: String);
350 procedure SelectItem(Item: String);
351 procedure Clear();
352 function GetWidth(): Word;
353 function GetHeight(): Word;
354 function SelectedItem(): String;
356 property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent;
357 property Sort: Boolean read FSort write FSort;
358 property ItemIndex: Integer read FIndex write FSetIndex;
359 property Items: SArray read FItems write FSetItems;
360 property DrawBack: Boolean read FDrawBack write FDrawBack;
361 property DrawScrollBar: Boolean read FDrawScroll write FDrawScroll;
362 property ActiveColor: TRGB read FActiveColor write FActiveColor;
363 property UnActiveColor: TRGB read FUnActiveColor write FUnActiveColor;
364 property Font: TFont read FFont write FFont;
365 end;
367 TGUIFileListBox = class (TGUIListBox)
368 private
369 FBasePath: String;
370 FPath: String;
371 FFileMask: String;
372 FDirs: Boolean;
374 procedure OpenDir(path: String);
376 public
377 procedure OnMessage(var Msg: TMessage); override;
378 procedure SetBase(path: String);
379 function SelectedItem(): String;
380 procedure UpdateFileList();
382 property Dirs: Boolean read FDirs write FDirs;
383 property FileMask: String read FFileMask write FFileMask;
384 property Path: String read FPath;
385 end;
387 TGUIMemo = class(TGUIControl)
388 private
389 FLines: SArray;
390 FFont: TFont;
391 FStartLine: Integer;
392 FWidth: Word;
393 FHeight: Word;
394 FColor: TRGB;
395 FDrawBack: Boolean;
396 FDrawScroll: Boolean;
397 public
398 constructor Create(FontID: DWORD; Width, Height: Word);
399 procedure OnMessage(var Msg: TMessage); override;
400 procedure Draw; override;
401 procedure Clear;
402 function GetWidth(): Word;
403 function GetHeight(): Word;
404 procedure SetText(Text: string);
405 property DrawBack: Boolean read FDrawBack write FDrawBack;
406 property DrawScrollBar: Boolean read FDrawScroll write FDrawScroll;
407 property Color: TRGB read FColor write FColor;
408 property Font: TFont read FFont write FFont;
409 end;
411 TGUIMainMenu = class(TGUIControl)
412 private
413 FButtons: array of TGUITextButton;
414 FHeader: TGUILabel;
415 FIndex: Integer;
416 FFontID: DWORD;
417 FCounter: Byte;
418 FMarkerID1: DWORD;
419 FMarkerID2: DWORD;
420 public
421 constructor Create(FontID: DWORD; Header: string);
422 destructor Destroy; override;
423 procedure OnMessage(var Msg: TMessage); override;
424 function AddButton(fProc: Pointer; Caption: string; ShowWindow: string = ''): TGUITextButton;
425 function GetButton(Name: string): TGUITextButton;
426 procedure EnableButton(Name: string; e: Boolean);
427 procedure AddSpace();
428 procedure Update; override;
429 procedure Draw; override;
430 end;
432 TControlType = class of TGUIControl;
434 PMenuItem = ^TMenuItem;
435 TMenuItem = record
436 Text: TGUILabel;
437 ControlType: TControlType;
438 Control: TGUIControl;
439 end;
441 TGUIMenu = class(TGUIControl)
442 private
443 FItems: array of TMenuItem;
444 FHeader: TGUILabel;
445 FIndex: Integer;
446 FFontID: DWORD;
447 FCounter: Byte;
448 FAlign: Boolean;
449 FLeft: Integer;
450 function NewItem(): Integer;
451 public
452 constructor Create(HeaderFont, ItemsFont: DWORD; Header: string);
453 destructor Destroy; override;
454 procedure OnMessage(var Msg: TMessage); override;
455 procedure AddSpace();
456 procedure AddLine(fText: string);
457 procedure AddText(fText: string; MaxWidth: Word);
458 function AddLabel(fText: string): TGUILabel;
459 function AddButton(Proc: Pointer; fText: string; _ShowWindow: string = ''): TGUITextButton;
460 function AddScroll(fText: string): TGUIScroll;
461 function AddSwitch(fText: string): TGUISwitch;
462 function AddEdit(fText: string): TGUIEdit;
463 function AddKeyRead(fText: string): TGUIKeyRead;
464 function AddList(fText: string; Width, Height: Word): TGUIListBox;
465 function AddFileList(fText: string; Width, Height: Word): TGUIFileListBox;
466 function AddMemo(fText: string; Width, Height: Word): TGUIMemo;
467 procedure ReAlign();
468 function GetControl(Name: string): TGUIControl;
469 function GetControlsText(Name: string): TGUILabel;
470 procedure Draw; override;
471 procedure Update; override;
472 procedure UpdateIndex();
473 property Align: Boolean read FAlign write FAlign;
474 property Left: Integer read FLeft write FLeft;
475 end;
477 var
478 g_GUIWindows: array of TGUIWindow;
479 g_ActiveWindow: TGUIWindow = nil;
481 procedure g_GUI_Init();
482 function g_GUI_AddWindow(Window: TGUIWindow): TGUIWindow;
483 function g_GUI_GetWindow(Name: string): TGUIWindow;
484 procedure g_GUI_ShowWindow(Name: string);
485 procedure g_GUI_HideWindow(PlaySound: Boolean = True);
486 function g_GUI_Destroy(): Boolean;
487 procedure g_GUI_SaveMenuPos();
488 procedure g_GUI_LoadMenuPos();
490 implementation
492 uses
493 GL, GLExt, g_textures, g_sound, SysUtils,
494 g_game, Math, StrUtils, g_player, g_options, MAPREADER,
495 g_map, MAPDEF, g_weapons;
497 var
498 Box: Array [0..8] of DWORD;
499 Saved_Windows: SArray;
501 procedure g_GUI_Init();
502 begin
503 g_Texture_Get(BOX1, Box[0]);
504 g_Texture_Get(BOX2, Box[1]);
505 g_Texture_Get(BOX3, Box[2]);
506 g_Texture_Get(BOX4, Box[3]);
507 g_Texture_Get(BOX5, Box[4]);
508 g_Texture_Get(BOX6, Box[5]);
509 g_Texture_Get(BOX7, Box[6]);
510 g_Texture_Get(BOX8, Box[7]);
511 g_Texture_Get(BOX9, Box[8]);
512 end;
514 function g_GUI_Destroy(): Boolean;
515 var
516 i: Integer;
517 begin
518 Result := (Length(g_GUIWindows) > 0);
520 for i := 0 to High(g_GUIWindows) do
521 g_GUIWindows[i].Free();
523 g_GUIWindows := nil;
524 g_ActiveWindow := nil;
525 end;
527 function g_GUI_AddWindow(Window: TGUIWindow): TGUIWindow;
528 begin
529 SetLength(g_GUIWindows, Length(g_GUIWindows)+1);
530 g_GUIWindows[High(g_GUIWindows)] := Window;
532 Result := Window;
533 end;
535 function g_GUI_GetWindow(Name: string): TGUIWindow;
536 var
537 i: Integer;
538 begin
539 Result := nil;
541 if g_GUIWindows <> nil then
542 for i := 0 to High(g_GUIWindows) do
543 if g_GUIWindows[i].FName = Name then
544 begin
545 Result := g_GUIWindows[i];
546 Break;
547 end;
549 Assert(Result <> nil, 'GUI_Window "'+Name+'" not found');
550 end;
552 procedure g_GUI_ShowWindow(Name: string);
553 var
554 i: Integer;
555 begin
556 if g_GUIWindows = nil then
557 Exit;
559 for i := 0 to High(g_GUIWindows) do
560 if g_GUIWindows[i].FName = Name then
561 begin
562 g_GUIWindows[i].FPrevWindow := g_ActiveWindow;
563 g_ActiveWindow := g_GUIWindows[i];
565 if g_ActiveWindow.MainWindow then
566 g_ActiveWindow.FPrevWindow := nil;
568 if g_ActiveWindow.FDefControl <> '' then
569 g_ActiveWindow.SetActive(g_ActiveWindow.GetControl(g_ActiveWindow.FDefControl))
570 else
571 g_ActiveWindow.SetActive(nil);
573 if @g_ActiveWindow.FOnShowEvent <> nil then
574 g_ActiveWindow.FOnShowEvent();
576 Break;
577 end;
578 end;
580 procedure g_GUI_HideWindow(PlaySound: Boolean = True);
581 begin
582 if g_ActiveWindow <> nil then
583 begin
584 if @g_ActiveWindow.OnClose <> nil then
585 g_ActiveWindow.OnClose();
586 g_ActiveWindow := g_ActiveWindow.FPrevWindow;
587 if PlaySound then
588 g_Sound_PlayEx(WINDOW_CLOSESOUND);
589 end;
590 end;
592 procedure g_GUI_SaveMenuPos();
593 var
594 len: Integer;
595 win: TGUIWindow;
596 begin
597 SetLength(Saved_Windows, 0);
598 win := g_ActiveWindow;
600 while win <> nil do
601 begin
602 len := Length(Saved_Windows);
603 SetLength(Saved_Windows, len + 1);
605 Saved_Windows[len] := win.Name;
607 if win.MainWindow then
608 win := nil
609 else
610 win := win.FPrevWindow;
611 end;
612 end;
614 procedure g_GUI_LoadMenuPos();
615 var
616 i, j, k, len: Integer;
617 ok: Boolean;
618 begin
619 g_ActiveWindow := nil;
620 len := Length(Saved_Windows);
622 if len = 0 then
623 Exit;
625 // Îêíî ñ ãëàâíûì ìåíþ:
626 g_GUI_ShowWindow(Saved_Windows[len-1]);
628 // Íå ïåðåêëþ÷èëîñü (èëè íåêóäà äàëüøå):
629 if (len = 1) or (g_ActiveWindow = nil) then
630 Exit;
632 // Èùåì êíîïêè â îñòàëüíûõ îêíàõ:
633 for k := len-1 downto 1 do
634 begin
635 ok := False;
637 for i := 0 to Length(g_ActiveWindow.Childs)-1 do
638 begin
639 if g_ActiveWindow.Childs[i] is TGUIMainMenu then
640 begin // GUI_MainMenu
641 with TGUIMainMenu(g_ActiveWindow.Childs[i]) do
642 for j := 0 to Length(FButtons)-1 do
643 if FButtons[j].ShowWindow = Saved_Windows[k-1] then
644 begin
645 FButtons[j].Click(True);
646 ok := True;
647 Break;
648 end;
649 end
650 else // GUI_Menu
651 if g_ActiveWindow.Childs[i] is TGUIMenu then
652 with TGUIMenu(g_ActiveWindow.Childs[i]) do
653 for j := 0 to Length(FItems)-1 do
654 if FItems[j].ControlType = TGUITextButton then
655 if TGUITextButton(FItems[j].Control).ShowWindow = Saved_Windows[k-1] then
656 begin
657 TGUITextButton(FItems[j].Control).Click(True);
658 ok := True;
659 Break;
660 end;
662 if ok then
663 Break;
664 end;
666 // Íå ïåðåêëþ÷èëîñü:
667 if (not ok) or
668 (g_ActiveWindow.Name = Saved_Windows[k]) then
669 Break;
670 end;
671 end;
673 procedure DrawBox(X, Y: Integer; Width, Height: Word);
674 begin
675 e_Draw(Box[0], X, Y, 0, False, False);
676 e_DrawFill(Box[1], X+4, Y, Width*4, 1, 0, False, False);
677 e_Draw(Box[2], X+4+Width*16, Y, 0, False, False);
678 e_DrawFill(Box[3], X, Y+4, 1, Height*4, 0, False, False);
679 e_DrawFill(Box[4], X+4, Y+4, Width, Height, 0, False, False);
680 e_DrawFill(Box[5], X+4+Width*16, Y+4, 1, Height*4, 0, False, False);
681 e_Draw(Box[6], X, Y+4+Height*16, 0, False, False);
682 e_DrawFill(Box[7], X+4, Y+4+Height*16, Width*4, 1, 0, False, False);
683 e_Draw(Box[8], X+4+Width*16, Y+4+Height*16, 0, False, False);
684 end;
686 procedure DrawScroll(X, Y: Integer; Height: Word; Up, Down: Boolean);
687 var
688 ID: DWORD;
689 begin
690 if Height < 3 then Exit;
692 if Up then
693 g_Texture_Get(BSCROLL_UPA, ID)
694 else
695 g_Texture_Get(BSCROLL_UPU, ID);
696 e_Draw(ID, X, Y, 0, False, False);
698 if Down then
699 g_Texture_Get(BSCROLL_DOWNA, ID)
700 else
701 g_Texture_Get(BSCROLL_DOWNU, ID);
702 e_Draw(ID, X, Y+(Height-1)*16, 0, False, False);
704 g_Texture_Get(BSCROLL_MIDDLE, ID);
705 e_DrawFill(ID, X, Y+16, 1, Height-2, 0, False, False);
706 end;
708 { TGUIWindow }
710 constructor TGUIWindow.Create(Name: string);
711 begin
712 Childs := nil;
713 FActiveControl := nil;
714 FName := Name;
715 FOnKeyDown := nil;
716 FOnCloseEvent := nil;
717 FOnShowEvent := nil;
718 end;
720 destructor TGUIWindow.Destroy;
721 var
722 i: Integer;
723 begin
724 if Childs = nil then
725 Exit;
727 for i := 0 to High(Childs) do
728 Childs[i].Free();
729 end;
731 function TGUIWindow.AddChild(Child: TGUIControl): TGUIControl;
732 begin
733 Child.FWindow := Self;
735 SetLength(Childs, Length(Childs) + 1);
736 Childs[High(Childs)] := Child;
738 Result := Child;
739 end;
741 procedure TGUIWindow.Update;
742 var
743 i: Integer;
744 begin
745 for i := 0 to High(Childs) do
746 if Childs[i] <> nil then Childs[i].Update;
747 end;
749 procedure TGUIWindow.Draw;
750 var
751 i: Integer;
752 ID: DWORD;
753 begin
754 if FBackTexture <> '' then
755 if g_Texture_Get(FBackTexture, ID) then
756 e_DrawSize(ID, 0, 0, 0, False, False, gScreenWidth, gScreenHeight)
757 else
758 e_Clear(GL_COLOR_BUFFER_BIT, 0.5, 0.5, 0.5);
760 for i := 0 to High(Childs) do
761 if Childs[i] <> nil then Childs[i].Draw;
762 end;
764 procedure TGUIWindow.OnMessage(var Msg: TMessage);
765 begin
766 if FActiveControl <> nil then FActiveControl.OnMessage(Msg);
767 if @FOnKeyDown <> nil then FOnKeyDown(Msg.wParam);
769 if Msg.Msg = WM_KEYDOWN then
770 if Msg.wParam = IK_ESCAPE then
771 begin
772 g_GUI_HideWindow;
773 Exit;
774 end;
775 end;
777 procedure TGUIWindow.SetActive(Control: TGUIControl);
778 begin
779 FActiveControl := Control;
780 end;
782 function TGUIWindow.GetControl(Name: String): TGUIControl;
783 var
784 i: Integer;
785 begin
786 Result := nil;
788 if Childs <> nil then
789 for i := 0 to High(Childs) do
790 if Childs[i] <> nil then
791 if LowerCase(Childs[i].FName) = LowerCase(Name) then
792 begin
793 Result := Childs[i];
794 Break;
795 end;
797 Assert(Result <> nil, 'Window Control "'+Name+'" not Found!');
798 end;
800 { TGUIControl }
802 constructor TGUIControl.Create();
803 begin
804 FX := 0;
805 FY := 0;
807 FEnabled := True;
808 end;
810 procedure TGUIControl.OnMessage(var Msg: TMessage);
811 begin
812 if not FEnabled then
813 Exit;
814 end;
816 procedure TGUIControl.Update();
817 begin
819 end;
821 procedure TGUIControl.Draw();
822 begin
824 end;
826 { TGUITextButton }
828 procedure TGUITextButton.Click(Silent: Boolean = False);
829 begin
830 if (FSound <> '') and (not Silent) then
831 g_Sound_PlayEx(FSound);
833 if @Proc <> nil then
834 Proc();
835 if FShowWindow <> '' then
836 g_GUI_ShowWindow(FShowWindow);
837 end;
839 constructor TGUITextButton.Create(Proc: Pointer; FontID: DWORD; Text: string);
840 begin
841 inherited Create();
843 Self.Proc := Proc;
845 FFont := TFont.Create(FontID, FONT_CHAR);
847 FText := Text;
848 end;
850 destructor TGUITextButton.Destroy;
851 begin
853 inherited;
854 end;
856 procedure TGUITextButton.Draw;
857 begin
858 FFont.Draw(FX, FY, FText, FColor.R, FColor.G, FColor.B)
859 end;
861 function TGUITextButton.GetHeight: Integer;
862 var
863 w, h: Word;
864 begin
865 FFont.GetTextSize(FText, w, h);
866 Result := h;
867 end;
869 function TGUITextButton.GetWidth: Integer;
870 var
871 w, h: Word;
872 begin
873 FFont.GetTextSize(FText, w, h);
874 Result := w;
875 end;
877 procedure TGUITextButton.OnMessage(var Msg: TMessage);
878 begin
879 if not FEnabled then Exit;
881 inherited;
883 case Msg.Msg of
884 WM_KEYDOWN:
885 case Msg.wParam of
886 IK_RETURN, IK_KPRETURN: Click();
887 end;
888 end;
889 end;
891 procedure TGUITextButton.Update;
892 begin
893 inherited;
894 end;
896 { TFont }
898 constructor TFont.Create(FontID: DWORD; FontType: TFontType);
899 begin
900 ID := FontID;
902 FScale := 1;
903 FFontType := FontType;
904 end;
906 destructor TFont.Destroy;
907 begin
909 inherited;
910 end;
912 procedure TFont.Draw(X, Y: Integer; Text: string; R, G, B: Byte);
913 begin
914 if FFontType = FONT_CHAR then e_CharFont_PrintEx(ID, X, Y, Text, _RGB(R, G, B), FScale)
915 else e_TextureFontPrintEx(X, Y, Text, ID, R, G, B, FScale);
916 end;
918 procedure TFont.GetTextSize(Text: string; var w, h: Word);
919 var
920 cw, ch: Byte;
921 begin
922 if FFontType = FONT_CHAR then e_CharFont_GetSize(ID, Text, w, h)
923 else
924 begin
925 e_TextureFontGetSize(ID, cw, ch);
926 w := cw*Length(Text);
927 h := ch;
928 end;
930 w := Round(w*FScale);
931 h := Round(h*FScale);
932 end;
934 { TGUIMainMenu }
936 function TGUIMainMenu.AddButton(fProc: Pointer; Caption: string; ShowWindow: string = ''): TGUITextButton;
937 var
938 a, _x: Integer;
939 h, hh: Word;
940 begin
941 FIndex := 0;
943 SetLength(FButtons, Length(FButtons)+1);
944 FButtons[High(FButtons)] := TGUITextButton.Create(fProc, FFontID, Caption);
945 FButtons[High(FButtons)].ShowWindow := ShowWindow;
946 with FButtons[High(FButtons)] do
947 begin
948 if (fProc <> nil) or (ShowWindow <> '') then FColor := MAINMENU_ITEMS_COLOR
949 else FColor := MAINMENU_UNACTIVEITEMS_COLOR;
950 FSound := MAINMENU_CLICKSOUND;
951 end;
953 _x := gScreenWidth div 2;
955 for a := 0 to High(FButtons) do
956 if FButtons[a] <> nil then
957 _x := Min(_x, (gScreenWidth div 2)-(FButtons[a].GetWidth div 2));
959 hh := FHeader.GetHeight;
961 h := hh*(2+Length(FButtons))+MAINMENU_SPACE*(Length(FButtons)-1);
962 h := (gScreenHeight div 2)-(h div 2);
964 with FHeader do
965 begin
966 FX := _x;
967 FY := h;
968 end;
970 Inc(h, hh*2);
972 for a := 0 to High(FButtons) do
973 begin
974 if FButtons[a] <> nil then
975 with FButtons[a] do
976 begin
977 FX := _x;
978 FY := h;
979 end;
981 Inc(h, hh+MAINMENU_SPACE);
982 end;
984 Result := FButtons[High(FButtons)];
985 end;
987 procedure TGUIMainMenu.AddSpace;
988 begin
989 SetLength(FButtons, Length(FButtons)+1);
990 FButtons[High(FButtons)] := nil;
991 end;
993 constructor TGUIMainMenu.Create(FontID: DWORD; Header: string);
994 begin
995 inherited Create();
997 FIndex := -1;
998 FFontID := FontID;
999 FCounter := MAINMENU_MARKERDELAY;
1001 g_Texture_Get(MAINMENU_MARKER1, FMarkerID1);
1002 g_Texture_Get(MAINMENU_MARKER2, FMarkerID2);
1004 FHeader := TGUILabel.Create(Header, FFontID);
1005 with FHeader do
1006 begin
1007 FColor := MAINMENU_HEADER_COLOR;
1008 FX := (gScreenWidth div 2)-(GetWidth div 2);
1009 FY := (gScreenHeight div 2)-(GetHeight div 2);
1010 end;
1011 end;
1013 destructor TGUIMainMenu.Destroy;
1014 var
1015 a: Integer;
1016 begin
1017 if FButtons <> nil then
1018 for a := 0 to High(FButtons) do
1019 FButtons[a].Free();
1021 FHeader.Free();
1023 inherited;
1024 end;
1026 procedure TGUIMainMenu.Draw;
1027 var
1028 a: Integer;
1029 begin
1030 inherited;
1032 FHeader.Draw;
1034 if FButtons <> nil then
1035 begin
1036 for a := 0 to High(FButtons) do
1037 if FButtons[a] <> nil then FButtons[a].Draw;
1039 if FIndex <> -1 then
1040 e_Draw(FMarkerID1, FButtons[FIndex].FX-48, FButtons[FIndex].FY, 0, True, False);
1041 end;
1042 end;
1044 procedure TGUIMainMenu.EnableButton(Name: string; e: Boolean);
1045 var
1046 a: Integer;
1047 begin
1048 if FButtons = nil then Exit;
1050 for a := 0 to High(FButtons) do
1051 if (FButtons[a] <> nil) and (FButtons[a].Name = Name) then
1052 begin
1053 if e then FButtons[a].FColor := MAINMENU_ITEMS_COLOR
1054 else FButtons[a].FColor := MAINMENU_UNACTIVEITEMS_COLOR;
1055 FButtons[a].Enabled := e;
1056 Break;
1057 end;
1058 end;
1060 function TGUIMainMenu.GetButton(Name: string): TGUITextButton;
1061 var
1062 a: Integer;
1063 begin
1064 Result := nil;
1066 if FButtons = nil then Exit;
1068 for a := 0 to High(FButtons) do
1069 if (FButtons[a] <> nil) and (FButtons[a].Name = Name) then
1070 begin
1071 Result := FButtons[a];
1072 Break;
1073 end;
1074 end;
1076 procedure TGUIMainMenu.OnMessage(var Msg: TMessage);
1077 var
1078 ok: Boolean;
1079 a: Integer;
1080 begin
1081 if not FEnabled then Exit;
1083 inherited;
1085 if FButtons = nil then Exit;
1087 ok := False;
1088 for a := 0 to High(FButtons) do
1089 if FButtons[a] <> nil then
1090 begin
1091 ok := True;
1092 Break;
1093 end;
1095 if not ok then Exit;
1097 case Msg.Msg of
1098 WM_KEYDOWN:
1099 case Msg.wParam of
1100 IK_UP, IK_KPUP:
1101 begin
1102 repeat
1103 Dec(FIndex);
1104 if FIndex < 0 then FIndex := High(FButtons);
1105 until FButtons[FIndex] <> nil;
1107 g_Sound_PlayEx(MENU_CHANGESOUND);
1108 end;
1109 IK_DOWN, IK_KPDOWN:
1110 begin
1111 repeat
1112 Inc(FIndex);
1113 if FIndex > High(FButtons) then FIndex := 0;
1114 until FButtons[FIndex] <> nil;
1116 g_Sound_PlayEx(MENU_CHANGESOUND);
1117 end;
1118 IK_RETURN, IK_KPRETURN: if (FIndex <> -1) and FButtons[FIndex].FEnabled then FButtons[FIndex].Click;
1119 end;
1120 end;
1121 end;
1123 procedure TGUIMainMenu.Update;
1124 var
1125 t: DWORD;
1126 begin
1127 inherited;
1129 if FCounter = 0 then
1130 begin
1131 t := FMarkerID1;
1132 FMarkerID1 := FMarkerID2;
1133 FMarkerID2 := t;
1135 FCounter := MAINMENU_MARKERDELAY;
1136 end else Dec(FCounter);
1137 end;
1139 { TGUILabel }
1141 constructor TGUILabel.Create(Text: string; FontID: DWORD);
1142 begin
1143 inherited Create();
1145 FFont := TFont.Create(FontID, FONT_CHAR);
1147 FText := Text;
1148 FFixedLen := 0;
1149 FOnClickEvent := nil;
1150 end;
1152 procedure TGUILabel.Draw;
1153 begin
1154 FFont.Draw(FX, FY, FText, FColor.R, FColor.G, FColor.B);
1155 end;
1157 function TGUILabel.GetHeight: Integer;
1158 var
1159 w, h: Word;
1160 begin
1161 FFont.GetTextSize(FText, w, h);
1162 Result := h;
1163 end;
1165 function TGUILabel.GetWidth: Integer;
1166 var
1167 w, h: Word;
1168 begin
1169 if FFixedLen = 0 then
1170 FFont.GetTextSize(FText, w, h)
1171 else
1172 w := e_CharFont_GetMaxWidth(FFont.ID)*FFixedLen;
1173 Result := w;
1174 end;
1176 procedure TGUILabel.OnMessage(var Msg: TMessage);
1177 begin
1178 if not FEnabled then Exit;
1180 inherited;
1182 case Msg.Msg of
1183 WM_KEYDOWN:
1184 case Msg.wParam of
1185 IK_RETURN, IK_KPRETURN: if @FOnClickEvent <> nil then FOnClickEvent();
1186 end;
1187 end;
1188 end;
1190 { TGUIMenu }
1192 function TGUIMenu.AddButton(Proc: Pointer; fText: string; _ShowWindow: string = ''): TGUITextButton;
1193 var
1194 i: Integer;
1195 begin
1196 i := NewItem();
1197 with FItems[i] do
1198 begin
1199 Control := TGUITextButton.Create(Proc, FFontID, fText);
1200 with Control as TGUITextButton do
1201 begin
1202 ShowWindow := _ShowWindow;
1203 FColor := MENU_ITEMSCTRL_COLOR;
1204 end;
1206 Text := nil;
1207 ControlType := TGUITextButton;
1209 Result := (Control as TGUITextButton);
1210 end;
1212 if FIndex = -1 then FIndex := i;
1214 ReAlign();
1215 end;
1217 procedure TGUIMenu.AddLine(fText: string);
1218 var
1219 i: Integer;
1220 begin
1221 i := NewItem();
1222 with FItems[i] do
1223 begin
1224 Text := TGUILabel.Create(fText, FFontID);
1225 with Text do
1226 begin
1227 FColor := MENU_ITEMSTEXT_COLOR;
1228 end;
1230 Control := nil;
1231 end;
1233 ReAlign();
1234 end;
1236 procedure TGUIMenu.AddText(fText: string; MaxWidth: Word);
1237 var
1238 a, i: Integer;
1239 l: SArray;
1240 begin
1241 l := GetLines(fText, FFontID, MaxWidth);
1243 if l = nil then Exit;
1245 for a := 0 to High(l) do
1246 begin
1247 i := NewItem();
1248 with FItems[i] do
1249 begin
1250 Text := TGUILabel.Create(l[a], FFontID);
1251 with Text do
1252 begin
1253 FColor := MENU_ITEMSTEXT_COLOR;
1254 end;
1256 Control := nil;
1257 end;
1258 end;
1260 ReAlign();
1261 end;
1263 procedure TGUIMenu.AddSpace;
1264 var
1265 i: Integer;
1266 begin
1267 i := NewItem();
1268 with FItems[i] do
1269 begin
1270 Text := nil;
1271 Control := nil;
1272 end;
1274 ReAlign();
1275 end;
1277 constructor TGUIMenu.Create(HeaderFont, ItemsFont: DWORD; Header: string);
1278 begin
1279 inherited Create();
1281 FItems := nil;
1282 FIndex := -1;
1283 FFontID := ItemsFont;
1284 FCounter := MENU_MARKERDELAY;
1285 FAlign := True;
1287 FHeader := TGUILabel.Create(Header, HeaderFont);
1288 with FHeader do
1289 begin
1290 FX := (gScreenWidth div 2)-(GetWidth div 2);
1291 FY := 0;
1292 FColor := MAINMENU_HEADER_COLOR;
1293 end;
1294 end;
1296 destructor TGUIMenu.Destroy;
1297 var
1298 a: Integer;
1299 begin
1300 if FItems <> nil then
1301 for a := 0 to High(FItems) do
1302 with FItems[a] do
1303 begin
1304 Text.Free();
1305 Control.Free();
1306 end;
1308 FItems := nil;
1310 FHeader.Free();
1312 inherited;
1313 end;
1315 procedure TGUIMenu.Draw;
1316 var
1317 a, x, y: Integer;
1318 begin
1319 inherited;
1321 if FHeader <> nil then FHeader.Draw;
1323 if FItems <> nil then
1324 for a := 0 to High(FItems) do
1325 begin
1326 if FItems[a].Text <> nil then FItems[a].Text.Draw;
1327 if FItems[a].Control <> nil then FItems[a].Control.Draw;
1328 end;
1330 if (FIndex <> -1) and (FCounter > MENU_MARKERDELAY div 2) then
1331 begin
1332 x := 0;
1333 y := 0;
1335 if FItems[FIndex].Text <> nil then
1336 begin
1337 x := FItems[FIndex].Text.FX;
1338 y := FItems[FIndex].Text.FY;
1339 end
1340 else if FItems[FIndex].Control <> nil then
1341 begin
1342 x := FItems[FIndex].Control.FX;
1343 y := FItems[FIndex].Control.FY;
1344 end;
1346 x := x-e_CharFont_GetMaxWidth(FFontID);
1348 e_CharFont_PrintEx(FFontID, x, y, #16, _RGB(255, 0, 0));
1349 end;
1350 end;
1352 function TGUIMenu.GetControl(Name: String): TGUIControl;
1353 var
1354 a: Integer;
1355 begin
1356 Result := nil;
1358 if FItems <> nil then
1359 for a := 0 to High(FItems) do
1360 if FItems[a].Control <> nil then
1361 if LowerCase(FItems[a].Control.Name) = LowerCase(Name) then
1362 begin
1363 Result := FItems[a].Control;
1364 Break;
1365 end;
1367 Assert(Result <> nil, 'GUI control "'+Name+'" not found!');
1368 end;
1370 function TGUIMenu.GetControlsText(Name: String): TGUILabel;
1371 var
1372 a: Integer;
1373 begin
1374 Result := nil;
1376 if FItems <> nil then
1377 for a := 0 to High(FItems) do
1378 if FItems[a].Control <> nil then
1379 if LowerCase(FItems[a].Control.Name) = LowerCase(Name) then
1380 begin
1381 Result := FItems[a].Text;
1382 Break;
1383 end;
1385 Assert(Result <> nil, 'GUI control''s text "'+Name+'" not found!');
1386 end;
1388 function TGUIMenu.NewItem: Integer;
1389 begin
1390 SetLength(FItems, Length(FItems)+1);
1391 Result := High(FItems);
1392 end;
1394 procedure TGUIMenu.OnMessage(var Msg: TMessage);
1395 var
1396 ok: Boolean;
1397 a, c: Integer;
1398 begin
1399 if not FEnabled then Exit;
1401 inherited;
1403 if FItems = nil then Exit;
1405 ok := False;
1406 for a := 0 to High(FItems) do
1407 if FItems[a].Control <> nil then
1408 begin
1409 ok := True;
1410 Break;
1411 end;
1413 if not ok then Exit;
1415 case Msg.Msg of
1416 WM_KEYDOWN:
1417 begin
1418 case Msg.wParam of
1419 IK_UP, IK_KPUP:
1420 begin
1421 c := 0;
1422 repeat
1423 c := c+1;
1424 if c > Length(FItems) then
1425 begin
1426 FIndex := -1;
1427 Break;
1428 end;
1430 Dec(FIndex);
1431 if FIndex < 0 then FIndex := High(FItems);
1432 until (FItems[FIndex].Control <> nil) and
1433 (FItems[FIndex].Control.Enabled);
1435 FCounter := 0;
1437 g_Sound_PlayEx(MENU_CHANGESOUND);
1438 end;
1440 IK_DOWN, IK_KPDOWN:
1441 begin
1442 c := 0;
1443 repeat
1444 c := c+1;
1445 if c > Length(FItems) then
1446 begin
1447 FIndex := -1;
1448 Break;
1449 end;
1451 Inc(FIndex);
1452 if FIndex > High(FItems) then FIndex := 0;
1453 until (FItems[FIndex].Control <> nil) and
1454 (FItems[FIndex].Control.Enabled);
1456 FCounter := 0;
1458 g_Sound_PlayEx(MENU_CHANGESOUND);
1459 end;
1461 IK_LEFT, IK_RIGHT, IK_KPLEFT, IK_KPRIGHT:
1462 begin
1463 if FIndex <> -1 then
1464 if FItems[FIndex].Control <> nil then
1465 FItems[FIndex].Control.OnMessage(Msg);
1466 end;
1467 IK_RETURN, IK_KPRETURN:
1468 begin
1469 if FIndex <> -1 then
1470 if FItems[FIndex].Control <> nil then
1471 FItems[FIndex].Control.OnMessage(Msg);
1473 g_Sound_PlayEx(MENU_CLICKSOUND);
1474 end;
1475 end;
1476 end;
1477 end;
1478 end;
1480 procedure TGUIMenu.ReAlign();
1481 var
1482 a, tx, cx, w, h: Integer;
1483 begin
1484 if FItems = nil then Exit;
1486 if not FAlign then tx := FLeft else
1487 begin
1488 tx := gScreenWidth;
1489 for a := 0 to High(FItems) do
1490 begin
1491 w := 0;
1492 if FItems[a].Text <> nil then w := FItems[a].Text.GetWidth;
1493 if FItems[a].Control <> nil then
1494 begin
1495 w := w+MENU_HSPACE;
1497 if FItems[a].ControlType = TGUILabel then
1498 w := w+(FItems[a].Control as TGUILabel).GetWidth
1499 else if FItems[a].ControlType = TGUITextButton then
1500 w := w+(FItems[a].Control as TGUITextButton).GetWidth
1501 else if FItems[a].ControlType = TGUIScroll then
1502 w := w+(FItems[a].Control as TGUIScroll).GetWidth
1503 else if FItems[a].ControlType = TGUISwitch then
1504 w := w+(FItems[a].Control as TGUISwitch).GetWidth
1505 else if FItems[a].ControlType = TGUIEdit then
1506 w := w+(FItems[a].Control as TGUIEdit).GetWidth
1507 else if FItems[a].ControlType = TGUIKeyRead then
1508 w := w+(FItems[a].Control as TGUIKeyRead).GetWidth
1509 else if (FItems[a].ControlType = TGUIListBox) then
1510 w := w+(FItems[a].Control as TGUIListBox).GetWidth
1511 else if (FItems[a].ControlType = TGUIFileListBox) then
1512 w := w+(FItems[a].Control as TGUIFileListBox).GetWidth
1513 else if FItems[a].ControlType = TGUIMemo then
1514 w := w+(FItems[a].Control as TGUIMemo).GetWidth;
1515 end;
1517 tx := Min(tx, (gScreenWidth div 2)-(w div 2));
1518 end;
1519 end;
1521 cx := 0;
1522 for a := 0 to High(FItems) do
1523 with FItems[a] do
1524 begin
1525 if (Text <> nil) and (Control = nil) then Continue;
1527 w := 0;
1528 if Text <> nil then w := tx+Text.GetWidth;
1530 if w > cx then cx := w;
1531 end;
1533 cx := cx+MENU_HSPACE;
1535 h := FHeader.GetHeight*2+MENU_VSPACE*(Length(FItems)-1);
1537 for a := 0 to High(FItems) do
1538 with FItems[a] do
1539 begin
1540 if (ControlType = TGUIListBox) or (ControlType = TGUIFileListBox) then
1541 h := h+(FItems[a].Control as TGUIListBox).GetHeight()
1542 else
1543 h := h+e_CharFont_GetMaxHeight(FFontID);
1544 end;
1546 h := (gScreenHeight div 2)-(h div 2);
1548 with FHeader do
1549 begin
1550 FX := (gScreenWidth div 2)-(GetWidth div 2);
1551 FY := h;
1553 Inc(h, GetHeight*2);
1554 end;
1556 for a := 0 to High(FItems) do
1557 with FItems[a] do
1558 begin
1559 if Text <> nil then
1560 with Text do
1561 begin
1562 FX := tx;
1563 FY := h;
1564 end;
1566 if Control <> nil then
1567 with Control do
1568 if Text <> nil then
1569 begin
1570 FX := cx;
1571 FY := h;
1572 end
1573 else
1574 begin
1575 FX := tx;
1576 FY := h;
1577 end;
1579 if (ControlType = TGUIListBox) or (ControlType = TGUIFileListBox) then
1580 Inc(h, (Control as TGUIListBox).GetHeight+MENU_VSPACE)
1581 else if ControlType = TGUIMemo then
1582 Inc(h, (Control as TGUIMemo).GetHeight+MENU_VSPACE)
1583 else
1584 Inc(h, e_CharFont_GetMaxHeight(FFontID)+MENU_VSPACE);
1585 end;
1586 end;
1588 function TGUIMenu.AddScroll(fText: string): TGUIScroll;
1589 var
1590 i: Integer;
1591 begin
1592 i := NewItem();
1593 with FItems[i] do
1594 begin
1595 Control := TGUIScroll.Create();
1597 Text := TGUILabel.Create(fText, FFontID);
1598 with Text do
1599 begin
1600 FColor := MENU_ITEMSTEXT_COLOR;
1601 end;
1603 ControlType := TGUIScroll;
1605 Result := (Control as TGUIScroll);
1606 end;
1608 if FIndex = -1 then FIndex := i;
1610 ReAlign();
1611 end;
1613 function TGUIMenu.AddSwitch(fText: string): TGUISwitch;
1614 var
1615 i: Integer;
1616 begin
1617 i := NewItem();
1618 with FItems[i] do
1619 begin
1620 Control := TGUISwitch.Create(FFontID);
1621 (Control as TGUISwitch).FColor := MENU_ITEMSCTRL_COLOR;
1623 Text := TGUILabel.Create(fText, FFontID);
1624 with Text do
1625 begin
1626 FColor := MENU_ITEMSTEXT_COLOR;
1627 end;
1629 ControlType := TGUISwitch;
1631 Result := (Control as TGUISwitch);
1632 end;
1634 if FIndex = -1 then FIndex := i;
1636 ReAlign();
1637 end;
1639 function TGUIMenu.AddEdit(fText: string): TGUIEdit;
1640 var
1641 i: Integer;
1642 begin
1643 i := NewItem();
1644 with FItems[i] do
1645 begin
1646 Control := TGUIEdit.Create(FFontID);
1647 with Control as TGUIEdit do
1648 begin
1649 FWindow := Self.FWindow;
1650 FColor := MENU_ITEMSCTRL_COLOR;
1651 end;
1653 if fText = '' then Text := nil else
1654 begin
1655 Text := TGUILabel.Create(fText, FFontID);
1656 Text.FColor := MENU_ITEMSTEXT_COLOR;
1657 end;
1659 ControlType := TGUIEdit;
1661 Result := (Control as TGUIEdit);
1662 end;
1664 if FIndex = -1 then FIndex := i;
1666 ReAlign();
1667 end;
1669 procedure TGUIMenu.Update;
1670 var
1671 a: Integer;
1672 begin
1673 inherited;
1675 if FCounter = 0 then FCounter := MENU_MARKERDELAY else Dec(FCounter);
1677 if FItems <> nil then
1678 for a := 0 to High(FItems) do
1679 if FItems[a].Control <> nil then
1680 (FItems[a].Control as FItems[a].ControlType).Update;
1681 end;
1683 function TGUIMenu.AddKeyRead(fText: string): TGUIKeyRead;
1684 var
1685 i: Integer;
1686 begin
1687 i := NewItem();
1688 with FItems[i] do
1689 begin
1690 Control := TGUIKeyRead.Create(FFontID);
1691 with Control as TGUIKeyRead do
1692 begin
1693 FWindow := Self.FWindow;
1694 FColor := MENU_ITEMSCTRL_COLOR;
1695 end;
1697 Text := TGUILabel.Create(fText, FFontID);
1698 with Text do
1699 begin
1700 FColor := MENU_ITEMSTEXT_COLOR;
1701 end;
1703 ControlType := TGUIKeyRead;
1705 Result := (Control as TGUIKeyRead);
1706 end;
1708 if FIndex = -1 then FIndex := i;
1710 ReAlign();
1711 end;
1713 function TGUIMenu.AddList(fText: string; Width, Height: Word): TGUIListBox;
1714 var
1715 i: Integer;
1716 begin
1717 i := NewItem();
1718 with FItems[i] do
1719 begin
1720 Control := TGUIListBox.Create(FFontID, Width, Height);
1721 with Control as TGUIListBox do
1722 begin
1723 FWindow := Self.FWindow;
1724 FActiveColor := MENU_ITEMSCTRL_COLOR;
1725 FUnActiveColor := MENU_ITEMSTEXT_COLOR;
1726 end;
1728 Text := TGUILabel.Create(fText, FFontID);
1729 with Text do
1730 begin
1731 FColor := MENU_ITEMSTEXT_COLOR;
1732 end;
1734 ControlType := TGUIListBox;
1736 Result := (Control as TGUIListBox);
1737 end;
1739 if FIndex = -1 then FIndex := i;
1741 ReAlign();
1742 end;
1744 function TGUIMenu.AddFileList(fText: string; Width, Height: Word): TGUIFileListBox;
1745 var
1746 i: Integer;
1747 begin
1748 i := NewItem();
1749 with FItems[i] do
1750 begin
1751 Control := TGUIFileListBox.Create(FFontID, Width, Height);
1752 with Control as TGUIFileListBox do
1753 begin
1754 FWindow := Self.FWindow;
1755 FActiveColor := MENU_ITEMSCTRL_COLOR;
1756 FUnActiveColor := MENU_ITEMSTEXT_COLOR;
1757 end;
1759 if fText = '' then Text := nil else
1760 begin
1761 Text := TGUILabel.Create(fText, FFontID);
1762 Text.FColor := MENU_ITEMSTEXT_COLOR;
1763 end;
1765 ControlType := TGUIFileListBox;
1767 Result := (Control as TGUIFileListBox);
1768 end;
1770 if FIndex = -1 then FIndex := i;
1772 ReAlign();
1773 end;
1775 function TGUIMenu.AddLabel(fText: string): TGUILabel;
1776 var
1777 i: Integer;
1778 begin
1779 i := NewItem();
1780 with FItems[i] do
1781 begin
1782 Control := TGUILabel.Create('', FFontID);
1783 with Control as TGUILabel do
1784 begin
1785 FWindow := Self.FWindow;
1786 FColor := MENU_ITEMSCTRL_COLOR;
1787 end;
1789 Text := TGUILabel.Create(fText, FFontID);
1790 with Text do
1791 begin
1792 FColor := MENU_ITEMSTEXT_COLOR;
1793 end;
1795 ControlType := TGUILabel;
1797 Result := (Control as TGUILabel);
1798 end;
1800 if FIndex = -1 then FIndex := i;
1802 ReAlign();
1803 end;
1805 function TGUIMenu.AddMemo(fText: string; Width, Height: Word): TGUIMemo;
1806 var
1807 i: Integer;
1808 begin
1809 i := NewItem();
1810 with FItems[i] do
1811 begin
1812 Control := TGUIMemo.Create(FFontID, Width, Height);
1813 with Control as TGUIMemo do
1814 begin
1815 FWindow := Self.FWindow;
1816 FColor := MENU_ITEMSTEXT_COLOR;
1817 end;
1819 if fText = '' then Text := nil else
1820 begin
1821 Text := TGUILabel.Create(fText, FFontID);
1822 Text.FColor := MENU_ITEMSTEXT_COLOR;
1823 end;
1825 ControlType := TGUIMemo;
1827 Result := (Control as TGUIMemo);
1828 end;
1830 if FIndex = -1 then FIndex := i;
1832 ReAlign();
1833 end;
1835 procedure TGUIMenu.UpdateIndex();
1836 var
1837 res: Boolean;
1838 begin
1839 res := True;
1841 while res do
1842 begin
1843 if (FIndex < 0) or (FIndex > High(FItems)) then
1844 begin
1845 FIndex := -1;
1846 res := False;
1847 end
1848 else
1849 if FItems[FIndex].Control.Enabled then
1850 res := False
1851 else
1852 Inc(FIndex);
1853 end;
1854 end;
1856 { TGUIScroll }
1858 constructor TGUIScroll.Create;
1859 begin
1860 inherited Create();
1862 FMax := 0;
1863 FOnChangeEvent := nil;
1865 g_Texture_Get(SCROLL_LEFT, FLeftID);
1866 g_Texture_Get(SCROLL_RIGHT, FRightID);
1867 g_Texture_Get(SCROLL_MIDDLE, FMiddleID);
1868 g_Texture_Get(SCROLL_MARKER, FMarkerID);
1869 end;
1871 procedure TGUIScroll.Draw;
1872 var
1873 a: Integer;
1874 begin
1875 inherited;
1877 e_Draw(FLeftID, FX, FY, 0, True, False);
1878 e_Draw(FRightID, FX+8+(FMax+1)*8, FY, 0, True, False);
1880 for a := 0 to FMax do
1881 e_Draw(FMiddleID, FX+8+a*8, FY, 0, True, False);
1883 e_Draw(FMarkerID, FX+8+FValue*8, FY, 0, True, False);
1884 end;
1886 procedure TGUIScroll.FSetValue(a: Integer);
1887 begin
1888 if a > FMax then FValue := FMax else FValue := a;
1889 end;
1891 function TGUIScroll.GetWidth: Word;
1892 begin
1893 Result := 16+(FMax+1)*8;
1894 end;
1896 procedure TGUIScroll.OnMessage(var Msg: TMessage);
1897 begin
1898 if not FEnabled then Exit;
1900 inherited;
1902 case Msg.Msg of
1903 WM_KEYDOWN:
1904 begin
1905 case Msg.wParam of
1906 IK_LEFT, IK_KPLEFT:
1907 if FValue > 0 then
1908 begin
1909 Dec(FValue);
1910 g_Sound_PlayEx(SCROLL_SUBSOUND);
1911 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
1912 end;
1913 IK_RIGHT, IK_KPRIGHT:
1914 if FValue < FMax then
1915 begin
1916 Inc(FValue);
1917 g_Sound_PlayEx(SCROLL_ADDSOUND);
1918 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
1919 end;
1920 end;
1921 end;
1922 end;
1923 end;
1925 procedure TGUIScroll.Update;
1926 begin
1927 inherited;
1929 end;
1931 { TGUISwitch }
1933 procedure TGUISwitch.AddItem(Item: string);
1934 begin
1935 SetLength(FItems, Length(FItems)+1);
1936 FItems[High(FItems)] := Item;
1938 if FIndex = -1 then FIndex := 0;
1939 end;
1941 constructor TGUISwitch.Create(FontID: DWORD);
1942 begin
1943 inherited Create();
1945 FIndex := -1;
1947 FFont := TFont.Create(FontID, FONT_CHAR);
1948 end;
1950 procedure TGUISwitch.Draw;
1951 begin
1952 inherited;
1954 FFont.Draw(FX, FY, FItems[FIndex], FColor.R, FColor.G, FColor.B);
1955 end;
1957 function TGUISwitch.GetText: string;
1958 begin
1959 if FIndex <> -1 then Result := FItems[FIndex]
1960 else Result := '';
1961 end;
1963 function TGUISwitch.GetWidth: Word;
1964 var
1965 a: Integer;
1966 w, h: Word;
1967 begin
1968 Result := 0;
1970 if FItems = nil then Exit;
1972 for a := 0 to High(FItems) do
1973 begin
1974 FFont.GetTextSize(FItems[a], w, h);
1975 if w > Result then Result := w;
1976 end;
1977 end;
1979 procedure TGUISwitch.OnMessage(var Msg: TMessage);
1980 begin
1981 if not FEnabled then Exit;
1983 inherited;
1985 if FItems = nil then Exit;
1987 case Msg.Msg of
1988 WM_KEYDOWN:
1989 case Msg.wParam of
1990 IK_RETURN, IK_RIGHT, IK_KPRETURN, IK_KPRIGHT:
1991 begin
1992 if FIndex < High(FItems) then
1993 Inc(FIndex)
1994 else
1995 FIndex := 0;
1997 if @FOnChangeEvent <> nil then
1998 FOnChangeEvent(Self);
1999 end;
2001 IK_LEFT, IK_KPLEFT:
2002 begin
2003 if FIndex > 0 then
2004 Dec(FIndex)
2005 else
2006 FIndex := High(FItems);
2008 if @FOnChangeEvent <> nil then
2009 FOnChangeEvent(Self);
2010 end;
2011 end;
2012 end;
2013 end;
2015 procedure TGUISwitch.Update;
2016 begin
2017 inherited;
2019 end;
2021 { TGUIEdit }
2023 constructor TGUIEdit.Create(FontID: DWORD);
2024 begin
2025 inherited Create();
2027 FFont := TFont.Create(FontID, FONT_CHAR);
2029 FMaxLength := 0;
2030 FWidth := 0;
2032 g_Texture_Get(EDIT_LEFT, FLeftID);
2033 g_Texture_Get(EDIT_RIGHT, FRightID);
2034 g_Texture_Get(EDIT_MIDDLE, FMiddleID);
2035 end;
2037 procedure TGUIEdit.Draw;
2038 var
2039 c, w, h: Word;
2040 begin
2041 inherited;
2043 e_Draw(FLeftID, FX, FY, 0, True, False);
2044 e_Draw(FRightID, FX+8+FWidth*16, FY, 0, True, False);
2046 for c := 0 to FWidth-1 do
2047 e_Draw(FMiddleID, FX+8+c*16, FY, 0, True, False);
2049 FFont.Draw(FX+8, FY, FText, FColor.R, FColor.G, FColor.B);
2051 if FWindow.FActiveControl = Self then
2052 begin
2053 FFont.GetTextSize(Copy(FText, 1, FCaretPos), w, h);
2054 h := e_CharFont_GetMaxHeight(FFont.ID);
2055 e_DrawLine(2, FX+8+w, FY+h-3, FX+8+w+EDIT_CURSORLEN, FY+h-3,
2056 EDIT_CURSORCOLOR.R, EDIT_CURSORCOLOR.G, EDIT_CURSORCOLOR.B);
2057 end;
2058 end;
2060 function TGUIEdit.GetWidth: Word;
2061 begin
2062 Result := 16+FWidth*16;
2063 end;
2065 procedure TGUIEdit.OnMessage(var Msg: TMessage);
2066 begin
2067 if not FEnabled then Exit;
2069 inherited;
2071 with Msg do
2072 case Msg of
2073 WM_CHAR:
2074 if FOnlyDigits then
2075 begin
2076 if (wParam in [48..57]) and (Chr(wParam) <> '`') then
2077 if Length(Text) < FMaxLength then
2078 begin
2079 Insert(Chr(wParam), FText, FCaretPos + 1);
2080 Inc(FCaretPos);
2081 end;
2082 end
2083 else
2084 begin
2085 if (wParam in [32..255]) and (Chr(wParam) <> '`') then
2086 if Length(Text) < FMaxLength then
2087 begin
2088 Insert(Chr(wParam), FText, FCaretPos + 1);
2089 Inc(FCaretPos);
2090 end;
2091 end;
2092 WM_KEYDOWN:
2093 case wParam of
2094 IK_BACKSPACE:
2095 begin
2096 Delete(FText, FCaretPos, 1);
2097 if FCaretPos > 0 then Dec(FCaretPos);
2098 end;
2099 IK_DELETE: Delete(FText, FCaretPos + 1, 1);
2100 IK_END, IK_KPEND: FCaretPos := Length(FText);
2101 IK_HOME, IK_KPHOME: FCaretPos := 0;
2102 IK_LEFT, IK_KPLEFT: if FCaretPos > 0 then Dec(FCaretPos);
2103 IK_RIGHT, IK_KPRIGHT: if FCaretPos < Length(FText) then Inc(FCaretPos);
2104 IK_RETURN, IK_KPRETURN:
2105 with FWindow do
2106 begin
2107 if FActiveControl <> Self then
2108 begin
2109 SetActive(Self);
2110 if @FOnEnterEvent <> nil then FOnEnterEvent(Self);
2111 end
2112 else
2113 begin
2114 if FDefControl <> '' then SetActive(GetControl(FDefControl))
2115 else SetActive(nil);
2116 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
2117 end;
2118 end;
2119 end;
2120 end;
2121 end;
2123 procedure TGUIEdit.SetText(Text: string);
2124 begin
2125 if Length(Text) > FMaxLength then SetLength(Text, FMaxLength);
2126 FText := Text;
2127 FCaretPos := Length(FText);
2128 end;
2130 procedure TGUIEdit.Update;
2131 begin
2132 inherited;
2133 end;
2135 { TGUIKeyRead }
2137 constructor TGUIKeyRead.Create(FontID: DWORD);
2138 begin
2139 inherited Create();
2141 FFont := TFont.Create(FontID, FONT_CHAR);
2142 end;
2144 procedure TGUIKeyRead.Draw;
2145 begin
2146 inherited;
2148 FFont.Draw(FX, FY, IfThen(FIsQuery, KEYREAD_QUERY, IfThen(FKey <> 0, e_KeyNames[FKey], KEYREAD_CLEAR)),
2149 FColor.R, FColor.G, FColor.B);
2150 end;
2152 function TGUIKeyRead.GetWidth: Word;
2153 var
2154 a: Byte;
2155 w, h: Word;
2156 begin
2157 Result := 0;
2159 for a := 0 to 255 do
2160 begin
2161 FFont.GetTextSize(e_KeyNames[a], w, h);
2162 Result := Max(Result, w);
2163 end;
2165 FFont.GetTextSize(KEYREAD_QUERY, w, h);
2166 if w > Result then Result := w;
2168 FFont.GetTextSize(KEYREAD_CLEAR, w, h);
2169 if w > Result then Result := w;
2170 end;
2172 procedure TGUIKeyRead.OnMessage(var Msg: TMessage);
2173 begin
2174 inherited;
2176 if not FEnabled then
2177 Exit;
2179 with Msg do
2180 case Msg of
2181 WM_KEYDOWN:
2182 case wParam of
2183 IK_ESCAPE:
2184 begin
2185 if FIsQuery then
2186 with FWindow do
2187 if FDefControl <> '' then
2188 SetActive(GetControl(FDefControl))
2189 else
2190 SetActive(nil);
2192 FIsQuery := False;
2193 end;
2194 IK_RETURN, IK_KPRETURN:
2195 begin
2196 if not FIsQuery then
2197 begin
2198 with FWindow do
2199 if FActiveControl <> Self then
2200 SetActive(Self);
2202 FIsQuery := True;
2203 end
2204 else
2205 begin
2206 FKey := IK_ENTER; // <Enter>
2207 FIsQuery := False;
2209 with FWindow do
2210 if FDefControl <> '' then
2211 SetActive(GetControl(FDefControl))
2212 else
2213 SetActive(nil);
2214 end;
2215 end;
2216 end;
2218 MESSAGE_DIKEY:
2219 if FIsQuery and (wParam <> IK_ENTER) and (wParam <> IK_KPRETURN) then // Not <Enter
2220 begin
2221 if e_KeyNames[wParam] <> '' then
2222 FKey := wParam;
2223 FIsQuery := False;
2225 with FWindow do
2226 if FDefControl <> '' then
2227 SetActive(GetControl(FDefControl))
2228 else
2229 SetActive(nil);
2230 end;
2231 end;
2232 end;
2234 { TGUIModelView }
2236 constructor TGUIModelView.Create;
2237 begin
2238 inherited Create();
2240 FModel := nil;
2241 end;
2243 destructor TGUIModelView.Destroy;
2244 begin
2245 FModel.Free();
2247 inherited;
2248 end;
2250 procedure TGUIModelView.Draw;
2251 begin
2252 inherited;
2254 DrawBox(FX, FY, 4, 4);
2256 if FModel <> nil then FModel.Draw(FX+4, FY+4);
2257 end;
2259 procedure TGUIModelView.NextAnim();
2260 begin
2261 if FModel = nil then
2262 Exit;
2264 if FModel.Animation < A_PAIN then
2265 FModel.ChangeAnimation(FModel.Animation+1, True)
2266 else
2267 FModel.ChangeAnimation(A_STAND, True);
2268 end;
2270 procedure TGUIModelView.NextWeapon();
2271 begin
2272 if FModel = nil then
2273 Exit;
2275 if FModel.Weapon < WEAPON_SUPERPULEMET then
2276 FModel.SetWeapon(FModel.Weapon+1)
2277 else
2278 FModel.SetWeapon(WEAPON_KASTET);
2279 end;
2281 procedure TGUIModelView.OnMessage(var Msg: TMessage);
2282 begin
2283 inherited;
2285 end;
2287 procedure TGUIModelView.SetColor(Red, Green, Blue: Byte);
2288 begin
2289 if FModel <> nil then FModel.SetColor(Red, Green, Blue);
2290 end;
2292 procedure TGUIModelView.SetModel(ModelName: string);
2293 begin
2294 FModel.Free();
2296 FModel := g_PlayerModel_Get(ModelName);
2297 end;
2299 procedure TGUIModelView.Update;
2300 begin
2301 inherited;
2303 a := not a;
2304 if a then Exit;
2306 if FModel <> nil then FModel.Update;
2307 end;
2309 { TGUIMapPreview }
2311 constructor TGUIMapPreview.Create();
2312 begin
2313 inherited Create();
2314 ClearMap;
2315 end;
2317 destructor TGUIMapPreview.Destroy();
2318 begin
2319 ClearMap;
2320 inherited;
2321 end;
2323 procedure TGUIMapPreview.Draw();
2324 var
2325 a: Integer;
2326 r, g, b: Byte;
2327 begin
2328 inherited;
2330 DrawBox(FX, FY, MAPPREVIEW_WIDTH, MAPPREVIEW_HEIGHT);
2332 if (FMapSize.X <= 0) or (FMapSize.Y <= 0) then
2333 Exit;
2335 e_DrawFillQuad(FX+4, FY+4,
2336 FX+4 + Trunc(FMapSize.X / FScale) - 1,
2337 FY+4 + Trunc(FMapSize.Y / FScale) - 1,
2338 32, 32, 32, 0);
2340 if FMapData <> nil then
2341 for a := 0 to High(FMapData) do
2342 with FMapData[a] do
2343 begin
2344 if X1 > MAPPREVIEW_WIDTH*16 then Continue;
2345 if Y1 > MAPPREVIEW_HEIGHT*16 then Continue;
2347 if X2 < 0 then Continue;
2348 if Y2 < 0 then Continue;
2350 if X2 > MAPPREVIEW_WIDTH*16 then X2 := MAPPREVIEW_WIDTH*16;
2351 if Y2 > MAPPREVIEW_HEIGHT*16 then Y2 := MAPPREVIEW_HEIGHT*16;
2353 if X1 < 0 then X1 := 0;
2354 if Y1 < 0 then Y1 := 0;
2356 case PanelType of
2357 PANEL_WALL:
2358 begin
2359 r := 255;
2360 g := 255;
2361 b := 255;
2362 end;
2363 PANEL_CLOSEDOOR:
2364 begin
2365 r := 255;
2366 g := 255;
2367 b := 0;
2368 end;
2369 PANEL_WATER:
2370 begin
2371 r := 0;
2372 g := 0;
2373 b := 192;
2374 end;
2375 PANEL_ACID1:
2376 begin
2377 r := 0;
2378 g := 176;
2379 b := 0;
2380 end;
2381 PANEL_ACID2:
2382 begin
2383 r := 176;
2384 g := 0;
2385 b := 0;
2386 end;
2387 else
2388 begin
2389 r := 128;
2390 g := 128;
2391 b := 128;
2392 end;
2393 end;
2395 if ((X2-X1) > 0) and ((Y2-Y1) > 0) then
2396 e_DrawFillQuad(FX+4 + X1, FY+4 + Y1,
2397 FX+4 + X2 - 1, FY+4 + Y2 - 1, r, g, b, 0);
2398 end;
2399 end;
2401 procedure TGUIMapPreview.OnMessage(var Msg: TMessage);
2402 begin
2403 inherited;
2405 end;
2407 procedure TGUIMapPreview.SetMap(Res: string);
2408 var
2409 WAD: TWADEditor_1;
2410 MapReader: TMapReader_1;
2411 panels: TPanelsRec1Array;
2412 header: TMapHeaderRec_1;
2413 a: Integer;
2414 FileName, SectionName, ResName: string;
2415 Data: Pointer;
2416 Len: Integer;
2417 rX, rY: Single;
2418 begin
2419 g_ProcessResourceStr(Res, FileName, SectionName, ResName);
2421 WAD := TWADEditor_1.Create();
2422 if not WAD.ReadFile(FileName) then
2423 begin
2424 WAD.Free();
2425 Exit;
2426 end;
2428 if not WAD.GetResource('', ResName, Data, Len) then
2429 begin
2430 WAD.Free();
2431 Exit;
2432 end;
2434 WAD.Free();
2436 MapReader := TMapReader_1.Create();
2438 if not MapReader.LoadMap(Data) then
2439 begin
2440 FreeMem(Data);
2441 MapReader.Free();
2442 FMapSize.X := 0;
2443 FMapSize.Y := 0;
2444 FScale := 0.0;
2445 FMapData := nil;
2446 Exit;
2447 end;
2449 FreeMem(Data);
2451 panels := MapReader.GetPanels();
2452 header := MapReader.GetMapHeader();
2454 FMapSize.X := header.Width div 16;
2455 FMapSize.Y := header.Height div 16;
2457 rX := Ceil(header.Width / (MAPPREVIEW_WIDTH*256.0));
2458 rY := Ceil(header.Height / (MAPPREVIEW_HEIGHT*256.0));
2459 FScale := max(rX, rY);
2461 FMapData := nil;
2463 if panels <> nil then
2464 for a := 0 to High(panels) do
2465 if WordBool(panels[a].PanelType and (PANEL_WALL or PANEL_CLOSEDOOR or
2466 PANEL_STEP or PANEL_WATER or
2467 PANEL_ACID1 or PANEL_ACID2)) then
2468 begin
2469 SetLength(FMapData, Length(FMapData)+1);
2470 with FMapData[High(FMapData)] do
2471 begin
2472 X1 := panels[a].X div 16;
2473 Y1 := panels[a].Y div 16;
2475 X2 := (panels[a].X + panels[a].Width) div 16;
2476 Y2 := (panels[a].Y + panels[a].Height) div 16;
2478 X1 := Trunc(X1/FScale + 0.5);
2479 Y1 := Trunc(Y1/FScale + 0.5);
2480 X2 := Trunc(X2/FScale + 0.5);
2481 Y2 := Trunc(Y2/FScale + 0.5);
2483 if (X1 <> X2) or (Y1 <> Y2) then
2484 begin
2485 if X1 = X2 then
2486 X2 := X2 + 1;
2487 if Y1 = Y2 then
2488 Y2 := Y2 + 1;
2489 end;
2491 PanelType := panels[a].PanelType;
2492 end;
2493 end;
2495 panels := nil;
2497 MapReader.Free();
2498 end;
2500 procedure TGUIMapPreview.ClearMap();
2501 begin
2502 SetLength(FMapData, 0);
2503 FMapData := nil;
2504 FMapSize.X := 0;
2505 FMapSize.Y := 0;
2506 FScale := 0.0;
2507 end;
2509 procedure TGUIMapPreview.Update();
2510 begin
2511 inherited;
2513 end;
2515 function TGUIMapPreview.GetScaleStr(): String;
2516 begin
2517 if FScale > 0.0 then
2518 begin
2519 Result := FloatToStrF(FScale*16.0, ffFixed, 3, 3);
2520 while (Result[Length(Result)] = '0') do
2521 Delete(Result, Length(Result), 1);
2522 if (Result[Length(Result)] = ',') or (Result[Length(Result)] = '.') then
2523 Delete(Result, Length(Result), 1);
2524 Result := '1 : ' + Result;
2525 end
2526 else
2527 Result := '';
2528 end;
2530 { TGUIListBox }
2532 procedure TGUIListBox.AddItem(Item: string);
2533 begin
2534 SetLength(FItems, Length(FItems)+1);
2535 FItems[High(FItems)] := Item;
2537 if FSort then g_Basic.Sort(FItems);
2538 end;
2540 procedure TGUIListBox.Clear();
2541 begin
2542 FItems := nil;
2544 FStartLine := 0;
2545 FIndex := -1;
2546 end;
2548 constructor TGUIListBox.Create(FontID: DWORD; Width, Height: Word);
2549 begin
2550 inherited Create();
2552 FFont := TFont.Create(FontID, FONT_CHAR);
2554 FWidth := Width;
2555 FHeight := Height;
2556 FIndex := -1;
2557 FOnChangeEvent := nil;
2558 FDrawBack := True;
2559 FDrawScroll := True;
2560 end;
2562 procedure TGUIListBox.Draw;
2563 var
2564 w2, h2: Word;
2565 a: Integer;
2566 s: string;
2567 begin
2568 inherited;
2570 if FDrawBack then DrawBox(FX, FY, FWidth+1, FHeight);
2571 if FDrawScroll then
2572 DrawScroll(FX+4+FWidth*16, FY+4, FHeight, (FStartLine > 0) and (FItems <> nil),
2573 (FStartLine+FHeight-1 < High(FItems)) and (FItems <> nil));
2575 if FItems <> nil then
2576 for a := FStartLine to Min(High(FItems), FStartLine+FHeight-1) do
2577 begin
2578 s := Items[a];
2580 FFont.GetTextSize(s, w2, h2);
2581 while (Length(s) > 0) and (w2 > FWidth*16) do
2582 begin
2583 SetLength(s, Length(s)-1);
2584 FFont.GetTextSize(s, w2, h2);
2585 end;
2587 if a = FIndex then
2588 FFont.Draw(FX+4, FY+4+(a-FStartLine)*16, s, FActiveColor.R, FActiveColor.G, FActiveColor.B)
2589 else
2590 FFont.Draw(FX+4, FY+4+(a-FStartLine)*16, s, FUnActiveColor.R, FUnActiveColor.G, FUnActiveColor.B);
2591 end;
2592 end;
2594 function TGUIListBox.GetHeight: Word;
2595 begin
2596 Result := 8+FHeight*16;
2597 end;
2599 function TGUIListBox.GetWidth: Word;
2600 begin
2601 Result := 8+(FWidth+1)*16;
2602 end;
2604 procedure TGUIListBox.OnMessage(var Msg: TMessage);
2605 var
2606 a: Integer;
2607 begin
2608 if not FEnabled then Exit;
2610 inherited;
2612 if FItems = nil then Exit;
2614 with Msg do
2615 case Msg of
2616 WM_KEYDOWN:
2617 case wParam of
2618 IK_HOME, IK_KPHOME:
2619 begin
2620 FIndex := 0;
2621 FStartLine := 0;
2622 end;
2623 IK_END, IK_KPEND:
2624 begin
2625 FIndex := High(FItems);
2626 FStartLine := Max(High(FItems)-FHeight+1, 0);
2627 end;
2628 IK_UP, IK_LEFT, IK_KPUP, IK_KPLEFT:
2629 if FIndex > 0 then
2630 begin
2631 Dec(FIndex);
2632 if FIndex < FStartLine then Dec(FStartLine);
2633 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
2634 end;
2635 IK_DOWN, IK_RIGHT, IK_KPDOWN, IK_KPRIGHT:
2636 if FIndex < High(FItems) then
2637 begin
2638 Inc(FIndex);
2639 if FIndex > FStartLine+FHeight-1 then Inc(FStartLine);
2640 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
2641 end;
2642 IK_RETURN, IK_KPRETURN:
2643 with FWindow do
2644 begin
2645 if FActiveControl <> Self then SetActive(Self)
2646 else
2647 if FDefControl <> '' then SetActive(GetControl(FDefControl))
2648 else SetActive(nil);
2649 end;
2650 end;
2651 WM_CHAR:
2652 for a := 0 to High(FItems) do
2653 if (Length(FItems[a]) > 0) and (LowerCase(FItems[a][1]) = LowerCase(Chr(wParam))) then
2654 begin
2655 FIndex := a;
2656 FStartLine := Min(Max(FIndex-1, 0), Length(FItems)-FHeight);
2657 if @FOnChangeEvent <> nil then FOnChangeEvent(Self);
2658 Break;
2659 end;
2660 end;
2661 end;
2663 function TGUIListBox.SelectedItem(): String;
2664 begin
2665 Result := '';
2667 if (FIndex < 0) or (FItems = nil) or
2668 (FIndex > High(FItems)) then
2669 Exit;
2671 Result := FItems[FIndex];
2672 end;
2674 procedure TGUIListBox.FSetItems(Items: SArray);
2675 begin
2676 if FItems <> nil then
2677 FItems := nil;
2679 FItems := Items;
2681 FStartLine := 0;
2682 FIndex := -1;
2684 if FSort then g_Basic.Sort(FItems);
2685 end;
2687 procedure TGUIListBox.SelectItem(Item: String);
2688 var
2689 a: Integer;
2690 begin
2691 if FItems = nil then
2692 Exit;
2694 FIndex := 0;
2695 Item := LowerCase(Item);
2697 for a := 0 to High(FItems) do
2698 if LowerCase(FItems[a]) = Item then
2699 begin
2700 FIndex := a;
2701 Break;
2702 end;
2704 if FIndex < FHeight then
2705 FStartLine := 0
2706 else
2707 FStartLine := Min(FIndex, Length(FItems)-FHeight);
2708 end;
2710 procedure TGUIListBox.FSetIndex(aIndex: Integer);
2711 begin
2712 if FItems = nil then
2713 Exit;
2715 if (aIndex < 0) or (aIndex > High(FItems)) then
2716 Exit;
2718 FIndex := aIndex;
2720 if FIndex <= FHeight then
2721 FStartLine := 0
2722 else
2723 FStartLine := Min(FIndex, Length(FItems)-FHeight);
2724 end;
2726 { TGUIFileListBox }
2728 procedure TGUIFileListBox.OnMessage(var Msg: TMessage);
2729 var
2730 a: Integer;
2731 begin
2732 if not FEnabled then
2733 Exit;
2735 if FItems = nil then
2736 Exit;
2738 with Msg do
2739 case Msg of
2740 WM_KEYDOWN:
2741 case wParam of
2742 IK_HOME, IK_KPHOME:
2743 begin
2744 FIndex := 0;
2745 FStartLine := 0;
2746 if @FOnChangeEvent <> nil then
2747 FOnChangeEvent(Self);
2748 end;
2750 IK_END, IK_KPEND:
2751 begin
2752 FIndex := High(FItems);
2753 FStartLine := Max(High(FItems)-FHeight+1, 0);
2754 if @FOnChangeEvent <> nil then
2755 FOnChangeEvent(Self);
2756 end;
2758 IK_PAGEUP, IK_KPPAGEUP:
2759 begin
2760 if FIndex > FHeight then
2761 FIndex := FIndex-FHeight
2762 else
2763 FIndex := 0;
2765 if FStartLine > FHeight then
2766 FStartLine := FStartLine-FHeight
2767 else
2768 FStartLine := 0;
2769 end;
2771 IK_PAGEDN, IK_KPPAGEDN:
2772 begin
2773 if FIndex < High(FItems)-FHeight then
2774 FIndex := FIndex+FHeight
2775 else
2776 FIndex := High(FItems);
2778 if FStartLine < High(FItems)-FHeight then
2779 FStartLine := FStartLine+FHeight
2780 else
2781 FStartLine := High(FItems)-FHeight+1;
2782 end;
2784 IK_UP, IK_LEFT, IK_KPUP, IK_KPLEFT:
2785 if FIndex > 0 then
2786 begin
2787 Dec(FIndex);
2788 if FIndex < FStartLine then
2789 Dec(FStartLine);
2790 if @FOnChangeEvent <> nil then
2791 FOnChangeEvent(Self);
2792 end;
2794 IK_DOWN, IK_RIGHT, IK_KPDOWN, IK_KPRIGHT:
2795 if FIndex < High(FItems) then
2796 begin
2797 Inc(FIndex);
2798 if FIndex > FStartLine+FHeight-1 then
2799 Inc(FStartLine);
2800 if @FOnChangeEvent <> nil then
2801 FOnChangeEvent(Self);
2802 end;
2804 IK_RETURN, IK_KPRETURN:
2805 with FWindow do
2806 begin
2807 if FActiveControl <> Self then
2808 SetActive(Self)
2809 else
2810 begin
2811 if FItems[FIndex][1] = #29 then // Ïàïêà
2812 begin
2813 OpenDir(FPath+Copy(FItems[FIndex], 2, 255));
2814 FIndex := 0;
2815 Exit;
2816 end;
2818 if FDefControl <> '' then
2819 SetActive(GetControl(FDefControl))
2820 else
2821 SetActive(nil);
2822 end;
2823 end;
2824 end;
2826 WM_CHAR:
2827 for a := 0 to High(FItems) do
2828 if ( (Length(FItems[a]) > 0) and
2829 (LowerCase(FItems[a][1]) = LowerCase(Chr(wParam))) ) or
2830 ( (Length(FItems[a]) > 1) and
2831 (FItems[a][1] = #29) and // Ïàïêà
2832 (LowerCase(FItems[a][2]) = LowerCase(Chr(wParam))) ) then
2833 begin
2834 FIndex := a;
2835 FStartLine := Min(Max(FIndex-1, 0), Length(FItems)-FHeight);
2836 if @FOnChangeEvent <> nil then
2837 FOnChangeEvent(Self);
2838 Break;
2839 end;
2840 end;
2841 end;
2843 procedure TGUIFileListBox.OpenDir(path: String);
2844 var
2845 SR: TSearchRec;
2846 i: Integer;
2847 sm, sc: string;
2848 begin
2849 Clear();
2851 path := IncludeTrailingPathDelimiter(path);
2852 path := ExpandFileName(path);
2854 // Êàòàëîãè:
2855 if FDirs then
2856 begin
2857 if FindFirst(path+'*', faDirectory, SR) = 0 then
2858 repeat
2859 if not LongBool(SR.Attr and faDirectory) then
2860 Continue;
2861 if (SR.Name = '.') or
2862 ((SR.Name = '..') and (path = ExpandFileName(FBasePath))) then
2863 Continue;
2865 AddItem(#1 + SR.Name);
2866 until FindNext(SR) <> 0;
2868 FindClose(SR);
2869 end;
2871 // Ôàéëû:
2872 sm := FFileMask;
2873 while sm <> '' do
2874 begin
2875 i := Pos('|', sm);
2876 if i = 0 then i := length(sm)+1;
2877 sc := Copy(sm, 1, i-1);
2878 Delete(sm, 1, i);
2879 if FindFirst(path+sc, faAnyFile, SR) = 0 then repeat AddItem(SR.Name); until FindNext(SR) <> 0;
2880 FindClose(SR);
2881 end;
2883 for i := 0 to High(FItems) do
2884 if FItems[i][1] = #1 then
2885 FItems[i][1] := #29;
2887 FPath := path;
2888 end;
2890 procedure TGUIFileListBox.SetBase(path: String);
2891 begin
2892 FBasePath := path;
2893 OpenDir(FBasePath);
2894 end;
2896 function TGUIFileListBox.SelectedItem(): String;
2897 begin
2898 Result := '';
2900 if (FIndex = -1) or (FItems = nil) or
2901 (FIndex > High(FItems)) or
2902 (FItems[FIndex][1] = '/') or
2903 (FItems[FIndex][1] = '\') then
2904 Exit;
2906 Result := FPath + FItems[FIndex];
2907 end;
2909 procedure TGUIFileListBox.UpdateFileList();
2910 var
2911 fn: String;
2912 begin
2913 if (FIndex = -1) or (FItems = nil) or
2914 (FIndex > High(FItems)) or
2915 (FItems[FIndex][1] = '/') or
2916 (FItems[FIndex][1] = '\') then
2917 fn := ''
2918 else
2919 fn := FItems[FIndex];
2921 OpenDir(FPath);
2923 if fn <> '' then
2924 SelectItem(fn);
2925 end;
2927 { TGUIMemo }
2929 procedure TGUIMemo.Clear;
2930 begin
2931 FLines := nil;
2932 FStartLine := 0;
2933 end;
2935 constructor TGUIMemo.Create(FontID: DWORD; Width, Height: Word);
2936 begin
2937 inherited Create();
2939 FFont := TFont.Create(FontID, FONT_CHAR);
2941 FWidth := Width;
2942 FHeight := Height;
2943 FDrawBack := True;
2944 FDrawScroll := True;
2945 end;
2947 procedure TGUIMemo.Draw;
2948 var
2949 a: Integer;
2950 begin
2951 inherited;
2953 if FDrawBack then DrawBox(FX, FY, FWidth+1, FHeight);
2954 if FDrawScroll then
2955 DrawScroll(FX+4+FWidth*16, FY+4, FHeight, (FStartLine > 0) and (FLines <> nil),
2956 (FStartLine+FHeight-1 < High(FLines)) and (FLines <> nil));
2958 if FLines <> nil then
2959 for a := FStartLine to Min(High(FLines), FStartLine+FHeight-1) do
2960 FFont.Draw(FX+4, FY+4+(a-FStartLine)*16, FLines[a], FColor.R, FColor.G, FColor.B);
2961 end;
2963 function TGUIMemo.GetHeight: Word;
2964 begin
2965 Result := 8+FHeight*16;
2966 end;
2968 function TGUIMemo.GetWidth: Word;
2969 begin
2970 Result := 8+(FWidth+1)*16;
2971 end;
2973 procedure TGUIMemo.OnMessage(var Msg: TMessage);
2974 begin
2975 if not FEnabled then Exit;
2977 inherited;
2979 if FLines = nil then Exit;
2981 with Msg do
2982 case Msg of
2983 WM_KEYDOWN:
2984 case wParam of
2985 IK_UP, IK_LEFT, IK_KPUP, IK_KPLEFT:
2986 if FStartLine > 0 then
2987 Dec(FStartLine);
2988 IK_DOWN, IK_RIGHT, IK_KPDOWN, IK_KPRIGHT:
2989 if FStartLine < Length(FLines)-FHeight then
2990 Inc(FStartLine);
2991 IK_RETURN, IK_KPRETURN:
2992 with FWindow do
2993 begin
2994 if FActiveControl <> Self then
2995 begin
2996 SetActive(Self);
2997 {FStartLine := 0;}
2998 end
2999 else
3000 if FDefControl <> '' then SetActive(GetControl(FDefControl))
3001 else SetActive(nil);
3002 end;
3003 end;
3004 end;
3005 end;
3007 procedure TGUIMemo.SetText(Text: string);
3008 begin
3009 FStartLine := 0;
3010 FLines := GetLines(Text, FFont.ID, FWidth*16);
3011 end;
3013 { TGUIimage }
3015 procedure TGUIimage.ClearImage();
3016 begin
3017 if FImageRes = '' then Exit;
3019 g_Texture_Delete(FImageRes);
3020 FImageRes := '';
3021 end;
3023 constructor TGUIimage.Create();
3024 begin
3025 inherited Create();
3027 FImageRes := '';
3028 end;
3030 destructor TGUIimage.Destroy();
3031 begin
3032 inherited;
3033 end;
3035 procedure TGUIimage.Draw();
3036 var
3037 ID: DWORD;
3038 begin
3039 inherited;
3041 if FImageRes = '' then
3042 begin
3043 if g_Texture_Get(FDefaultRes, ID) then e_Draw(ID, FX, FY, 0, True, False);
3044 end
3045 else
3046 if g_Texture_Get(FImageRes, ID) then e_Draw(ID, FX, FY, 0, True, False);
3047 end;
3049 procedure TGUIimage.OnMessage(var Msg: TMessage);
3050 begin
3051 inherited;
3052 end;
3054 procedure TGUIimage.SetImage(Res: string);
3055 begin
3056 ClearImage();
3058 if g_Texture_CreateWADEx(Res, Res) then FImageRes := Res;
3059 end;
3061 procedure TGUIimage.Update();
3062 begin
3063 inherited;
3064 end;
3066 end.