diff options
author | whiteshark0 <whiteshark0@b956fd51-792f-4845-bead-9b4dfca2ff2c> | 2009-05-31 14:10:42 +0000 |
---|---|---|
committer | whiteshark0 <whiteshark0@b956fd51-792f-4845-bead-9b4dfca2ff2c> | 2009-05-31 14:10:42 +0000 |
commit | 257854c587f0876a912cfbeb4fe0a30970d25a9b (patch) | |
tree | 43a87074b46eb6211e8c103510f9b2261fe2d08b /src/menu | |
parent | 1d3a28457fb5ff32d55435e31a5697fd383366d4 (diff) | |
download | usdx-257854c587f0876a912cfbeb4fe0a30970d25a9b.tar.gz usdx-257854c587f0876a912cfbeb4fe0a30970d25a9b.tar.xz usdx-257854c587f0876a912cfbeb4fe0a30970d25a9b.zip |
merged (experimental) mouse support patch by d0ccrazy
some changes to patch
- implemented software cursor (texturable)
- option to turn of mouse support or switch between hardware and software cursor
- hide software cursor if there is no mouse activity for 5 seconds
- soft fade in and out for software cursor
- some test cursor-textures for deluxe theme (mog pls change these horible looking images)
git-svn-id: svn://svn.code.sf.net/p/ultrastardx/svn/trunk@1789 b956fd51-792f-4845-bead-9b4dfca2ff2c
Diffstat (limited to 'src/menu')
-rw-r--r-- | src/menu/UDisplay.pas | 191 | ||||
-rw-r--r-- | src/menu/UMenu.pas | 119 |
2 files changed, 303 insertions, 7 deletions
diff --git a/src/menu/UDisplay.pas b/src/menu/UDisplay.pas index 58c416db..10a80c00 100644 --- a/src/menu/UDisplay.pas +++ b/src/menu/UDisplay.pas @@ -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,11 +89,28 @@ 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; +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 uses @@ -125,6 +153,15 @@ begin //Set LastError for OSD to No Error OSD_LastError := 'No Errors'; + + // software cursor default values + Cursor_LastMove := SDL_GetTicks; + 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,160 @@ 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; + + if not Cursor_Visible 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; diff --git a/src/menu/UMenu.pas b/src/menu/UMenu.pas index ceb4ac77..7d8bdce8 100644 --- a/src/menu/UMenu.pas +++ b/src/menu/UMenu.pas @@ -35,6 +35,7 @@ interface uses gl, + SDL, SysUtils, UTexture, UMenuStatic, @@ -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,7 +84,7 @@ 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 @@ -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,8 +170,11 @@ type end; const - pmMove = 1; - pmClick = 2; + MENU_MDOWN = 8; + MENU_MUP = 0; + + pmMove = 1; + pmClick = 2; pmUnClick = 3; iButton = 0; // interaction type @@ -221,6 +227,8 @@ begin ButtonPos := -1; Background := nil; + + RightMbESC := True; end; { constructor TMenu.Create(Back: string); @@ -1595,6 +1603,103 @@ 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 |