From 1ed2c76ecb3f7351b9194356623bbad2f1313aa8 Mon Sep 17 00:00:00 2001 From: s_alexander Date: Mon, 29 Jun 2009 01:02:40 +0000 Subject: merged svn trunk r1837 into cmake branche git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/branches/experimental@1838 b956fd51-792f-4845-bead-9b4dfca2ff2c --- cmake/src/menu/UDisplay.pas | 218 ++++++++++++++++++++++++-- cmake/src/menu/UMenu.pas | 302 +++++++++++++++++++++++++++++------- cmake/src/menu/UMenuButton.pas | 74 ++++----- cmake/src/menu/UMenuSelectSlide.pas | 192 +++++++++++++---------- cmake/src/menu/UMenuText.pas | 167 ++++++++++---------- 5 files changed, 680 insertions(+), 273 deletions(-) (limited to 'cmake/src/menu') diff --git a/cmake/src/menu/UDisplay.pas b/cmake/src/menu/UDisplay.pas index 58c416db..f2eb2ced 100644 --- a/cmake/src/menu/UDisplay.pas +++ b/cmake/src/menu/UDisplay.pas @@ -45,7 +45,7 @@ type TDisplay = class private //fade-to-black-hack - BlackScreen: boolean; + BlackScreen: boolean; FadeEnabled: boolean; // true if fading is enabled FadeFailed: boolean; // true if fading is possible (enough memory, etc.) @@ -60,6 +60,17 @@ type OSD_LastError: string; + { software cursor data } + Cursor_X: double; + Cursor_Y: double; + Cursor_Pressed: boolean; + Cursor_HiddenByScreen: boolean; // hides software cursor and deactivate auto fade in + + // used for cursor fade out when there is no movement + Cursor_Visible: boolean; + Cursor_LastMove: cardinal; + Cursor_Fade: boolean; + procedure DrawDebugInformation; public NextScreen: PMenu; @@ -78,10 +89,27 @@ type procedure SaveScreenShot; function Draw: boolean; + + { sets SDL_ShowCursor depending on options set in Ini } + procedure SetCursor; + + { called when cursor moves, positioning of software cursor } + procedure MoveCursor(X, Y: double; Pressed: boolean); + + + { draws software cursor } + procedure DrawCursor; end; var - Display: TDisplay; + Display: TDisplay; + +const + { constants for software cursor effects + time in milliseconds } + Cursor_FadeIn_Time = 500; // seconds the fade in effect lasts + Cursor_FadeOut_Time = 2000; // seconds the fade out effect lasts + Cursor_AutoHide_Time = 5000; // seconds until auto fade out starts if there is no mouse movement implementation @@ -110,9 +138,9 @@ begin BlackScreen := false; // fade mod - FadeState := 0; + FadeState := 0; FadeEnabled := (Ini.ScreenFade = 1); - FadeFailed:= false; + FadeFailed := false; glGenTextures(2, @FadeTex); @@ -125,6 +153,15 @@ begin //Set LastError for OSD to No Error OSD_LastError := 'No Errors'; + + // software cursor default values + Cursor_LastMove := 0; + Cursor_Visible := false; + Cursor_Pressed := false; + Cursor_X := -1; + Cursor_Y := -1; + Cursor_Fade := false; + Cursor_HiddenByScreen := true; end; destructor TDisplay.Destroy; @@ -306,6 +343,162 @@ begin if ((Ini.Debug = 1) or (Params.Debug)) and (S = 1) then DrawDebugInformation; end; // for + + if not BlackScreen then + DrawCursor; +end; + +{ sets SDL_ShowCursor depending on options set in Ini } +procedure TDisplay.SetCursor; +var + Cursor: Integer; +begin + Cursor := 0; + + if (CurrentScreen <> @ScreenSing) or (Cursor_HiddenByScreen) then + begin // hide cursor on singscreen + if (Ini.Mouse = 0) and (Ini.FullScreen = 0) then + // show sdl (os) cursor in window mode even when mouse support is off + Cursor := 1 + else if (Ini.Mouse = 1) then + // show sdl (os) cursor when hardware cursor is selected + Cursor := 1; + + if (Ini.Mouse <> 2) then + Cursor_HiddenByScreen := false; + end + else if (Ini.Mouse <> 2) then + Cursor_HiddenByScreen := true; + + + SDL_ShowCursor(Cursor); + + if (Ini.Mouse = 2) then + begin + if Cursor_HiddenByScreen then + begin + // show software cursor + Cursor_HiddenByScreen := false; + Cursor_Visible := false; + Cursor_Fade := false; + end + else if (CurrentScreen = @ScreenSing) then + begin + // hide software cursor in singscreen + Cursor_HiddenByScreen := true; + Cursor_Visible := false; + Cursor_Fade := false; + end; + end; +end; + +{ called when cursor moves, positioning of software cursor } +procedure TDisplay.MoveCursor(X, Y: double; Pressed: boolean); +var + Ticks: cardinal; +begin + if (Ini.Mouse = 2) and + ((X <> Cursor_X) or (Y <> Cursor_Y) or (Pressed <> Cursor_Pressed)) then + begin + Cursor_X := X; + Cursor_Y := Y; + Cursor_Pressed := Pressed; + + Ticks := SDL_GetTicks; + + { fade in on movement (or button press) if not first movement } + if (not Cursor_Visible) and (Cursor_LastMove <> 0) then + begin + if Cursor_Fade then // we use a trick here to consider progress of fade out + Cursor_LastMove := Ticks - round(Cursor_FadeIn_Time * (1 - (Ticks - Cursor_LastMove)/Cursor_FadeOut_Time)) + else + Cursor_LastMove := Ticks; + + Cursor_Visible := true; + Cursor_Fade := true; + end + else if not Cursor_Fade then + begin + Cursor_LastMove := Ticks; + end; + end; +end; + +{ draws software cursor } +procedure TDisplay.DrawCursor; +var + Alpha: single; + Ticks: cardinal; +begin + if (Ini.Mouse = 2) then + begin // draw software cursor + Ticks := SDL_GetTicks; + + if (Cursor_Visible) and (Cursor_LastMove + Cursor_AutoHide_Time <= Ticks) then + begin // start fade out after 5 secs w/o activity + Cursor_Visible := false; + Cursor_LastMove := Ticks; + Cursor_Fade := true; + end; + + // fading + if Cursor_Fade then + begin + if Cursor_Visible then + begin // fade in + if (Cursor_LastMove + Cursor_FadeIn_Time <= Ticks) then + Cursor_Fade := false + else + Alpha := sin((Ticks - Cursor_LastMove) * 0.5 * pi / Cursor_FadeIn_Time) * 0.7; + end + else + begin //fade out + if (Cursor_LastMove + Cursor_FadeOut_Time <= Ticks) then + Cursor_Fade := false + else + Alpha := cos((Ticks - Cursor_LastMove) * 0.5 * pi / Cursor_FadeOut_Time) * 0.7; + end; + end; + + // no else if here because we may turn off fade in if block + if not Cursor_Fade then + begin + if Cursor_Visible then + Alpha := 0.7 // alpha when cursor visible and not fading + else + Alpha := 0; // alpha when cursor is hidden + end; + + if (Alpha > 0) and (not Cursor_HiddenByScreen) then + begin + glColor4f(1, 1, 1, Alpha); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + + if (Cursor_Pressed) and (Tex_Cursor_Pressed.TexNum > 0) then + glBindTexture(GL_TEXTURE_2D, Tex_Cursor_Pressed.TexNum) + else + glBindTexture(GL_TEXTURE_2D, Tex_Cursor_Unpressed.TexNum); + + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(Cursor_X, Cursor_Y); + + glTexCoord2f(0, 1); + glVertex2f(Cursor_X, Cursor_Y + 32); + + glTexCoord2f(1, 1); + glVertex2f(Cursor_X + 32, Cursor_Y + 32); + + glTexCoord2f(1, 0); + glVertex2f(Cursor_X + 32, Cursor_Y); + glEnd; + + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + end; + end; end; procedure TDisplay.SaveScreenShot; @@ -360,10 +553,11 @@ begin end; //------------ -// DrawDebugInformation - Procedure draw FPS and some other Informations on Screen +// DrawDebugInformation - procedure draw fps and some other informations on screen //------------ procedure TDisplay.DrawDebugInformation; -var Ticks: cardinal; +var + Ticks: cardinal; begin // Some White Background for information glEnable(GL_BLEND); @@ -377,13 +571,13 @@ begin glEnd; glDisable(GL_BLEND); -// Set Font Specs +// set font specs SetFontStyle(0); SetFontSize(21); SetFontItalic(false); glColor4f(0, 0, 0, 1); -// Calculate FPS +// calculate fps Ticks := SDL_GetTicks(); if (Ticks >= NextFPSSwap) then begin @@ -394,17 +588,17 @@ begin Inc(FPSCounter); -// Draw Text +// draw text -// FPS +// fps SetFontPos(695, 0); glPrint ('FPS: ' + InttoStr(LastFPS)); -// RSpeed +// rspeed SetFontPos(695, 13); glPrint ('RSpeed: ' + InttoStr(Round(1000 * TimeMid))); -// LastError +// lasterror SetFontPos(695, 26); glColor4f(1, 0, 0, 1); glPrint (OSD_LastError); diff --git a/cmake/src/menu/UMenu.pas b/cmake/src/menu/UMenu.pas index f86746ed..a3f47b3d 100644 --- a/cmake/src/menu/UMenu.pas +++ b/cmake/src/menu/UMenu.pas @@ -34,19 +34,20 @@ interface {$I switches.inc} uses - gl, SysUtils, - UTexture, - UMenuStatic, - UMenuText, - UMenuButton, - UMenuSelectSlide, - UMenuInteract, + Math, + gl, + SDL, UMenuBackground, - UThemes, + UMenuButton, UMenuButtonCollection, - Math, - UMusic; + UMenuInteract, + UMenuSelectSlide, + UMenuStatic, + UMenuText, + UMusic, + UTexture, + UThemes; type { Int16 = SmallInt;} @@ -61,7 +62,7 @@ type ButtonPos: integer; Button: array of TButton; - + SelectsS: array of TSelectSlide; ButtonCollection: array of TButtonCollection; public @@ -72,6 +73,7 @@ type Fade: integer; // fade type ShowFinish: boolean; // true if there is no fade + RightMbESC: boolean; // true to simulate ESC keypress when RMB is pressed destructor Destroy; override; constructor Create; overload; virtual; @@ -82,10 +84,10 @@ type function WideCharUpperCase(wchar: WideChar) : WideString; function WideStringUpperCase(wstring: WideString) : WideString; procedure AddInteraction(Typ, Num: integer); - procedure SetInteraction(Num: integer); + procedure SetInteraction(Num: integer); virtual; property Interaction: integer read SelInteraction write SetInteraction; - //Procedure Load BG, Texts, Statics and Button Collections from ThemeBasic + // procedure load bg, texts, statics and button collections from themebasic procedure LoadFromTheme(const ThemeBasic: TThemeBasic); procedure PrepareButtonCollections(const Collections: AThemeButtonCollection); @@ -145,9 +147,10 @@ type function DrawFG: boolean; virtual; function Draw: boolean; virtual; function ParseInput(PressedKey: cardinal; CharCode: WideChar; PressedDown : boolean): boolean; virtual; - // FIXME: ParseMouse is not implemented in any subclass and not even used anywhere in the code - // -> do this before activation of this method - //function ParseMouse(Typ: integer; X: integer; Y: integer): boolean; virtual; abstract; + function ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean; virtual; + function InRegion(X1, Y1, W, H, X, Y: real): boolean; + function InteractAt(X, Y: real): integer; + function CollectionAt(X, Y: real): integer; procedure onShow; virtual; procedure onShowFinish; virtual; procedure onHide; virtual; @@ -167,6 +170,9 @@ type end; const + MENU_MDOWN = 8; + MENU_MUP = 0; + pmMove = 1; pmClick = 2; pmUnClick = 3; @@ -183,14 +189,14 @@ implementation uses UCommon, - ULog, - UMain, + UCovers, + UDisplay, UDrawTexture, UGraphic, - UDisplay, - UCovers, - UTime, + ULog, + UMain, USkins, + UTime, //Background types UMenuBackgroundNone, UMenuBackgroundColor, @@ -221,6 +227,8 @@ begin ButtonPos := -1; Background := nil; + + RightMbESC := true; end; { constructor TMenu.Create(Back: string); @@ -252,7 +260,7 @@ begin BackH := H; end; } -function RGBFloatToInt(R, G, B: Double): cardinal; +function RGBFloatToInt(R, G, B: double): cardinal; begin Result := (Trunc(255 * R) shl 16) or (Trunc(255 * G) shl 8) or @@ -291,8 +299,8 @@ begin begin Button[OldNum].Selected := false; - //Deselect Collection if Next Button is Not from Collection - if (NewTyp <> iButton) Or (Button[NewNum].Parent <> Button[OldNum].Parent) then + // deselect collection if next button is not from collection + if (NewTyp <> iButton) or (Button[NewNum].Parent <> Button[OldNum].Parent) then ButtonCollection[Button[OldNum].Parent-1].Selected := false; end; end; @@ -596,17 +604,25 @@ begin Result := AddStatic(X, Y, W, H, Name, TEXTURE_TYPE_PLAIN); end; -function TMenu.AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; +function TMenu.AddStatic(X, Y, W, H: real; + ColR, ColG, ColB: real; + const Name: string; + Typ: TTextureType): integer; begin Result := AddStatic(X, Y, W, H, ColR, ColG, ColB, Name, Typ, $FFFFFF); end; -function TMenu.AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType): integer; +function TMenu.AddStatic(X, Y, W, H, Z: real; + ColR, ColG, ColB: real; + const Name: string; + Typ: TTextureType): integer; begin Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, Name, Typ, $FFFFFF); end; -function TMenu.AddStatic(X, Y, W, H: real; const Name: string; Typ: TTextureType): integer; +function TMenu.AddStatic(X, Y, W, H: real; + const Name: string; + Typ: TTextureType): integer; var StatNum: integer; begin @@ -624,17 +640,32 @@ begin Result := StatNum; end; -function TMenu.AddStatic(X, Y, W, H: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; +function TMenu.AddStatic(X, Y, W, H: real; + ColR, ColG, ColB: real; + const Name: string; + Typ: TTextureType; + Color: integer): integer; begin Result := AddStatic(X, Y, W, H, 0, ColR, ColG, ColB, Name, Typ, Color); end; -function TMenu.AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; const Name: string; Typ: TTextureType; Color: integer): integer; +function TMenu.AddStatic(X, Y, W, H, Z: real; + ColR, ColG, ColB: real; + const Name: string; + Typ: TTextureType; + Color: integer): integer; begin Result := AddStatic(X, Y, W, H, Z, ColR, ColG, ColB, 0, 0, 1, 1, Name, Typ, Color, false, 0); end; -function TMenu.AddStatic(X, Y, W, H, Z: real; ColR, ColG, ColB: real; TexX1, TexY1, TexX2, TexY2: real; const Name: string; Typ: TTextureType; Color: integer; Reflection: boolean; ReflectionSpacing: real): integer; +function TMenu.AddStatic(X, Y, W, H, Z: real; + ColR, ColG, ColB: real; + TexX1, TexY1, TexX2, TexY2: real; + const Name: string; + Typ: TTextureType; + Color: integer; + Reflection: boolean; + ReflectionSpacing: real): integer; var StatNum: integer; begin @@ -652,12 +683,22 @@ begin begin Static[StatNum] := TStatic.Create(Texture.GetTexture(Name, Typ, Color)); // new skin end; - + // configures static Static[StatNum].Texture.X := X; Static[StatNum].Texture.Y := Y; - Static[StatNum].Texture.W := W; - Static[StatNum].Texture.H := H; + + //Set height and width via sprite size if omitted + if(H = 0) then + Static[StatNum].Texture.H := Static[StatNum].Texture.H + else + Static[StatNum].Texture.H := H; + + if(W = 0) then + Static[StatNum].Texture.W := Static[StatNum].Texture.W + else + Static[StatNum].Texture.W := W; + Static[StatNum].Texture.Z := Z; if (Typ <> TEXTURE_TYPE_COLORIZED) then begin @@ -696,12 +737,22 @@ begin Result := TextNum; end; -function TMenu.AddText(X, Y: real; Style: integer; Size, ColR, ColG, ColB: real; const Text: string): integer; +function TMenu.AddText(X, Y: real; + Style: integer; + Size, ColR, ColG, ColB: real + ; const Text: string): integer; begin Result := AddText(X, Y, 0, Style, Size, ColR, ColG, ColB, 0, Text, false, 0, 0); end; -function TMenu.AddText(X, Y, W: real; Style: integer; Size, ColR, ColG, ColB: real; Align: integer; const Text_: string; Reflection_: boolean; ReflectionSpacing_: real; Z : real): integer; +function TMenu.AddText(X, Y, W: real; + Style: integer; + Size, ColR, ColG, ColB: real; + Align: integer; + const Text_: string; + Reflection_: boolean; + ReflectionSpacing_: real; + Z : real): integer; var TextNum: integer; begin @@ -771,10 +822,10 @@ begin ThemeButton.Text[BT].Text); end; - //BAutton Collection Mod + // bautton collection mod if (ThemeButton.Parent <> 0) then begin - //If Collection Exists then Change Interaction to Child Button + // if collection exists then change interaction to child button if (@ButtonCollection[ThemeButton.Parent-1] <> nil) then begin Interactions[High(Interactions)].Typ := iBCollectionChild; @@ -803,8 +854,10 @@ begin end; function TMenu.AddButton(X, Y, W, H, ColR, ColG, ColB, Int, DColR, DColG, DColB, DInt: real; - const Name: string; Typ: TTextureType; - Reflection: boolean; ReflectionSpacing, DeSelectReflectionSpacing: real): integer; + const Name: string; + Typ: TTextureType; + Reflection: boolean; + ReflectionSpacing, DeSelectReflectionSpacing: real): integer; begin // adds button //SetLength is used once to reduce Memory usement @@ -857,7 +910,7 @@ begin Button[Result].Reflectionspacing := ReflectionSpacing; Button[Result].DeSelectReflectionspacing := DeSelectReflectionSpacing; - //Button Collection Mod + // button collection mod Button[Result].Parent := 0; // adds interaction @@ -870,11 +923,10 @@ begin Setlength(Button, 0); end; -// Method to draw our TMenu and all his child buttons +// method to draw our tmenu and all his child buttons function TMenu.DrawBG: boolean; begin Background.Draw; - Result := true; end; @@ -993,9 +1045,10 @@ begin Int := Int - ceil(Length(Interactions) / 2); //Set Interaction - if ((Int < 0) or (Int > Length(Interactions) - 1)) - then Int := Interaction //nonvalid button, keep current one - else Interaction := Int; //select row above + if ((Int < 0) or (Int > Length(Interactions) - 1)) then + Int := Interaction // invalid button, keep current one + else + Interaction := Int; // select row above end; procedure TMenu.InteractNextRow; @@ -1007,9 +1060,10 @@ begin Int := Int + ceil(Length(Interactions) / 2); //Set Interaction - if ((Int < 0) or (Int > Length(Interactions) - 1)) - then Int := Interaction //nonvalid button, keep current one - else Interaction := Int; //select row above + if ((Int < 0) or (Int > Length(Interactions) - 1)) then + Int := Interaction // invalid button, keep current one + else + Interaction := Int; // select row above end; procedure TMenu.InteractNext; @@ -1023,7 +1077,8 @@ begin Int := (Int + 1) mod Length(Interactions); //If no Interaction is Selectable Simply Select Next - if (Int = Interaction) then Break; + if (Int = Interaction) then + Break; until IsSelectable(Int); @@ -1040,10 +1095,12 @@ begin // change interaction as long as it's needed repeat Int := Int - 1; - if Int = -1 then Int := High(Interactions); + if Int = -1 then + Int := High(Interactions); //If no Interaction is Selectable Simply Select Next - if (Int = Interaction) then Break; + if (Int = Interaction) then + Break; until IsSelectable(Int); //Set Interaction @@ -1068,7 +1125,8 @@ begin while (Again = true) do begin Num := SelInteraction - CustomSwitch; - if Num = -1 then Num := High(Interactions); + if Num = -1 then + Num := High(Interactions); Interaction := Num; Again := false; // reset, default to accept changing interaction @@ -1212,6 +1270,9 @@ begin SelectsS[High(SelectsS)].Texture.Z := ThemeSelectS.Z; SelectsS[High(SelectsS)].TextureSBG.Z := ThemeSelectS.Z; + SelectsS[High(SelectsS)].showArrows := ThemeSelectS.showArrows; + SelectsS[High(SelectsS)].oneItemOnly := ThemeSelectS.oneItemOnly; + //Generate Lines SelectsS[High(SelectsS)].GenLines; @@ -1255,9 +1316,20 @@ begin else SelectsS[S].TextureSBG := Texture.GetTexture(SBGName, SBGTyp); + SelectsS[High(SelectsS)].Tex_SelectS_ArrowL := Tex_SelectS_ArrowL; + SelectsS[High(SelectsS)].Tex_SelectS_ArrowL.X := X + W + SkipX; + SelectsS[High(SelectsS)].Tex_SelectS_ArrowL.Y := Y; + SelectsS[High(SelectsS)].Tex_SelectS_ArrowL.W := Tex_SelectS_ArrowL.W; + SelectsS[High(SelectsS)].Tex_SelectS_ArrowL.H := Tex_SelectS_ArrowL.H; + + SelectsS[High(SelectsS)].Tex_SelectS_ArrowR := Tex_SelectS_ArrowR; + SelectsS[High(SelectsS)].Tex_SelectS_ArrowR.X := X + W + SkipX + SBGW - Tex_SelectS_ArrowR.W; + SelectsS[High(SelectsS)].Tex_SelectS_ArrowR.Y := Y; + SelectsS[High(SelectsS)].Tex_SelectS_ArrowR.W := Tex_SelectS_ArrowR.W; + SelectsS[High(SelectsS)].Tex_SelectS_ArrowR.H := Tex_SelectS_ArrowR.H; + SelectsS[S].TextureSBG.X := X + W + SkipX; SelectsS[S].TextureSBG.Y := Y; - //SelectsS[S].TextureSBG.W := 450; SelectsS[S].SBGW := SBGW; SelectsS[S].TextureSBG.H := H; SelectsS[S].SBGColR := SBGColR; @@ -1355,10 +1427,12 @@ begin SetLength(SelectsS[SelectNo].TextOptT, SO + 1); SelectsS[SelectNo].TextOptT[SO] := AddText; +{ + SelectsS[S].SelectedOption := SelectsS[S].SelectOptInt; // refresh - //SelectsS[S].SelectedOption := SelectsS[S].SelectOptInt; // refresh - - //if SO = Selects[S].PData^ then Selects[S].SelectedOption := SO; + if SO = Selects[S].PData^ then + Selects[S].SelectedOption := SO; +} end; procedure TMenu.UpdateSelectSlideOptions(ThemeSelectSlide: TThemeSelectSlide; SelectNum: integer; Values: array of string; var Data: integer); @@ -1458,11 +1532,11 @@ begin end; end; end; - //interact Prev if there is Nothing to Change + // interact prev if there is nothing to change else begin InteractPrev; - //If ButtonCollection with more than 1 Entry then Select Last Entry + // if buttoncollection with more than 1 entry then select last entry if (Button[Interactions[Interaction].Num].Parent <> 0) and (ButtonCollection[Button[Interactions[Interaction].Num].Parent-1].CountChilds > 1) then begin //Select Last Child @@ -1571,10 +1645,120 @@ begin Result := true; end; +function TMenu.ParseMouse(MouseButton: integer; BtnDown: boolean; X, Y: integer): boolean; +var + nBut: integer; +begin + //default mouse parsing: clicking generates return keypress, + // mousewheel selects in select slide + //override ParseMouse to customize + Result := true; + + if RightMbESC and (MouseButton = SDL_BUTTON_RIGHT) and BtnDown then + begin + //if RightMbESC is set, send ESC keypress + Result:=ParseInput(SDLK_ESCAPE, #0, true); + end; + + nBut := InteractAt(X, Y); + if nBut >= 0 then + begin + //select on mouse-over + if nBut <> Interaction then + SetInteraction(nBut); + if (MouseButton = SDL_BUTTON_LEFT) and BtnDown then + begin + //click button + Result:=ParseInput(SDLK_RETURN, #0, true); + end; + if (Interactions[nBut].Typ = iSelectS) then + begin + //forward/backward in select slide with mousewheel + if (MouseButton = SDL_BUTTON_WHEELDOWN) and BtnDown then + begin + ParseInput(SDLK_RIGHT, #0, true); + end; + if (MouseButton = SDL_BUTTON_WHEELUP) and BtnDown then + begin + ParseInput(SDLK_LEFT, #0, true); + end; + end; + end + else + begin + nBut := CollectionAt(X, Y); + if nBut >= 0 then + begin + // if over button collection, select first child but don't allow click + nBut := ButtonCollection[nBut].FirstChild - 1; + if nBut <> Interaction then + SetInteraction(nBut); + end; + end; +end; + +function TMenu.InRegion(X1, Y1, W, H, X, Y: real): boolean; +begin + Result := false; + X1 := X1 * Screen.w / 800; + W := W * Screen.w / 800; + Y1 := Y1 * Screen.h / 600; + H := H * Screen.h / 600; + if (X >= X1) and (X <= X1 + W) and (Y >= Y1) and (Y <= Y1 + H) then + Result := true; +end; + +//takes x,y coordinates and returns the interaction number +//of the control at this position +function TMenu.InteractAt(X, Y: real): integer; +var + i, nBut: integer; +begin + Result := -1; + for i := Low(Interactions) to High(Interactions) do + begin + case Interactions[i].Typ of + iButton: if InRegion(Button[Interactions[i].Num].X, Button[Interactions[i].Num].Y, Button[Interactions[i].Num].W, Button[Interactions[i].Num].H, X, Y) and + Button[Interactions[i].Num].Visible then + begin + Result:=i; + exit; + end; + iBCollectionChild: if InRegion(Button[Interactions[i].Num].X, Button[Interactions[i].Num].Y, Button[Interactions[i].Num].W, Button[Interactions[i].Num].H, X, Y) then + begin + Result:=i; + exit; + end; + iSelectS: if InRegion(SelectSs[Interactions[i].Num].X, SelectSs[Interactions[i].Num].Y, SelectSs[Interactions[i].Num].W, SelectSs[Interactions[i].Num].H, X, Y) or + InRegion(SelectSs[Interactions[i].Num].TextureSBG.X, SelectSs[Interactions[i].Num].TextureSBG.Y, SelectSs[Interactions[i].Num].TextureSBG.W, SelectSs[Interactions[i].Num].TextureSBG.H, X, Y) then + begin + Result:=i; + exit; + end; + end; + end; +end; + +//takes x,y coordinates and returns the button collection id +function TMenu.CollectionAt(X, Y: real): integer; +var + i, nBut: integer; +begin + Result := -1; + for i:= Low(ButtonCollection) to High(ButtonCollection) do + begin + if InRegion(ButtonCollection[i].X, ButtonCollection[i].Y, ButtonCollection[i].W, ButtonCollection[i].H, X, Y) and + ButtonCollection[i].Visible then + begin + Result:=i; + exit; + end; + end; +end; + procedure TMenu.SetAnimationProgress(Progress: real); begin // nothing end; end. - diff --git a/cmake/src/menu/UMenuButton.pas b/cmake/src/menu/UMenuButton.pas index c6ff8ab7..923f0b14 100644 --- a/cmake/src/menu/UMenuButton.pas +++ b/cmake/src/menu/UMenuButton.pas @@ -55,7 +55,6 @@ type PosX, PosY: real; - constructor Create(); overload; public Text: array of TText; @@ -113,6 +112,7 @@ type procedure Draw; virtual; + constructor Create(); overload; constructor Create(Textura: TTexture); overload; constructor Create(Textura, DSTexture: TTexture); overload; destructor Destroy; override; @@ -252,42 +252,6 @@ begin end; end; -constructor TButton.Create(); -begin - inherited Create; - // We initialize all to 0, nil or false - Visible := true; - SelectBool := false; - DeselectType := 0; - Selectable := true; - Reflection := false; - Colorized := false; - - SelectColR := 1; - SelectColG := 1; - SelectColB := 1; - SelectInt := 1; - SelectTInt := 1; - - DeselectColR := 1; - DeselectColG := 1; - DeselectColB := 1; - DeselectInt := 0.5; - DeselectTInt := 1; - - Fade := false; - FadeTex.TexNum := 0; - FadeProgress := 0; - FadeText := false; - SelectW := DeSelectW; - SelectH := DeSelectH; - - PosX := 0; - PosY := 0; - - Parent := 0; -end; - // ***** Public methods ****** // procedure TButton.Draw; @@ -571,6 +535,42 @@ begin inherited; end; +constructor TButton.Create(); +begin + inherited Create; + // We initialize all to 0, nil or false + Visible := true; + SelectBool := false; + DeselectType := 0; + Selectable := true; + Reflection := false; + Colorized := false; + + SelectColR := 1; + SelectColG := 1; + SelectColB := 1; + SelectInt := 1; + SelectTInt := 1; + + DeselectColR := 1; + DeselectColG := 1; + DeselectColB := 1; + DeselectInt := 0.5; + DeselectTInt := 1; + + Fade := false; + FadeTex.TexNum := 0; + FadeProgress := 0; + FadeText := false; + SelectW := DeSelectW; + SelectH := DeSelectH; + + PosX := 0; + PosY := 0; + + Parent := 0; +end; + constructor TButton.Create(Textura: TTexture); begin Create(); diff --git a/cmake/src/menu/UMenuSelectSlide.pas b/cmake/src/menu/UMenuSelectSlide.pas index a7133492..f9f6bbae 100644 --- a/cmake/src/menu/UMenuSelectSlide.pas +++ b/cmake/src/menu/UMenuSelectSlide.pas @@ -34,10 +34,10 @@ interface {$I switches.inc} uses - TextGL, - UTexture, gl, - UMenuText; + TextGL, + UMenuText, + UTexture; type PSelectSlide = ^TSelectSlide; @@ -54,8 +54,8 @@ type TextureSBG: TTexture; // Background Selections Texture // TextureS: array of TTexture; // Selections Texture (not used) -// TextureArrowL: TTexture; // Texture for left arrow (not used yet) -// TextureArrowR: TTexture; // Texture for right arrow (not used yet) + Tex_SelectS_ArrowL: TTexture; // Texture for left arrow + Tex_SelectS_ArrowR: TTexture; // Texture for right arrow SelectOptInt: integer; PData: ^integer; @@ -63,6 +63,12 @@ type //For automatically Setting LineCount Lines: byte; + //Arrows on/off + showArrows: boolean; //default is false + + //whether to show one item or all that fit into the select + oneItemOnly: boolean; //default is false + //Visibility Visible: boolean; @@ -132,11 +138,12 @@ type end; implementation + uses - UDrawTexture, math, - ULog, - SysUtils; + SysUtils, + UDrawTexture, + ULog; // ------------ Select constructor TSelectSlide.Create; @@ -145,15 +152,7 @@ begin Text := TText.Create; SetLength(TextOpt, 1); TextOpt[0] := TText.Create; - - //Set Standard Width for Selections Background - SBGW := 450; - Visible := true; - {SetLength(TextOpt, 3); - TextOpt[0] := TText.Create; - TextOpt[1] := TText.Create; - TextOpt[2] := TText.Create;} end; procedure TSelectSlide.SetSelect(Value: boolean); @@ -178,14 +177,6 @@ begin TextureSBG.ColG := SBGColG; TextureSBG.ColB := SBGColB; TextureSBG.Int := SBGInt; - -{ for I := 0 to High(TextOpt) do begin - TextOpt[I].ColR := STColR; - TextOpt[I].ColG := STColG; - TextOpt[I].ColB := STColB; - TextOpt[I].Int := STInt; - end;} - end else begin @@ -203,13 +194,6 @@ begin TextureSBG.ColG := SBGDColG; TextureSBG.ColB := SBGDColB; TextureSBG.Int := SBGDInt; - -{ for I := 0 to High(TextOpt) do begin - TextOpt[I].ColR := STDColR; - TextOpt[I].ColG := STDColG; - TextOpt[I].ColB := STDColB; - TextOpt[I].Int := STDInt; - end;} end; end; @@ -219,98 +203,112 @@ var HalfL: integer; HalfR: integer; -procedure DoSelection(Sel: cardinal); + procedure DoSelection(Sel: cardinal); var I: integer; begin - for I := low(TextOpt) to high(TextOpt) do + for I := Low(TextOpt) to High(TextOpt) do begin TextOpt[I].ColR := STDColR; TextOpt[I].ColG := STDColG; TextOpt[I].ColB := STDColB; TextOpt[I].Int := STDInt; end; - if (integer(Sel) <= high(TextOpt)) then + + if (integer(Sel) <= High(TextOpt)) then begin TextOpt[Sel].ColR := STColR; TextOpt[Sel].ColG := STColG; TextOpt[Sel].ColB := STColB; TextOpt[Sel].Int := STInt; + end; end; - end; + begin SelectOptInt := Value; PData^ := Value; -// SetSelect(true); // reset all colors - if (Length(TextOpt)>0) AND (Length(TextOptT)>0) then + if (Length(TextOpt) > 0) and (Length(TextOptT) > 0) then begin + //First option selected if (Value <= 0) then - begin //First Option Selected + begin Value := 0; - for SO := low (TextOpt) to high(TextOpt) do + Tex_SelectS_ArrowL.alpha := 0; + Tex_SelectS_ArrowR.alpha := 1; + + for SO := Low(TextOpt) to High(TextOpt) do begin TextOpt[SO].Text := TextOptT[SO]; end; DoSelection(0); end - else if (Value >= high(TextOptT)) then - begin //Last Option Selected - Value := high(TextOptT); - for SO := high(TextOpt) downto low (TextOpt) do + //Last option selected + else if (Value >= High(TextOptT)) then + begin + Value := High(TextOptT); + + Tex_SelectS_ArrowL.alpha := 1; + Tex_SelectS_ArrowR.alpha := 0; + + for SO := High(TextOpt) downto Low(TextOpt) do begin - TextOpt[SO].Text := TextOptT[high(TextOptT)-(Lines-SO-1)]; + TextOpt[SO].Text := TextOptT[High(TextOptT) - (Lines - SO - 1)]; end; - DoSelection(Lines-1); + DoSelection(Lines - 1); end + + //in between first and last else begin - HalfL := Ceil((Lines-1)/2); - HalfR := Lines-1-HalfL; + Tex_SelectS_ArrowL.alpha := 1; + Tex_SelectS_ArrowR.alpha := 1; + HalfL := Ceil((Lines - 1) / 2); + HalfR := Lines - 1 - HalfL; + + //Selected option is near to the left side if (Value <= HalfL) then - begin //Selected Option is near to the left side - {HalfL := Value; - HalfR := Lines-1-HalfL;} - //Change Texts - for SO := low (TextOpt) to high(TextOpt) do - begin - TextOpt[SO].Text := TextOptT[SO]; - end; - - DoSelection(Value); + begin + //Change texts + for SO := Low(TextOpt) to High(TextOpt) do + begin + TextOpt[SO].Text := TextOptT[SO]; + end; + + DoSelection(Value); end - else if (Value > High(TextOptT)-HalfR) then - begin //Selected is too near to the right border - HalfR := high(TextOptT) - Value; - HalfL := Lines-1-HalfR; - //Change Texts - for SO := high(TextOpt) downto low (TextOpt) do - begin - TextOpt[SO].Text := TextOptT[high(TextOptT)-(Lines-SO-1)]; - end; - - DoSelection (HalfL); + + //Selected option is near to the right side + else if (Value > High(TextOptT) - HalfR) then + begin + HalfR := High(TextOptT) - Value; + HalfL := Lines - 1 - HalfR; + //Change texts + for SO := High(TextOpt) downto Low(TextOpt) do + begin + TextOpt[SO].Text := TextOptT[High(TextOptT) - (Lines - SO - 1)]; + end; + + DoSelection (HalfL); end + else begin - //Change Texts - for SO := low (TextOpt) to high(TextOpt) do - begin + //Change Texts + for SO := Low(TextOpt) to High(TextOpt) do + begin TextOpt[SO].Text := TextOptT[Value - HalfL + SO]; - end; + end; - DoSelection(HalfL); + DoSelection(HalfL); end; - end; - end; - end; procedure TSelectSlide.Draw; @@ -322,9 +320,15 @@ begin DrawTexture(Texture); DrawTexture(TextureSBG); + if showArrows then + begin + DrawTexture(Tex_SelectS_ArrowL); + DrawTexture(Tex_SelectS_ArrowR); + end; + Text.Draw; - for SO := low(TextOpt) to high(TextOpt) do + for SO := Low(TextOpt) to High(TextOpt) do TextOpt[SO].Draw; end; end; @@ -338,26 +342,36 @@ begin SetFontSize(Text.Size); maxlength := 0; - for I := low(TextOptT) to high (TextOptT) do + for I := Low(TextOptT) to High(TextOptT) do begin if (glTextWidth(TextOptT[I]) > maxlength) then maxlength := glTextWidth(TextOptT[I]); end; - Lines := floor((TextureSBG.W-40) / (maxlength+7)); - if (Lines > Length(TextOptT)) then - Lines := Length(TextOptT); - if (Lines <= 0) then + if (oneItemOnly = false) then + begin + //show all items + Lines := floor((TextureSBG.W-40) / (maxlength+7)); + if (Lines > Length(TextOptT)) then + Lines := Length(TextOptT); + + if (Lines <= 0) then + Lines := 1; + end + else + begin + //show one item only Lines := 1; + end; //Free old Space used by Texts - for I := low(TextOpt) to high(TextOpt) do + for I := Low(TextOpt) to High(TextOpt) do TextOpt[I].Free; setLength (TextOpt, Lines); - for I := low(TextOpt) to high(TextOpt) do + for I := Low(TextOpt) to High(TextOpt) do begin TextOpt[I] := TText.Create; TextOpt[I].Size := Text.Size; @@ -372,7 +386,7 @@ begin //Generate Positions //TextOpt[I].X := TextureSBG.X + 20 + (TextureSBG.W / Lines) * (I + 0.5); - if (I <> High(TextOpt)) OR (High(TextOpt) = 0) OR (Length(TextOptT) = Lines) then + if (I <> High(TextOpt)) or (High(TextOpt) = 0) or (Length(TextOptT) = Lines) then TextOpt[I].X := TextureSBG.X + 20 + (TextureSBG.W / Lines) * I else TextOpt[I].X := TextureSBG.X + TextureSBG.W - maxlength; @@ -380,8 +394,14 @@ begin TextOpt[I].Y := TextureSBG.Y + (TextureSBG.H - Text.Size) / 2; //Better Look with 2 Options - if (Lines=2) AND (Length(TextOptT)= 2) then + if (Lines = 2) and (Length(TextOptT) = 2) then TextOpt[I].X := TextureSBG.X + 20 + (TextureSBG.W -40 - glTextWidth(TextOptT[1])) * I; + + if (Lines = 1) then + begin + TextOpt[I].Align := 1; //center text + TextOpt[I].X := TextureSBG.X + (TextureSBG.W / 2); + end; end; end; diff --git a/cmake/src/menu/UMenuText.pas b/cmake/src/menu/UMenuText.pas index 6cf53200..b5507327 100644 --- a/cmake/src/menu/UMenuText.pas +++ b/cmake/src/menu/UMenuText.pas @@ -34,29 +34,29 @@ interface {$I switches.inc} uses - TextGL, - UTexture, - gl, math, SysUtils, - SDL; + gl, + SDL, + TextGL, + UTexture; type TText = class private - SelectBool: boolean; - TextString: string; - TextTiles: array of string; + SelectBool: boolean; + TextString: string; + TextTiles: array of string; - STicks: Cardinal; - SelectBlink: boolean; + STicks: cardinal; + SelectBlink: boolean; public X: real; Y: real; Z: real; - MoveX: real; //Some Modifier for X - Position that don't affect the real Y - MoveY: real; //Some Modifier for Y - Position that don't affect the real Y - W: real; //text wider than W is broken + MoveX: real; // some modifier for x - position that don't affect the real Y + MoveY: real; // some modifier for y - position that don't affect the real Y + W: real; // text wider than W is broken // H: real; Size: real; ColR: real; @@ -64,13 +64,13 @@ type ColB: real; Alpha: real; Int: real; - Style: integer; - Visible: boolean; - Align: integer; // 0 = left, 1 = center, 2 = right + Style: integer; + Visible: boolean; + Align: integer; // 0 = left, 1 = center, 2 = right - //Reflection - Reflection: boolean; - ReflectionSpacing: real; + // reflection + Reflection: boolean; + ReflectionSpacing: real; procedure SetSelect(Value: boolean); property Selected: boolean read SelectBool write SetSelect; @@ -78,7 +78,7 @@ type procedure SetText(Value: string); property Text: string read TextString write SetText; - procedure DeleteLastL; //Procedure to Delete Last Letter + procedure DeleteLastL; // procedure to delete last letter procedure Draw; constructor Create; overload; @@ -88,26 +88,27 @@ type implementation -uses UGraphic, - StrUtils; +uses + StrUtils, + UGraphic; procedure TText.SetSelect(Value: boolean); begin SelectBool := Value; - //Set Cursor Visible - SelectBlink := True; + // set cursor visible + SelectBlink := true; STicks := SDL_GetTicks() div 550; end; procedure TText.SetText(Value: string); var - NextPos: cardinal; // NextPos of a Space etc. - LastPos: cardinal; // LastPos " - LastBreak: cardinal; // Last Break - isBreak: boolean; // True if the Break is not Caused because the Text is out of the area - FirstWord: word; // Is First Word after Break? - Len: word; // Length of the Tiles Array + NextPos: cardinal; // next pos of a space etc. + LastPos: cardinal; // last pos " + LastBreak: cardinal; // last break + isBreak: boolean; // true if the break is not caused because the text is out of the area + FirstWord: word; // is first word after break? + Len: word; // length of the tiles array function GetNextPos: boolean; var @@ -115,16 +116,16 @@ var begin LastPos := NextPos; - //Next Space (If Width is given) + // next space (if width is given) if (W > 0) then T1 := PosEx(' ', Value, LastPos + 1) else T1 := Length(Value); - {//Next - + {// next - T2 := PosEx('-', Value, LastPos + 1);} - //Next Break + // next break T3 := PosEx('\n', Value, LastPos + 1); if T1 = 0 then @@ -134,7 +135,7 @@ var if T3 = 0 then T3 := Length(Value); - //Get Nearest Pos + // get nearest pos NextPos := min(T1, T3{min(T2, T3)}); if (LastPos = cardinal(Length(Value))) then @@ -161,14 +162,14 @@ var end; begin - //Set TExtstring + // set TextString TextString := Value; - //Set Cursor Visible - SelectBlink := True; + // set cursor visible + SelectBlink := true; STicks := SDL_GetTicks() div 550; - //Exit if there is no Need to Create Tiles + // exit if there is no need to create tiles if (W <= 0) and (Pos('\n', Value) = 0) then begin SetLength (TextTiles, 1); @@ -176,12 +177,12 @@ begin Exit; end; - //Create Tiles - //Reset Text Array + // create tiles + // reset text array SetLength (TextTiles, 0); Len := 0; - //Reset Counter Vars + // reset counter vars LastPos := 1; NextPos := 1; LastBreak := 1; @@ -189,57 +190,57 @@ begin if (W > 0) then begin - //Set Font Properties + // set font properties SetFontStyle(Style); SetFontSize(Size); end; - //go Through Text + // go through text while (GetNextPos) do begin - //Break in Text + // break in text if isBreak then begin - //Look for Break before the Break + // look for break before the break if (glTextWidth(Copy(Value, LastBreak, NextPos - LastBreak + 1)) > W) AND (NextPos-LastPos > 1) then begin - isBreak := False; - //Not the First word after Break, so we don't have to break within a word + isBreak := false; + // not the first word after break, so we don't have to break within a word if (FirstWord > 1) then begin - //Add Break before actual Position, because there the Text fits the Area + // add break before actual position, because there the text fits the area AddBreak(LastBreak, LastPos); end - else //First Word after Break Break within the Word + else // first word after break break within the word begin - //ToDo - //AddBreak(LastBreak, LastBreak + 155); + // to do + // AddBreak(LastBreak, LastBreak + 155); end; end; - isBreak := True; - //Add Break from Text + isBreak := true; + // add break from text AddBreak(LastBreak, NextPos); end - //Text comes out of the Text Area -> CreateBreak + // text comes out of the text area -> createbreak else if (glTextWidth(Copy(Value, LastBreak, NextPos - LastBreak + 1)) > W) then begin - //Not the First word after Break, so we don't have to break within a word + // not the first word after break, so we don't have to break within a word if (FirstWord > 1) then begin - //Add Break before actual Position, because there the Text fits the Area + // add break before actual position, because there the text fits the area AddBreak(LastBreak, LastPos); end - else //First Word after Break -> Break within the Word + else // first word after break -> break within the word begin - //ToDo - //AddBreak(LastBreak, LastBreak + 155); + // to do + // AddBreak(LastBreak, LastBreak + 155); end; end; //end; Inc(FirstWord) end; - //Add Ending + // add ending AddBreak(LastBreak, Length(Value)+1); end; @@ -260,34 +261,35 @@ procedure TText.Draw; var X2, Y2: real; Text2: string; - I: cardinal; + I: integer; + Ticks: cardinal; begin if Visible then begin SetFontStyle(Style); SetFontSize(Size); - SetFontItalic(False); + SetFontItalic(false); glColor4f(ColR*Int, ColG*Int, ColB*Int, Alpha); - //Reflection - if Reflection = true then + // reflection + if Reflection then SetFontReflection(true, ReflectionSpacing) else SetFontReflection(false,0); - //if selected set blink... + // if selected set blink... if SelectBool then begin - I := SDL_GetTicks() div 550; - if I <> STicks then - begin //Change Visability - STicks := I; + Ticks := SDL_GetTicks() div 550; + if Ticks <> STicks then + begin // change visability + STicks := Ticks; SelectBlink := Not SelectBlink; end; end; - {if (False) then //no width set draw as one long string + {if (false) then // no width set draw as one long string begin if not (SelectBool AND SelectBlink) then Text2 := Text @@ -306,20 +308,20 @@ begin end else begin} - //now use allways: - //draw text as many strings + // now use always: + // draw text as many strings Y2 := Y + MoveY; - for I := 0 to high(TextTiles) do + for I := 0 to High(TextTiles) do begin - if (not (SelectBool and SelectBlink)) or (I <> cardinal(high(TextTiles))) then + if (not (SelectBool and SelectBlink)) or (I <> High(TextTiles)) then Text2 := TextTiles[I] else Text2 := TextTiles[I] + '|'; case Align of - 0: X2 := X + MoveX; - 1: X2 := X + MoveX - glTextWidth(Text2)/2; - 2: X2 := X + MoveX - glTextWidth(Text2); + 1: X2 := X + MoveX - glTextWidth(Text2)/2; { centered } + 2: X2 := X + MoveX - glTextWidth(Text2); { right aligned } + else X2 := X + MoveX; { left aligned (default) } end; SetFontPos(X2, Y2); @@ -352,7 +354,14 @@ begin Create(X, Y, 0, 0, 30, 0, 0, 0, 0, Text, false, 0, 0); end; -constructor TText.Create(ParX, ParY, ParW: real; ParStyle: integer; ParSize, ParColR, ParColG, ParColB: real; ParAlign: integer; ParText: string; ParReflection: boolean; ParReflectionSpacing: real; ParZ:real); +constructor TText.Create(ParX, ParY, ParW: real; + ParStyle: integer; + ParSize, ParColR, ParColG, ParColB: real; + ParAlign: integer; + ParText: string; + ParReflection: boolean; + ParReflectionSpacing: real; + ParZ: real); begin inherited Create; Alpha := 1; @@ -370,8 +379,8 @@ begin Align := ParAlign; SelectBool := false; Visible := true; - Reflection:= ParReflection; - ReflectionSpacing:= ParReflectionSpacing; + Reflection := ParReflection; + ReflectionSpacing := ParReflectionSpacing; end; end. -- cgit v1.2.3