X-Git-Url: https://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Fgame%2Fg_holmes_ui.inc;h=f91ab1937f2ab50f496803255ebf6ebecbada50e;hb=f924968c450e1dc566b3abdde8d2aeac4de11fd0;hp=e903279ac3e0cd0360810387a76776dcad7de4db;hpb=f6c2d91ac9b65421c783b94ba4b64749b7795051;p=d2df-sdl.git diff --git a/src/game/g_holmes_ui.inc b/src/game/g_holmes_ui.inc index e903279..f91ab19 100644 --- a/src/game/g_holmes_ui.inc +++ b/src/game/g_holmes_ui.inc @@ -15,7 +15,10 @@ *) // ////////////////////////////////////////////////////////////////////////// // type - THControl = class + THControl = class(TPoolObject) + public + type TActionCB = procedure (me: THControl; uinfo: Integer); + private mParent: THControl; mX, mY: Integer; @@ -66,6 +69,9 @@ type // modifies rect0 class function intersectRect (var x0, y0, w0, h0: Integer; const x1, y1, w1, h1: Integer): Boolean; + public + actionCB: TActionCB; + public constructor Create (ax, ay, aw, ah: Integer; aparent: THControl=nil); destructor Destroy (); override; @@ -121,9 +127,14 @@ type protected procedure blurred (); override; + public + closeCB: TActionCB; // called after window was removed from ui window list + public constructor Create (const atitle: AnsiString; ax, ay: Integer; aw: Integer=-1; ah: Integer=-1); + procedure centerInScreen (); + // `sx` and `sy` are screen coordinates procedure drawControl (sx, sy: Integer); override; procedure drawControlPost (sx, sy: Integer); override; @@ -133,17 +144,49 @@ type end; + THCtlSimpleText = class(THControl) + private + type + PItem = ^TItem; + TItem = record + title: AnsiString; + centered: Boolean; + hline: Boolean; + end; + private + mItems: array of TItem; + + public + constructor Create (ax, ay: Integer; aparent: THControl=nil); + destructor Destroy (); override; + + procedure appendItem (const atext: AnsiString; acentered: Boolean=false; ahline: Boolean=false); + + procedure drawControl (sx, sy: Integer); override; + + function mouseEvent (var ev: THMouseEvent): Boolean; override; + function keyEvent (var ev: THKeyEvent): Boolean; override; + end; + + THCtlCBListBox = class(THControl) private - mItems: array of AnsiString; - mChecks: array of PBoolean; + type + PItem = ^TItem; + TItem = record + title: AnsiString; + varp: PBoolean; + actionCB: TActionCB; + end; + private + mItems: array of TItem; mCurIndex: Integer; public constructor Create (ax, ay: Integer; aparent: THControl=nil); destructor Destroy (); override; - procedure appendItem (const atext: AnsiString; bv: PBoolean); + procedure appendItem (const atext: AnsiString; bv: PBoolean; aaction: TActionCB=nil); procedure drawControl (sx, sy: Integer); override; @@ -151,6 +194,7 @@ type function keyEvent (var ev: THKeyEvent): Boolean; override; end; + // ////////////////////////////////////////////////////////////////////////// // var uiTopList: array of THControl = nil; @@ -251,6 +295,10 @@ begin ctl.blurred(); for c := f+1 to High(uiTopList) do uiTopList[c-1] := uiTopList[c]; SetLength(uiTopList, Length(uiTopList)-1); + if (ctl is THTopWindow) then + begin + if assigned(THTopWindow(ctl).closeCB) then THTopWindow(ctl).closeCB(ctl, 0); + end; exit; end; end; @@ -290,6 +338,7 @@ begin mEatKeys := false; scallowed := false; mDrawShadow := false; + actionCB := nil; end; @@ -615,6 +664,10 @@ end; procedure THControl.setScissorGLInternal (x, y, w, h: Integer); begin if not scallowed then exit; + x := trunc(x*g_holmes_ui_scale); + y := trunc(y*g_holmes_ui_scale); + w := trunc(w*g_holmes_ui_scale); + h := trunc(h*g_holmes_ui_scale); y := gWinSizeY-(y+h); if not intersectRect(x, y, w, h, scxywh[0], scxywh[1], scxywh[2], scxywh[3]) then glScissor(0, 0, 0, 0) else glScissor(x, y, w, h); end; @@ -719,6 +772,10 @@ begin begin if (ctl <> topLevel.mFocused) then ctl.setFocused(true); result := ctl.mouseEvent(ev); + end + else if (ctl = self) and assigned(actionCB) then + begin + actionCB(self, 0); end; end; @@ -732,7 +789,7 @@ begin if (topLevel.mFocused <> self) and isMyChild(topLevel.mFocused) and topLevel.mFocused.mEnabled then result := topLevel.mFocused.keyEvent(ev); if (mParent = nil) then begin - if (ev.kstate = THKeyEvent.ModShift) and (ev.scan = SDL_SCANCODE_TAB) then + if (ev.kind = ev.Press) and (ev = 'S-Tab') then begin result := true; if (ev.kind = ev.Press) then @@ -746,7 +803,7 @@ begin end; exit; end; - if (ev.kstate = 0) and (ev.scan = SDL_SCANCODE_TAB) then + if (ev.kind = ev.Press) and (ev = 'Tab') then begin result := true; if (ev.kind = ev.Press) then @@ -760,7 +817,7 @@ begin end; exit; end; - if mEscClose and (ev.kind = ev.Press) and (ev.kstate = 0) and (ev.scan = SDL_SCANCODE_ESCAPE) then + if mEscClose and (ev.kind = ev.Press) and (ev = 'Escape') then begin result := true; uiRemoveWindow(self); @@ -788,6 +845,17 @@ begin mDrawShadow := true; mWaitingClose := false; mInClose := false; + closeCB := nil; +end; + + +procedure THTopWindow.centerInScreen (); +begin + if (mWidth > 0) and (mHeight > 0) then + begin + mX := trunc((gWinSizeX/g_holmes_ui_scale-mWidth)/2); + mY := trunc((gWinSizeY/g_holmes_ui_scale-mHeight)/2); + end; end; @@ -806,12 +874,12 @@ var begin if mDragging then begin - drawRect(mX+4, mY+4, mWidth-8, mHeight-8, r, g, b); + drawRectUI(mX+4, mY+4, mWidth-8, mHeight-8, r, g, b); end else begin - drawRect(mX+3, mY+3, mWidth-6, mHeight-6, r, g, b); - drawRect(mX+5, mY+5, mWidth-10, mHeight-10, r, g, b); + drawRectUI(mX+3, mY+3, mWidth-6, mHeight-6, r, g, b); + drawRectUI(mX+5, mY+5, mWidth-10, mHeight-10, r, g, b); setScissor(mFrameWidth, 0, 3*8, 8); fillRect(mX+mFrameWidth, mY, 3*8, 8, 0, 0, 128); drawText8(mX+mFrameWidth, mY, '[ ]', r, g, b); @@ -821,7 +889,7 @@ begin if (Length(mTitle) > 0) then begin setScissor(mFrameWidth+3*8, 0, mWidth-mFrameWidth*2-3*8, 8); - tx := mX+(mWidth-Length(mTitle)*8) div 2; + tx := (mX+3*8)+((mWidth-3*8)-Length(mTitle)*8) div 2; fillRect(tx-3, mY, Length(mTitle)*8+3+2, 8, 0, 0, 128); drawText8(tx, mY, mTitle, r, g, b); end; @@ -842,7 +910,7 @@ function THTopWindow.keyEvent (var ev: THKeyEvent): Boolean; begin result := inherited keyEvent(ev); if not getFocused then exit; - if (ev.kstate = ev.ModAlt) and (ev.kind = ev.Press) and (ev.scan = SDL_SCANCODE_F3) then + if (ev.kind = ev.Press) and (ev = 'M-F3') then begin uiRemoveWindow(self); result := true; @@ -935,11 +1003,92 @@ begin end; +// ////////////////////////////////////////////////////////////////////////// // +constructor THCtlSimpleText.Create (ax, ay: Integer; aparent: THControl=nil); +begin + mItems := nil; + inherited Create(ax, ay, 4, 4); +end; + + +destructor THCtlSimpleText.Destroy (); +begin + mItems := nil; + inherited; +end; + + +procedure THCtlSimpleText.appendItem (const atext: AnsiString; acentered: Boolean=false; ahline: Boolean=false); +var + it: PItem; +begin + if (Length(atext)*8+3*8+2 > mWidth) then mWidth := Length(atext)*8+3*8+2; + SetLength(mItems, Length(mItems)+1); + it := @mItems[High(mItems)]; + it.title := atext; + it.centered := acentered; + it.hline := ahline; + if (Length(mItems)*8 > mHeight) then mHeight := Length(mItems)*8; +end; + + +procedure THCtlSimpleText.drawControl (sx, sy: Integer); +var + f, tx: Integer; + it: PItem; + r, g, b: Integer; +begin + for f := 0 to High(mItems) do + begin + it := @mItems[f]; + tx := sx; + r := 255; + g := 255; + b := 0; + if it.centered then begin b := 255; tx := sx+(mWidth-Length(it.title)*8) div 2; end; + if it.hline then + begin + b := 255; + if (Length(it.title) = 0) then + begin + drawLine(sx+4, sy+3, sx+mWidth-8, sy+3, r, g, b); + end + else if (tx-3 > sx+4) then + begin + drawLine(sx+4, sy+3, tx-3, sy+3, r, g, b); + drawLine(tx+Length(it.title)*8, sy+3, sx+mWidth-4, sy+3, r, g, b); + end; + end; + drawText8(tx, sy, it.title, r, g, b); + Inc(sy, 8); + end; +end; + + +function THCtlSimpleText.mouseEvent (var ev: THMouseEvent): Boolean; +var + lx, ly: Integer; +begin + result := inherited mouseEvent(ev); + lx := ev.x; + ly := ev.y; + if not result and toLocal(lx, ly) then + begin + result := true; + end; +end; + + +function THCtlSimpleText.keyEvent (var ev: THKeyEvent): Boolean; +begin + result := inherited keyEvent(ev); +end; + + // ////////////////////////////////////////////////////////////////////////// // constructor THCtlCBListBox.Create (ax, ay: Integer; aparent: THControl=nil); begin mItems := nil; - mChecks := nil; mCurIndex := -1; inherited Create(ax, ay, 4, 4); end; @@ -948,19 +1097,21 @@ end; destructor THCtlCBListBox.Destroy (); begin mItems := nil; - mChecks := nil; inherited; end; -procedure THCtlCBListBox.appendItem (const atext: AnsiString; bv: PBoolean); +procedure THCtlCBListBox.appendItem (const atext: AnsiString; bv: PBoolean; aaction: TActionCB=nil); +var + it: PItem; begin - if (Length(atext)*8+4+3*8+2 > mWidth) then mWidth := Length(atext)*8+4+3*8+2; + if (Length(atext)*8+3*8+2 > mWidth) then mWidth := Length(atext)*8+3*8+2; SetLength(mItems, Length(mItems)+1); - mItems[High(mItems)] := atext; - SetLength(mChecks, Length(mChecks)+1); - mChecks[High(mChecks)] := bv; - if (Length(mItems)*8+4 > mHeight) then mHeight := Length(mItems)*8+4; + it := @mItems[High(mItems)]; + it.title := atext; + it.varp := bv; + it.actionCB := aaction; + if (Length(mItems)*8 > mHeight) then mHeight := Length(mItems)*8; if (mCurIndex < 0) then mCurIndex := 0; end; @@ -968,29 +1119,26 @@ end; procedure THCtlCBListBox.drawControl (sx, sy: Integer); var f, tx: Integer; + it: PItem; begin - //fillRect(sx, sy, mWidth, mHeight, 0, 128, 0); - Inc(sx, 2); - Inc(sy, 2); for f := 0 to High(mItems) do begin - if (mCurIndex = f) then fillRect(sx-2, sy, mWidth, 8, 0, 128, 0); - if (mChecks[f] <> nil) then + it := @mItems[f]; + if (mCurIndex = f) then fillRect(sx, sy, mWidth, 8, 0, 128, 0); + if (it.varp <> nil) then begin - //drawText8(sx, sy, '[ ]', 255, 255, 255); - //if mChecks[f]^ then drawText8(sx+6, sy, 'x', 255, 255, 255); - if mChecks[f]^ then drawText8(sx, sy, '[x]', 255, 255, 255) else drawText8(sx, sy, '[ ]', 255, 255, 255); - drawText8(sx+3*8+2, sy, mItems[f], 255, 255, 0); + if it.varp^ then drawText8(sx, sy, '[x]', 255, 255, 255) else drawText8(sx, sy, '[ ]', 255, 255, 255); + drawText8(sx+3*8+2, sy, it.title, 255, 255, 0); end - else if (Length(mItems[f]) > 0) then + else if (Length(it.title) > 0) then begin - tx := sx+(mWidth-Length(mItems[f])*8) div 2; + tx := sx+(mWidth-Length(it.title)*8) div 2; if (tx-3 > sx+4) then begin drawLine(sx+4, sy+3, tx-3, sy+3, 255, 255, 255); - drawLine(tx+Length(mItems[f])*8, sy+3, sx+mWidth-4, sy+3, 255, 255, 255); + drawLine(tx+Length(it.title)*8, sy+3, sx+mWidth-4, sy+3, 255, 255, 255); end; - drawText8(sx+(mWidth-Length(mItems[f])*8) div 2, sy, mItems[f], 255, 255, 255); + drawText8(tx, sy, it.title, 255, 255, 255); end else begin @@ -1004,21 +1152,27 @@ end; function THCtlCBListBox.mouseEvent (var ev: THMouseEvent): Boolean; var lx, ly: Integer; + it: PItem; begin result := inherited mouseEvent(ev); - if not result and (Length(mItems) > 0) and (ev.kind = ev.Press) then + lx := ev.x; + ly := ev.y; + if not result and toLocal(lx, ly) then begin - lx := ev.x; - ly := ev.y; - if toLocal(lx, ly) then + result := true; + if (ev.kind = ev.Press) and (ev = 'lmb') then begin - if (ly < 2) then ly := 2; ly := ly div 8; - if (ly < 0) then ly := 0 else if (ly > High(mItems)) then ly := High(mItems); - if (mChecks[ly] <> nil) then + if (ly >= 0) and (ly < Length(mItems)) then begin - mCurIndex := ly; - if (mChecks[ly] <> nil) then mChecks[ly]^ := not mChecks[ly]^; + it := @mItems[ly]; + if (it.varp <> nil) then + begin + mCurIndex := ly; + it.varp^ := not it.varp^; + if assigned(it.actionCB) then it.actionCB(self, Integer(it.varp^)); + if assigned(actionCB) then actionCB(self, ly); + end; end; end; end; @@ -1026,65 +1180,68 @@ end; function THCtlCBListBox.keyEvent (var ev: THKeyEvent): Boolean; +var + it: PItem; begin result := inherited keyEvent(ev); if not getFocused then exit; //result := true; - if (ev.kstate = 0) and (ev.kind = ev.Press) then + if (ev.kind = ev.Press) then begin - case ev.scan of - SDL_SCANCODE_HOME, - SDL_SCANCODE_PAGEUP: - begin - result := true; - mCurIndex := 0; - end; - SDL_SCANCODE_END, - SDL_SCANCODE_PAGEDOWN: - begin - result := true; - mCurIndex := High(mItems); - end; - SDL_SCANCODE_UP: - begin - result := true; - if (Length(mItems) > 0) then - begin - if (mCurIndex < 0) then mCurIndex := Length(mItems); - while (mCurIndex > 0) do - begin - Dec(mCurIndex); - if (mChecks[mCurIndex] <> nil) then break; - end; - end - else - begin - mCurIndex := -1; - end; - end; - SDL_SCANCODE_DOWN: + if (ev = 'Home') or (ev = 'PageUp') then + begin + result := true; + mCurIndex := 0; + end; + if (ev = 'End') or (ev = 'PageDown') then + begin + result := true; + mCurIndex := High(mItems); + end; + if (ev = 'Up') then + begin + result := true; + if (Length(mItems) > 0) then + begin + if (mCurIndex < 0) then mCurIndex := Length(mItems); + while (mCurIndex > 0) do begin - result := true; - if (Length(mItems) > 0) then - begin - if (mCurIndex < 0) then mCurIndex := -1; - while (mCurIndex < High(mItems)) do - begin - Inc(mCurIndex); - if (mChecks[mCurIndex] <> nil) then break; - end; - end - else - begin - mCurIndex := -1; - end; + Dec(mCurIndex); + if (mItems[mCurIndex].varp <> nil) then break; end; - SDL_SCANCODE_SPACE, - SDL_SCANCODE_RETURN: + end + else + begin + mCurIndex := -1; + end; + end; + if (ev = 'Down') then + begin + result := true; + if (Length(mItems) > 0) then + begin + if (mCurIndex < 0) then mCurIndex := -1; + while (mCurIndex < High(mItems)) do begin - result := true; - if (mCurIndex >= 0) and (mCurIndex < Length(mChecks)) and (mChecks[mCurIndex] <> nil) then mChecks[mCurIndex]^ := not mChecks[mCurIndex]^; + Inc(mCurIndex); + if (mItems[mCurIndex].varp <> nil) then break; end; + end + else + begin + mCurIndex := -1; + end; + end; + if (ev = 'Space') or (ev = 'Return') then + begin + result := true; + if (mCurIndex >= 0) and (mCurIndex < Length(mItems)) and (mItems[mCurIndex].varp <> nil) then + begin + it := @mItems[mCurIndex]; + it.varp^ := not it.varp^; + if assigned(it.actionCB) then it.actionCB(self, Integer(it.varp^)); + if assigned(actionCB) then actionCB(self, mCurIndex); + end; end; end; end;