X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_gui.pas;h=ca49c711d8e7107ecda7cf0784dd8f62cfc7c9de;hb=7292fe409145dfcbb2776e34bb64d56e32985b9d;hp=e26ad7c05d796ca73a32e4442505a04fd3be7456;hpb=844441154d1220d6c83f75043300c2851ec87109;p=d2df-sdl.git diff --git a/src/game/g_gui.pas b/src/game/g_gui.pas index e26ad7c..ca49c71 100644 --- a/src/game/g_gui.pas +++ b/src/game/g_gui.pas @@ -1,9 +1,25 @@ +(* Copyright (C) DooM 2D:Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$INCLUDE g_amodes.inc} unit g_gui; interface uses - e_graphics, e_input, g_playermodel, g_basic, MAPSTRUCT, wadreader; + e_graphics, e_input, e_log, g_playermodel, g_basic, MAPSTRUCT, wadreader; const MAINMENU_HEADER_COLOR: TRGB = (R:255; G:255; B:255); @@ -99,16 +115,22 @@ type FWindow : TGUIWindow; FName: string; FUserData: Pointer; + FRightAlign: Boolean; //HACK! this works only for "normal" menus, only for menu text labels, and generally sux. sorry. + FMaxWidth: Integer; //HACK! used for right-aligning labels public constructor Create; procedure OnMessage(var Msg: TMessage); virtual; procedure Update; virtual; procedure Draw; virtual; + function GetWidth(): Integer; virtual; + function GetHeight(): Integer; virtual; + function WantActivationKey (key: LongInt): Boolean; virtual; property X: Integer read FX write FX; property Y: Integer read FY write FY; property Enabled: Boolean read FEnabled write FEnabled; property Name: string read FName write FName; property UserData: Pointer read FUserData write FUserData; + property RightAlign: Boolean read FRightAlign write FRightAlign; // for menu end; TGUIWindow = class @@ -160,8 +182,8 @@ type procedure OnMessage(var Msg: TMessage); override; procedure Update(); override; procedure Draw(); override; - function GetWidth(): Integer; - function GetHeight(): Integer; + function GetWidth(): Integer; override; + function GetHeight(): Integer; override; procedure Click(Silent: Boolean = False); property Caption: string read FText write FText; property Color: TRGB read FColor write FColor; @@ -180,8 +202,8 @@ type constructor Create(Text: string; FontID: DWORD); procedure OnMessage(var Msg: TMessage); override; procedure Draw; override; - function GetWidth: Integer; - function GetHeight: Integer; + function GetWidth: Integer; override; + function GetHeight: Integer; override; property OnClick: TOnClickEvent read FOnClickEvent write FOnClickEvent; property FixedLength: Word read FFixedLen write FFixedLen; property Text: string read FText write FText; @@ -204,7 +226,7 @@ type procedure OnMessage(var Msg: TMessage); override; procedure Update; override; procedure Draw; override; - function GetWidth(): Word; + function GetWidth(): Integer; override; property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent; property Max: Word read FMax write FMax; property Value: Integer read FValue write FSetValue; @@ -223,7 +245,7 @@ type procedure AddItem(Item: string); procedure Update; override; procedure Draw; override; - function GetWidth(): Word; + function GetWidth(): Integer; override; function GetText: string; property ItemIndex: Integer read FIndex write FIndex; property Color: TRGB read FColor write FColor; @@ -251,7 +273,7 @@ type procedure OnMessage(var Msg: TMessage); override; procedure Update; override; procedure Draw; override; - function GetWidth(): Word; + function GetWidth(): Integer; override; property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent; property OnEnter: TOnEnterEvent read FOnEnterEvent write FOnEnterEvent; property Width: Word read FWidth write FWidth; @@ -272,12 +294,35 @@ type constructor Create(FontID: DWORD); procedure OnMessage(var Msg: TMessage); override; procedure Draw; override; - function GetWidth(): Word; + function GetWidth(): Integer; override; + function WantActivationKey (key: LongInt): Boolean; override; property Key: Word read FKey write FKey; property Color: TRGB read FColor write FColor; property Font: TFont read FFont write FFont; end; + // can hold two keys + TGUIKeyRead2 = class(TGUIControl) + private + FFont: TFont; + FFontID: DWORD; + FColor: TRGB; + FKey0, FKey1: Word; // this should be an array. sorry. + FKeyIdx: Integer; + FIsQuery: Boolean; + FMaxKeyNameWdt: Integer; + public + constructor Create(FontID: DWORD); + procedure OnMessage(var Msg: TMessage); override; + procedure Draw; override; + function GetWidth(): Integer; override; + function WantActivationKey (key: LongInt): Boolean; override; + property Key0: Word read FKey0 write FKey0; + property Key1: Word read FKey1 write FKey1; + property Color: TRGB read FColor write FColor; + property Font: TFont read FFont write FFont; + end; + TGUIModelView = class(TGUIControl) private FModel: TPlayerModel; @@ -356,8 +401,8 @@ type procedure AddItem(Item: String); procedure SelectItem(Item: String); procedure Clear(); - function GetWidth(): Word; - function GetHeight(): Word; + function GetWidth(): Integer; override; + function GetHeight(): Integer; override; function SelectedItem(): String; property OnChange: TOnChangeEvent read FOnChangeEvent write FOnChangeEvent; @@ -406,8 +451,8 @@ type procedure OnMessage(var Msg: TMessage); override; procedure Draw; override; procedure Clear; - function GetWidth(): Word; - function GetHeight(): Word; + function GetWidth(): Integer; override; + function GetHeight(): Integer; override; procedure SetText(Text: string); property DrawBack: Boolean read FDrawBack write FDrawBack; property DrawScrollBar: Boolean read FDrawScroll write FDrawScroll; @@ -469,6 +514,7 @@ type function AddSwitch(fText: string): TGUISwitch; function AddEdit(fText: string): TGUIEdit; function AddKeyRead(fText: string): TGUIKeyRead; + function AddKeyRead2(fText: string): TGUIKeyRead2; function AddList(fText: string; Width, Height: Word): TGUIListBox; function AddFileList(fText: string; Width, Height: Word): TGUIFileListBox; function AddMemo(fText: string; Width, Height: Word): TGUIMemo; @@ -816,6 +862,8 @@ begin FY := 0; FEnabled := True; + FRightAlign := false; + FMaxWidth := -1; end; procedure TGUIControl.OnMessage(var Msg: TMessage); @@ -826,12 +874,25 @@ end; procedure TGUIControl.Update(); begin - end; procedure TGUIControl.Draw(); begin +end; + +function TGUIControl.WantActivationKey (key: LongInt): Boolean; +begin + result := false; +end; + +function TGUIControl.GetWidth(): Integer; +begin + result := 0; +end; +function TGUIControl.GetHeight(): Integer; +begin + result := 0; end; { TGUITextButton } @@ -1161,8 +1222,18 @@ begin end; procedure TGUILabel.Draw; +var + w, h: Word; begin - FFont.Draw(FX, FY, FText, FColor.R, FColor.G, FColor.B); + if RightAlign then + begin + FFont.GetTextSize(FText, w, h); + FFont.Draw(FX+FMaxWidth-w, FY, FText, FColor.R, FColor.G, FColor.B); + end + else + begin + FFont.Draw(FX, FY, FText, FColor.R, FColor.G, FColor.B); + end; end; function TGUILabel.GetHeight: Integer; @@ -1352,6 +1423,11 @@ begin begin x := FItems[FIndex].Text.FX; y := FItems[FIndex].Text.FY; + //HACK! + if FItems[FIndex].Text.RightAlign then + begin + x := x+FItems[FIndex].Text.FMaxWidth-FItems[FIndex].Text.GetWidth; + end; end else if FItems[FIndex].Control <> nil then begin @@ -1428,6 +1504,14 @@ begin if not ok then Exit; + if (Msg.Msg = WM_KEYDOWN) and (FIndex <> -1) and (FItems[FIndex].Control <> nil) and + (FItems[FIndex].Control.WantActivationKey(Msg.wParam)) then + begin + FItems[FIndex].Control.OnMessage(Msg); + g_Sound_PlayEx(MENU_CLICKSOUND); + exit; + end; + case Msg.Msg of WM_KEYDOWN: begin @@ -1511,10 +1595,27 @@ end; procedure TGUIMenu.ReAlign(); var a, tx, cx, w, h: Integer; + cww: array of Integer; // cached widths + maxcww: Integer; begin if FItems = nil then Exit; - if not FAlign then tx := FLeft else + SetLength(cww, length(FItems)); + maxcww := 0; + for a := 0 to High(FItems) do + begin + if FItems[a].Text <> nil then + begin + cww[a] := FItems[a].Text.GetWidth; + if maxcww < cww[a] then maxcww := cww[a]; + end; + end; + + if not FAlign then + begin + tx := FLeft; + end + else begin tx := gScreenWidth; for a := 0 to High(FItems) do @@ -1524,27 +1625,17 @@ begin if FItems[a].Control <> nil then begin w := w+MENU_HSPACE; - - if FItems[a].ControlType = TGUILabel then - w := w+(FItems[a].Control as TGUILabel).GetWidth - else if FItems[a].ControlType = TGUITextButton then - w := w+(FItems[a].Control as TGUITextButton).GetWidth - else if FItems[a].ControlType = TGUIScroll then - w := w+(FItems[a].Control as TGUIScroll).GetWidth - else if FItems[a].ControlType = TGUISwitch then - w := w+(FItems[a].Control as TGUISwitch).GetWidth - else if FItems[a].ControlType = TGUIEdit then - w := w+(FItems[a].Control as TGUIEdit).GetWidth - else if FItems[a].ControlType = TGUIKeyRead then - w := w+(FItems[a].Control as TGUIKeyRead).GetWidth - else if (FItems[a].ControlType = TGUIListBox) then - w := w+(FItems[a].Control as TGUIListBox).GetWidth - else if (FItems[a].ControlType = TGUIFileListBox) then - w := w+(FItems[a].Control as TGUIFileListBox).GetWidth - else if FItems[a].ControlType = TGUIMemo then - w := w+(FItems[a].Control as TGUIMemo).GetWidth; + if FItems[a].ControlType = TGUILabel then w := w+(FItems[a].Control as TGUILabel).GetWidth + else if FItems[a].ControlType = TGUITextButton then w := w+(FItems[a].Control as TGUITextButton).GetWidth + else if FItems[a].ControlType = TGUIScroll then w := w+(FItems[a].Control as TGUIScroll).GetWidth + else if FItems[a].ControlType = TGUISwitch then w := w+(FItems[a].Control as TGUISwitch).GetWidth + else if FItems[a].ControlType = TGUIEdit then w := w+(FItems[a].Control as TGUIEdit).GetWidth + else if FItems[a].ControlType = TGUIKeyRead then w := w+(FItems[a].Control as TGUIKeyRead).GetWidth + else if FItems[a].ControlType = TGUIKeyRead2 then w := w+(FItems[a].Control as TGUIKeyRead2).GetWidth + else if FItems[a].ControlType = TGUIListBox then w := w+(FItems[a].Control as TGUIListBox).GetWidth + else if FItems[a].ControlType = TGUIFileListBox then w := w+(FItems[a].Control as TGUIFileListBox).GetWidth + else if FItems[a].ControlType = TGUIMemo then w := w+(FItems[a].Control as TGUIMemo).GetWidth; end; - tx := Min(tx, (gScreenWidth div 2)-(w div 2)); end; end; @@ -1587,35 +1678,46 @@ begin end; for a := 0 to High(FItems) do + begin with FItems[a] do begin if Text <> nil then + begin with Text do begin FX := tx; FY := h; end; + //HACK! + if Text.RightAlign and (length(cww) > a) then + begin + //Text.FX := Text.FX+maxcww; + Text.FMaxWidth := maxcww; + end; + end; - if Control <> nil then - with Control do - if Text <> nil then - begin - FX := cx; - FY := h; - end - else - begin - FX := tx; - FY := h; - end; + if Control <> nil then + begin + with Control do + begin + if Text <> nil then + begin + FX := cx; + FY := h; + end + else + begin + FX := tx; + FY := h; + end; + end; + end; - if (ControlType = TGUIListBox) or (ControlType = TGUIFileListBox) then - Inc(h, (Control as TGUIListBox).GetHeight+MENU_VSPACE) - else if ControlType = TGUIMemo then - Inc(h, (Control as TGUIMemo).GetHeight+MENU_VSPACE) - else - Inc(h, e_CharFont_GetMaxHeight(FFontID)+MENU_VSPACE); + if (ControlType = TGUIListBox) or (ControlType = TGUIFileListBox) then Inc(h, (Control as TGUIListBox).GetHeight+MENU_VSPACE) + else if ControlType = TGUIMemo then Inc(h, (Control as TGUIMemo).GetHeight+MENU_VSPACE) + else Inc(h, e_CharFont_GetMaxHeight(FFontID)+MENU_VSPACE); end; + end; // another ugly hack if FYesNo and (length(FItems) > 1) then @@ -1767,6 +1869,37 @@ begin ReAlign(); end; +function TGUIMenu.AddKeyRead2(fText: string): TGUIKeyRead2; +var + i: Integer; +begin + i := NewItem(); + with FItems[i] do + begin + Control := TGUIKeyRead2.Create(FFontID); + with Control as TGUIKeyRead2 do + begin + FWindow := Self.FWindow; + FColor := MENU_ITEMSCTRL_COLOR; + end; + + Text := TGUILabel.Create(fText, FFontID); + with Text do + begin + FColor := MENU_ITEMSCTRL_COLOR; //MENU_ITEMSTEXT_COLOR; + RightAlign := true; + end; + + ControlType := TGUIKeyRead2; + + Result := (Control as TGUIKeyRead2); + end; + + if FIndex = -1 then FIndex := i; + + ReAlign(); +end; + function TGUIMenu.AddList(fText: string; Width, Height: Word): TGUIListBox; var i: Integer; @@ -1945,7 +2078,7 @@ begin if a > FMax then FValue := FMax else FValue := a; end; -function TGUIScroll.GetWidth: Word; +function TGUIScroll.GetWidth: Integer; begin Result := 16+(FMax+1)*8; end; @@ -2017,7 +2150,7 @@ begin else Result := ''; end; -function TGUISwitch.GetWidth: Word; +function TGUISwitch.GetWidth: Integer; var a: Integer; w, h: Word; @@ -2114,7 +2247,7 @@ begin end; end; -function TGUIEdit.GetWidth: Word; +function TGUIEdit.GetWidth: Integer; begin Result := 16+FWidth*16; end; @@ -2194,6 +2327,8 @@ end; constructor TGUIKeyRead.Create(FontID: DWORD); begin inherited Create(); + FKey := 0; + FIsQuery := false; FFont := TFont.Create(FontID, FONT_CHAR); end; @@ -2206,7 +2341,7 @@ begin FColor.R, FColor.G, FColor.B); end; -function TGUIKeyRead.GetWidth: Word; +function TGUIKeyRead.GetWidth: Integer; var a: Byte; w, h: Word; @@ -2226,7 +2361,23 @@ begin if w > Result then Result := w; end; +function TGUIKeyRead.WantActivationKey (key: LongInt): Boolean; +begin + result := + (key = IK_BACKSPACE) or + false; // oops +end; + procedure TGUIKeyRead.OnMessage(var Msg: TMessage); + procedure actDefCtl (); + begin + with FWindow do + if FDefControl <> '' then + SetActive(GetControl(FDefControl)) + else + SetActive(nil); + end; + begin inherited; @@ -2239,13 +2390,7 @@ begin case wParam of IK_ESCAPE: begin - if FIsQuery then - with FWindow do - if FDefControl <> '' then - SetActive(GetControl(FDefControl)) - else - SetActive(nil); - + if FIsQuery then actDefCtl(); FIsQuery := False; end; IK_RETURN, IK_KPRETURN: @@ -2262,32 +2407,198 @@ begin begin FKey := IK_ENTER; // FIsQuery := False; + actDefCtl(); + end; + end; + IK_BACKSPACE: // clear keybinding if we aren't waiting for a key + begin + if not FIsQuery then + begin + FKey := 0; + actDefCtl(); + end; + end; + end; + + MESSAGE_DIKEY: + begin + if not FIsQuery and (wParam = IK_BACKSPACE) then + begin + FKey := 0; + actDefCtl(); + end + else if FIsQuery and (wParam <> IK_ENTER) and (wParam <> IK_KPRETURN) then // Not '' then + FKey := wParam; + FIsQuery := False; + actDefCtl(); + end; + end; + end; +end; + +{ TGUIKeyRead2 } + +constructor TGUIKeyRead2.Create(FontID: DWORD); +var + a: Byte; + w, h: Word; +begin + inherited Create(); + + FKey0 := 0; + FKey1 := 0; + FKeyIdx := 0; + FIsQuery := False; + FFontID := FontID; + FFont := TFont.Create(FontID, FONT_CHAR); + + FMaxKeyNameWdt := 0; + for a := 0 to 255 do + begin + FFont.GetTextSize(e_KeyNames[a], w, h); + FMaxKeyNameWdt := Max(FMaxKeyNameWdt, w); + end; + + FMaxKeyNameWdt := FMaxKeyNameWdt-(FMaxKeyNameWdt div 3); + + FFont.GetTextSize(KEYREAD_QUERY, w, h); + if w > FMaxKeyNameWdt then FMaxKeyNameWdt := w; + + FFont.GetTextSize(KEYREAD_CLEAR, w, h); + if w > FMaxKeyNameWdt then FMaxKeyNameWdt := w; +end; + +procedure TGUIKeyRead2.Draw; + procedure drawText (idx: Integer); + var + x, y: Integer; + r, g, b: Byte; + kk: DWORD; + begin + if idx = 0 then kk := FKey0 else kk := FKey1; + y := FY; + if idx = 0 then x := FX+8 else x := FX+8+FMaxKeyNameWdt+16; + r := 255; + g := 0; + b := 0; + if FKeyIdx = idx then begin r := 255; g := 255; b := 255; end; + if FIsQuery and (FKeyIdx = idx) then + FFont.Draw(x, y, KEYREAD_QUERY, r, g, b) + else + FFont.Draw(x, y, IfThen(kk <> 0, e_KeyNames[kk], KEYREAD_CLEAR), r, g, b); + end; + +begin + inherited; + + //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); + //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); + drawText(0); + drawText(1); +end; + +function TGUIKeyRead2.GetWidth: Integer; +begin + Result := FMaxKeyNameWdt*2+8+8+16; +end; + +function TGUIKeyRead2.WantActivationKey (key: LongInt): Boolean; +begin + result := + (key = IK_BACKSPACE) or + (key = IK_LEFT) or (key = IK_RIGHT) or + (key = IK_KPLEFT) or (key = IK_KPRIGHT) or + false; // oops +end; + +procedure TGUIKeyRead2.OnMessage(var Msg: TMessage); + procedure actDefCtl (); + begin + with FWindow do + if FDefControl <> '' then + SetActive(GetControl(FDefControl)) + else + SetActive(nil); + end; + +begin + inherited; + + if not FEnabled then + Exit; + + with Msg do + case Msg of + WM_KEYDOWN: + case wParam of + IK_ESCAPE: + begin + if FIsQuery then actDefCtl(); + FIsQuery := False; + end; + IK_RETURN, IK_KPRETURN: + begin + if not FIsQuery then + begin with FWindow do - if FDefControl <> '' then - SetActive(GetControl(FDefControl)) - else - SetActive(nil); + if FActiveControl <> Self then + SetActive(Self); + + FIsQuery := True; + end + else + begin + if (FKeyIdx = 0) then FKey0 := IK_ENTER else FKey1 := IK_ENTER; // + FIsQuery := False; + actDefCtl(); end; end; + IK_BACKSPACE: // clear keybinding if we aren't waiting for a key + begin + if not FIsQuery then + begin + if (FKeyIdx = 0) then FKey0 := 0 else FKey1 := 0; + actDefCtl(); + end; + end; + IK_LEFT, IK_KPLEFT: + if not FIsQuery then + begin + FKeyIdx := 0; + actDefCtl(); + end; + IK_RIGHT, IK_KPRIGHT: + if not FIsQuery then + begin + FKeyIdx := 1; + actDefCtl(); + end; end; MESSAGE_DIKEY: - if FIsQuery and (wParam <> IK_ENTER) and (wParam <> IK_KPRETURN) then // Not '' then - FKey := wParam; - FIsQuery := False; - - with FWindow do - if FDefControl <> '' then - SetActive(GetControl(FDefControl)) - else - SetActive(nil); + if not FIsQuery and (wParam = IK_BACKSPACE) then + begin + if (FKeyIdx = 0) then FKey0 := 0 else FKey1 := 0; + actDefCtl(); + end + else if FIsQuery and (wParam <> IK_ENTER) and (wParam <> IK_KPRETURN) then // Not '' then + begin + if (FKeyIdx = 0) then FKey0 := wParam else FKey1 := wParam; + end; + FIsQuery := False; + actDefCtl(); + end; end; end; end; + { TGUIModelView } constructor TGUIModelView.Create; @@ -2329,7 +2640,7 @@ begin if FModel = nil then Exit; - if FModel.Weapon < WEAPON_SUPERPULEMET then + if FModel.Weapon < WP_LAST then FModel.SetWeapon(FModel.Weapon+1) else FModel.SetWeapon(WEAPON_KASTET); @@ -2468,12 +2779,12 @@ var panels: TPanelsRec1Array; header: TMapHeaderRec_1; a: Integer; - FileName, SectionName, ResName: string; + FileName: string; Data: Pointer; Len: Integer; rX, rY: Single; begin - g_ProcessResourceStr(Res, FileName, SectionName, ResName); + FileName := g_ExtractWadName(Res); WAD := TWADFile.Create(); if not WAD.ReadFile(FileName) then @@ -2482,7 +2793,8 @@ begin Exit; end; - if not WAD.GetResource('', ResName, Data, Len) then + //k8: ignores path again + if not WAD.GetMapResource(g_ExtractFileName(Res), Data, Len) then begin WAD.Free(); Exit; @@ -2648,12 +2960,12 @@ begin end; end; -function TGUIListBox.GetHeight: Word; +function TGUIListBox.GetHeight: Integer; begin Result := 8+FHeight*16; end; -function TGUIListBox.GetWidth: Word; +function TGUIListBox.GetWidth: Integer; begin Result := 8+(FWidth+1)*16; end; @@ -3017,12 +3329,12 @@ begin FFont.Draw(FX+4, FY+4+(a-FStartLine)*16, FLines[a], FColor.R, FColor.G, FColor.B); end; -function TGUIMemo.GetHeight: Word; +function TGUIMemo.GetHeight: Integer; begin Result := 8+FHeight*16; end; -function TGUIMemo.GetWidth: Word; +function TGUIMemo.GetWidth: Integer; begin Result := 8+(FWidth+1)*16; end;