aboutsummaryrefslogtreecommitdiffstats
path: root/src/menu
diff options
context:
space:
mode:
authorwhiteshark0 <whiteshark0@b956fd51-792f-4845-bead-9b4dfca2ff2c>2009-05-31 14:10:42 +0000
committerwhiteshark0 <whiteshark0@b956fd51-792f-4845-bead-9b4dfca2ff2c>2009-05-31 14:10:42 +0000
commit257854c587f0876a912cfbeb4fe0a30970d25a9b (patch)
tree43a87074b46eb6211e8c103510f9b2261fe2d08b /src/menu
parent1d3a28457fb5ff32d55435e31a5697fd383366d4 (diff)
downloadusdx-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.pas191
-rw-r--r--src/menu/UMenu.pas119
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