diff options
-rw-r--r-- | src/menu/UDisplay.pas | 648 | ||||
-rw-r--r-- | src/menu/display.cpp | 536 | ||||
-rw-r--r-- | src/menu/display.hpp | 112 |
3 files changed, 648 insertions, 648 deletions
diff --git a/src/menu/UDisplay.pas b/src/menu/UDisplay.pas deleted file mode 100644 index 927a1256..00000000 --- a/src/menu/UDisplay.pas +++ /dev/null @@ -1,648 +0,0 @@ -{* UltraStar Deluxe - Karaoke Game - * - * UltraStar Deluxe is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * 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 2 - * 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; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - *} - -unit UDisplay; - -interface - -{$IFDEF FPC} - {$MODE Delphi} -{$ENDIF} - -{$I switches.inc} - -uses - UCommon, - SDL, - gl, - glu, - SysUtils, - UMenu, - UPath; - -type - TDisplay = class - private - //fade-to-black-hack - BlackScreen: boolean; - - FadeEnabled: boolean; // true if fading is enabled - FadeFailed: boolean; // true if fading is possible (enough memory, etc.) - FadeState: integer; // fading state, 0 means that the fade texture must be initialized - LastFadeTime: cardinal; // last fade update time - - FadeTex: array[1..2] of GLuint; - - FPSCounter: cardinal; - LastFPS: cardinal; - NextFPSSwap: cardinal; - - 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; - - { called by MoveCursor and OnMouseButton to update last move and start fade in } - procedure UpdateCursorFade; - public - NextScreen: PMenu; - CurrentScreen: PMenu; - - //popup data - NextScreenWithCheck: Pmenu; - CheckOK: boolean; - - // FIXME: Fade is set to 0 in UMain and other files but not used here anymore. - Fade: real; - - constructor Create; - destructor Destroy; override; - - procedure SaveScreenShot; - - function Draw: boolean; - - { calls ParseInput of cur or next Screen if assigned } - function ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown : boolean): 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); - - { called when left or right mousebutton is pressed or released } - procedure OnMouseButton(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 - TextGL, - UCommandLine, - UGraphic, - UIni, - UImage, - ULog, - UMain, - UTexture, - UTime, - ULanguage, - UPathUtils; - -constructor TDisplay.Create; -var - i: integer; -begin - inherited Create; - - //popup hack - CheckOK := false; - NextScreen := nil; - NextScreenWithCheck := nil; - BlackScreen := false; - - // fade mod - FadeState := 0; - FadeEnabled := (Ini.ScreenFade = 1); - FadeFailed := false; - - glGenTextures(2, @FadeTex); - - for i := 1 to 2 do - begin - glBindTexture(GL_TEXTURE_2D, FadeTex[i]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - end; - - //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; -begin - glDeleteTextures(2, @FadeTex); - inherited Destroy; -end; - -function TDisplay.Draw: boolean; -var - S: integer; - FadeStateSquare: real; - currentTime: cardinal; - glError: glEnum; -begin - Result := true; - - //We don't need this here anymore, - //Because the background care about cleaning the buffers - //glClearColor(1, 1, 1 , 0); - //glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); - - for S := 1 to Screens do - begin - ScreenAct := S; - - //if Screens = 1 then ScreenX := 0; - //if (Screens = 2) and (S = 1) then ScreenX := -1; - //if (Screens = 2) and (S = 2) then ScreenX := 1; - ScreenX := 0; - - glViewPort((S-1) * ScreenW div Screens, 0, ScreenW div Screens, ScreenH); - - // popup hack - // check was successful... move on - if CheckOK then - begin - if assigned(NextScreenWithCheck) then - begin - NextScreen := NextScreenWithCheck; - NextScreenWithCheck := nil; - CheckOk := false; - end - else - begin - // on end of game fade to black before exit - BlackScreen := true; - end; - end; - - if (not assigned(NextScreen)) and (not BlackScreen) then - begin - CurrentScreen.Draw; - - //popup mod - if (ScreenPopupError <> nil) and ScreenPopupError.Visible then - ScreenPopupError.Draw - else if (ScreenPopupInfo <> nil) and ScreenPopupInfo.Visible then - ScreenPopupInfo.Draw - else if (ScreenPopupCheck <> nil) and ScreenPopupCheck.Visible then - ScreenPopupCheck.Draw; - - // fade mod - FadeState := 0; - if ((Ini.ScreenFade = 1) and (not FadeFailed)) then - FadeEnabled := true - else if (Ini.ScreenFade = 0) then - FadeEnabled := false; - end - else - begin - // disable fading if initialization failed - if (FadeEnabled and FadeFailed) then - begin - FadeEnabled := false; - end; - - if (FadeEnabled and not FadeFailed) then - begin - //Create Fading texture if we're just starting - if FadeState = 0 then - begin - // save old viewport and resize to fit texture - glPushAttrib(GL_VIEWPORT_BIT); - glViewPort(0, 0, 512, 512); - - // draw screen that will be faded - CurrentScreen.Draw; - - // clear OpenGL errors, otherwise fading might be disabled due to some - // older errors in previous OpenGL calls. - glGetError(); - - // copy screen to texture - glBindTexture(GL_TEXTURE_2D, FadeTex[S]); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 512, 512, 0); - glError := glGetError(); - if (glError <> GL_NO_ERROR) then - begin - FadeFailed := true; - Log.LogWarn('Fading disabled: ' + gluErrorString(glError), 'TDisplay.Draw'); - end; - - // restore viewport - glPopAttrib(); - - // blackscreen-hack - if not BlackScreen then - NextScreen.OnShow; - - // update fade state - LastFadeTime := SDL_GetTicks(); - if (S = 2) or (Screens = 1) then - FadeState := FadeState + 1; - end; // end texture creation in first fading step - - //do some time-based fading - currentTime := SDL_GetTicks(); - if (currentTime > LastFadeTime+30) and (S = 1) then - begin - FadeState := FadeState + 4; - LastFadeTime := currentTime; - end; - - // blackscreen-hack - if not BlackScreen then - NextScreen.Draw // draw next screen - else if ScreenAct = 1 then - begin - glClearColor(0, 0, 0 , 0); - glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); - end; - - // and draw old screen over it... slowly fading out - - FadeStateSquare := (FadeState*FadeState)/10000; - - glBindTexture(GL_TEXTURE_2D, FadeTex[S]); - glColor4f(1, 1, 1, 1-FadeStateSquare); - - glEnable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_BLEND); - glBegin(GL_QUADS); - glTexCoord2f(0+FadeStateSquare, 0+FadeStateSquare); glVertex2f(0, 600); - glTexCoord2f(0+FadeStateSquare, 1-FadeStateSquare); glVertex2f(0, 0); - glTexCoord2f(1-FadeStateSquare, 1-FadeStateSquare); glVertex2f(800, 0); - glTexCoord2f(1-FadeStateSquare, 0+FadeStateSquare); glVertex2f(800, 600); - glEnd; - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - end -// blackscreen hack - else if not BlackScreen then - begin - NextScreen.OnShow; - end; - - if ((FadeState > 40) or (not FadeEnabled) or FadeFailed) and (S = 1) then - begin - // fade out complete... - FadeState := 0; - CurrentScreen.onHide; - CurrentScreen.ShowFinish := false; - CurrentScreen := NextScreen; - NextScreen := nil; - if not BlackScreen then - begin - CurrentScreen.OnShowFinish; - CurrentScreen.ShowFinish := true; - end - else - begin - Result := false; - Break; - end; - end; - end; // if - -// Draw OSD only on first Screen if Debug Mode is enabled - 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 by MoveCursor and OnMouseButton to update last move and start fade in } -procedure TDisplay.UpdateCursorFade; -var - Ticks: cardinal; -begin - 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; - -{ called when cursor moves, positioning of software cursor } -procedure TDisplay.MoveCursor(X, Y: double); -begin - if (Ini.Mouse = 2) and - ((X <> Cursor_X) or (Y <> Cursor_Y)) then - begin - Cursor_X := X; - Cursor_Y := Y; - - UpdateCursorFade; - end; -end; - -{ called when left or right mousebutton is pressed or released } -procedure TDisplay.OnMouseButton(Pressed: boolean); -begin - if (Ini.Mouse = 2) then - begin - Cursor_Pressed := Pressed; - - UpdateCursorFade; - 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; - -function TDisplay.ParseInput(PressedKey: cardinal; CharCode: UCS4Char; PressedDown : boolean): boolean; -begin - if (assigned(NextScreen)) then - Result := NextScreen^.ParseInput(PressedKey, CharCode, PressedDown) - else if (assigned(CurrentScreen)) then - Result := CurrentScreen^.ParseInput(PressedKey, CharCode, PressedDown) - else - Result := True; -end; - -procedure TDisplay.SaveScreenShot; -var - Num: integer; - FileName: IPath; - Prefix: UTF8String; - ScreenData: PChar; - Surface: PSDL_Surface; - Success: boolean; - Align: integer; - RowSize: integer; -begin - // Exit if Screenshot-path does not exist or read-only - if (ScreenshotsPath.IsUnset) then - Exit; - - for Num := 1 to 9999 do - begin - // fill prefix to 4 digits with leading '0', e.g. '0001' - Prefix := Format('screenshot%.4d', [Num]); - FileName := ScreenshotsPath.Append(Prefix + '.png'); - if not FileName.Exists() then - break; - end; - - // we must take the row-alignment (4byte by default) into account - glGetIntegerv(GL_PACK_ALIGNMENT, @Align); - // calc aligned row-size - RowSize := ((ScreenW*3 + (Align-1)) div Align) * Align; - - GetMem(ScreenData, RowSize * ScreenH); - glReadPixels(0, 0, ScreenW, ScreenH, GL_RGB, GL_UNSIGNED_BYTE, ScreenData); - // on big endian machines (powerpc) this may need to be changed to - // Needs to be tests. KaMiSchi Sept 2008 - // in this case one may have to add " glext, " to the list of used units - // glReadPixels(0, 0, ScreenW, ScreenH, GL_BGR, GL_UNSIGNED_BYTE, ScreenData); - Surface := SDL_CreateRGBSurfaceFrom( - ScreenData, ScreenW, ScreenH, 24, RowSize, - $0000FF, $00FF00, $FF0000, 0); - - // Success := WriteJPGImage(FileName, Surface, 95); - // Success := WriteBMPImage(FileName, Surface); - Success := WritePNGImage(FileName, Surface); - if Success then - ScreenPopupInfo.ShowPopup(Format(Language.Translate('SCREENSHOT_SAVED'), [FileName.GetName.ToUTF8()])) - else - ScreenPopupError.ShowPopup(Language.Translate('SCREENSHOT_FAILED')); - - SDL_FreeSurface(Surface); - FreeMem(ScreenData); -end; - -//------------ -// DrawDebugInformation - procedure draw fps and some other informations on screen -//------------ -procedure TDisplay.DrawDebugInformation; -var - Ticks: cardinal; -begin - // Some White Background for information - glEnable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - glColor4f(1, 1, 1, 0.5); - glBegin(GL_QUADS); - glVertex2f(690, 44); - glVertex2f(690, 0); - glVertex2f(800, 0); - glVertex2f(800, 44); - glEnd; - glDisable(GL_BLEND); - - // set font specs - SetFontStyle(0); - SetFontSize(21); - SetFontItalic(false); - glColor4f(0, 0, 0, 1); - - // calculate fps - Ticks := SDL_GetTicks(); - if (Ticks >= NextFPSSwap) then - begin - LastFPS := FPSCounter * 4; - FPSCounter := 0; - NextFPSSwap := Ticks + 250; - end; - - Inc(FPSCounter); - - // draw text - - // fps - SetFontPos(695, 0); - glPrint ('FPS: ' + InttoStr(LastFPS)); - - // rspeed - SetFontPos(695, 13); - glPrint ('RSpeed: ' + InttoStr(Round(1000 * TimeMid))); - - // lasterror - SetFontPos(695, 26); - glColor4f(1, 0, 0, 1); - glPrint (OSD_LastError); - - glColor4f(1, 1, 1, 1); -end; - -end. diff --git a/src/menu/display.cpp b/src/menu/display.cpp new file mode 100644 index 00000000..200f961f --- /dev/null +++ b/src/menu/display.cpp @@ -0,0 +1,536 @@ +/* + * UltraStar Deluxe - Karaoke Game + * + * UltraStar Deluxe is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#include "display.hpp" +#include <math.h> +#include <SDL/SDL.h> +#include <GL/glu.h> + +// constants for software cursor effects time in milliseconds +const int Cursor_FadeIn_Time = 500; // seconds the fade in effect lasts +const int Cursor_FadeOut_Time = 2000; // seconds the fade out effect lasts +const int Cursor_AutoHide_Time = 5000; // seconds until auto fade out starts if there is no mouse movement + +namespace usdx +{ + Display* Display::get_instance(void) + { + if (!instance) { + instance = new Display(); + } + + return instance; + } + + Display::Display(void) + { + //popup hack + check_ok = false; + next_screen = NULL; + next_screen_with_check = NULL; + black_screen = false; + + // fade mod + fade_state = 0; + fade_enabled = (Ini.ScreenFade == 1); + fade_failed = false; + + glGenTextures(2, fade_tex); + + for (int i = 0; i < 2; i++) { + glBindTexture(GL_TEXTURE_2D, fade_tex[i]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } + + //Set LastError for OSD to No Error + osd_last_error = "No Errors"; + + // software cursor default values + cursor_last_move = 0; + cursor_visible = false; + cursor_pressed = false; + cursor_x = -1; + cursor_y = -1; + cursor_fade = false; + cursor_hidden_by_screen = true; + } + + Display::~Display(void) + { + glDeleteTextures(2, fade_tex); + } + + bool Display::draw(void) + { + //We don't need this here anymore, + //Because the background care about cleaning the buffers + //glClearColor(1, 1, 1 , 0); + //glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); + + for (int s = 0; s < screens; s++) + { + int ScreenAct = s; + + //if Screens = 1 then ScreenX := 0; + //if (Screens = 2) and (S = 1) then ScreenX := -1; + //if (Screens = 2) and (S = 2) then ScreenX := 1; + int ScreenX = 0; + + glViewPort((s-1) * screen_w / screens, 0, screen_w / screens, screen_h); + + // popup hack + // check was successful... move on + if (check_ok) { + if (next_screen_with_check) { + next_screen = next_screen_with_check; + next_screen_with_check = NULL; + check_ok = false; + } + else { + // on end of game fade to black before exit + black_screen = true; + } + } + + if (!next_screen && !black_screen) { + current_screen->Draw(); + + //popup mod + if (screen_popup_error && screen_popup_error->visible) + screen_popup_error->Draw(); + else if (screen_popup_info && screen_popup_info->visible) + screen_popup_info->Draw(); + else if (screen_popup_check && screen_popup_check->visible) + screen_popup_check->Draw(); + + // fade mod + fade_state = 0; + if ((Ini.ScreenFade == 1) && !fade_failed) + fade_enabled = true; + else if (Ini.ScreenFade == 0) + fade_enabled = false; + } + else { + // disable fading if initialization failed + if (fade_enabled && fade_failed) + fade_enabled = false; + + if (fade_enabled && !fade_failed) { + //Create Fading texture if we're just starting + if (fade_state == 0) { + // save old viewport and resize to fit texture + glPushAttrib(GL_VIEWPORT_BIT); + glViewPort(0, 0, 512, 512); + + // draw screen that will be faded + current_screen->Draw(); + + // clear OpenGL errors, otherwise fading might be disabled due to some + // older errors in previous OpenGL calls. + glGetError(); + + // copy screen to texture + glBindTexture(GL_TEXTURE_2D, fade_tex[s]); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 512, 512, 0); + + GLenum glError = glGetError(); + if (glError != GL_NO_ERROR) { + fade_failed = true; + Log->LogWarn(std::string("Fading disabled: ") + gluErrorString(glError), "TDisplay.Draw"); + } + + // restore viewport + glPopAttrib(); + + // blackscreen-hack + if (!black_screen) + next_screen->on_show(); + + // update fade state + last_fade_time = SDL_GetTicks(); + if ((s == 1) || (screens == 1)) + fade_state++; + } // end texture creation in first fading step + + //do some time-based fading + unsigned int current_time = SDL_GetTicks(); + if ((current_time > last_fade_time + 30) && (s == 0)) + { + fade_state += 4; + last_fade_time = current_time; + } + + // blackscreen-hack + if (!black_screen) + next_screen->Draw(); // draw next screen + else if (screen_act == 0) + { + glClearColor(0, 0, 0 , 0); + glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT); + } + + // and draw old screen over it... slowly fading out + float fade_state_square = (fade_state * fade_state) / 10000.0; + + glBindTexture(GL_TEXTURE_2D, fade_tex[s]); + glColor4f(1, 1, 1, 1 - fade_state_square); + + glEnable(GL_TEXTURE_2D); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glBegin(GL_QUADS); + glTexCoord2f(0 + fade_state_square, 0 + fade_state_square); glVertex2f(0, 600); + glTexCoord2f(0 + fade_state_square, 1 - fade_state_square); glVertex2f(0, 0); + glTexCoord2f(1 - fade_state_square, 1 - fade_state_square); glVertex2f(800, 0); + glTexCoord2f(1 - fade_state_square, 0 + fade_state_square); glVertex2f(800, 600); + glEnd(); + glDisable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + } + + // blackscreen hack + else if (!black_screen) + next_screen->on_show(); + + if ((((fade_state > 40) || !fade_enabled) || fade_failed) && (s == 0)) { + // fade out complete... + fade_state = 0; + current_screen->on_hide(); + current_screen->show_finish = false; + current_screen = next_screen; + next_screen = NULL; + + if (!black_screen) { + current_screen->on_show_finish(); + current_screen->show_finish = true; + } + else { + return false; + } + } + } + + // Draw OSD only on first Screen if Debug Mode is enabled + if (((Ini->Debug == 1) || (Params->Debug)) && (s == 0)) + draw_debug_information(); + + } // for + + if (!black_screen) + draw_cursor(); + + return true; + } + + // sets SDL_ShowCursor depending on options set in Ini + void Display::set_cursor(void) + { + int cursor = 0; + + if ((current_screen != screen_sing) || (cursor_hidden_by_screen)) { + + // hide cursor on singscreen + if ((Ini->Mouse == 0) and (Ini->FullScreen == 0)) + // show sdl (os) cursor in window mode even when mouse support is off + cursor = 1; + + else if ((Ini->Mouse == 1)) + // show sdl (os) cursor when hardware cursor is selected + cursor = 1; + + if ((Ini->Mouse != 2)) + cursor_hidden_by_screen = false; + } + else if ((Ini.Mouse != 2)) + cursor_hidden_by_screen = true; + + SDL_ShowCursor(cursor); + + if (Ini->Mouse == 2) + { + if (cursor_hidden_by_screen) + { + // show software cursor + cursor_hidden_by_screen = false; + cursor_visible = false; + cursor_fade = false; + } + else if (current_screen == screen_sing) + { + // hide software cursor in singscreen + cursor_hidden_by_screen = true; + cursor_visible = false; + cursor_fade = false; + } + } + } + + // called by MoveCursor and OnMouseButton to update last move and start fade in + void Display::update_cursor_fade(void) + { + unsigned int ticks = SDL_GetTicks(); + + // fade in on movement (or button press) if not first movement + if ((!cursor_visible) && (cursor_last_move != 0)) + { + if (cursor_fade) // we use a trick here to consider progress of fade out + cursor_last_move = ticks - (int)(Cursor_FadeIn_Time * (1 - (ticks - cursor_last_move) / (float)Cursor_FadeOut_Time) + 0.5); + else + cursor_last_move = ticks; + + cursor_visible = true; + cursor_fade = true; + } + else if (!cursor_fade) + { + cursor_last_move = ticks; + } + } + + // called when cursor moves, positioning of software cursor + void Display::move_cursor(double x, double y) + { + if ((Ini->Mouse == 2) && ((x != cursor_x) || (y != cursor_y))) + { + cursor_x = x; + cursor_y = y; + + update_cursor_fade(); + } + } + + // called when left or right mousebutton is pressed or released + void Display::on_mouse_button(bool pressed) + { + if (Ini->Mouse == 2) + { + cursor_pressed = pressed; + update_cursor_fade(); + } + } + + // draws software cursor + void Display::draw_cursor(void) + { + float alpha; + unsigned int ticks; + if (Ini->Mouse == 2) + { + // draw software cursor + ticks = SDL_GetTicks(); + + if ((cursor_visible) && (cursor_last_move + Cursor_AutoHide_Time <= ticks)) + { + // start fade out after 5 secs w/o activity + cursor_visible = false; + cursor_last_move = ticks; + cursor_fade = true; + } + + // fading + if (cursor_fade) + { + if (cursor_visible) + { + // fade in + if (cursor_last_move + Cursor_FadeIn_Time <= ticks) + cursor_fade = false; + else + alpha = sin((ticks - cursor_last_move) * 0.5 * M_PI / Cursor_FadeIn_Time) * 0.7; + } + else + { + //fade out + if (cursor_last_move + Cursor_FadeOut_Time <= ticks) + cursor_fade = false; + else + alpha = cos((ticks - cursor_last_move) * 0.5 * M_PI / Cursor_FadeOut_Time) * 0.7; + } + } + + // no else if here because we may turn off fade in if block + if (!cursor_fade) + { + if (cursor_visible) + // alpha when cursor visible and not fading + alpha = 0.7; + else + // alpha when cursor is hidden + alpha = 0; + } + + if ((alpha > 0) && (!cursor_hidden_by_screen)) + { + glColor4f(1, 1, 1, alpha); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glDisable(GL_DEPTH_TEST); + + if ((cursor_pressed) && (tex_cursor_pressed->tex_num > 0)) + glBindTexture(GL_TEXTURE_2D, tex_cursor_pressed->tex_num); + else + glBindTexture(GL_TEXTURE_2D, tex_cursor_unpressed->tex_num); + + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(cursor_x, cursor_x); + + 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); + } + } + } + + bool Display::parse_input(unsigned int pressed_key, UCS4Char char_code, bool pressed_down) + { + if (next_screen) + return next_screen->parse_input(pressed_key, char_code, pressed_down); + + if (current_screen) + return current_screen->parse_input(pressed_key, char_code, pressed_down); + + return true; + } + + void Display::save_screen_shot() + { + Path *file_name; + std::string prefix; + char *screen_data; + SDL_Surface *surface; + bool success; + int align; + int row_size; + + // Exit if Screenshot-path does not exist or read-only + if (!screenshots_path) + return; + + for (int num = 1; num < 10000; num++) + { + /** TODO: + + // fill prefix to 4 digits with leading '0', e.g. '0001' + Prefix = Format('screenshot%.4d', [Num]); + FileName = ScreenshotsPath.Append(Prefix + '.png'); + + if not FileName.Exists() + break; + */ + } + + // we must take the row-alignment (4byte by default) into account + glGetIntegerv(GL_PACK_ALIGNMENT, &align); + + // calc aligned row-size + row_size = ((screen_w * 3 + (align - 1)) / align) * align; + + malloc(screen_data, row_size * screen_h); + glReadPixels(0, 0, screen_w, screen_h, GL_RGB, GL_UNSIGNED_BYTE, screen_data); + + // on big endian machines (powerpc) this may need to be changed to + // Needs to be tests. KaMiSchi Sept 2008 + // in this case one may have to add " glext, " to the list of used units + // glReadPixels(0, 0, ScreenW, ScreenH, GL_BGR, GL_UNSIGNED_BYTE, ScreenData); + Surface = SDL_CreateRGBSurfaceFrom( + screen_data, screen_w, screen_h, 24, row_size, + 0x0000ff, 0x00ff00, 0xff0000, 0); + + // Success = WriteJPGImage(FileName, Surface, 95); + // Success = WriteBMPImage(FileName, Surface); + success = WritePNGImage(file_name, surface); + if (success) + ScreenPopupInfo->ShowPopup(Format(Language.Translate("SCREENSHOT_SAVED"), [FileName.GetName.ToUTF8()])); + else + ScreenPopupError->ShowPopup(Language.Translate("SCREENSHOT_FAILED")); + + SDL_FreeSurface(surface); + free(screen_data); + } + + //------------ + // DrawDebugInformation - procedure draw fps and some other informations on screen + //------------ + void Display::draw_debug_information() + { + // Some White Background for information + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glColor4f(1, 1, 1, 0.5); + glBegin(GL_QUADS); + glVertex2f(690, 44); + glVertex2f(690, 0); + glVertex2f(800, 0); + glVertex2f(800, 44); + glEnd(); + glDisable(GL_BLEND); + + // set font specs + SetFontStyle(0); + SetFontSize(21); + SetFontItalic(false); + glColor4f(0, 0, 0, 1); + + // calculate fps + unsigned int ticks = SDL_GetTicks(); + if (ticks >= next_fps_swap) { + last_fps = fps_counter * 4; + fps_counter = 0; + next_fps_swap = ticks + 250; + } + + fps_counter++; + + // draw text + + // TODO: + // fps + SetFontPos(695, 0); + glPrint ("FPS: " + itoa(last_fps)); + + // rspeed + SetFontPos(695, 13); + glPrint ("RSpeed: " + itoa((int)(1000 * time_mid))); + + // lasterror + SetFontPos(695, 26); + glColor4f(1, 0, 0, 1); + glPrint(osd_last_error.c_str()); + + glColor4f(1, 1, 1, 1); + } +}; diff --git a/src/menu/display.hpp b/src/menu/display.hpp new file mode 100644 index 00000000..7b320c54 --- /dev/null +++ b/src/menu/display.hpp @@ -0,0 +1,112 @@ +/* + * UltraStar Deluxe - Karaoke Game + * + * UltraStar Deluxe is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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 2 + * 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef DISPLAY_HPP +#define DISPLAY_HPP + +#include <GL/gl.h> +#include <string> + +namespace usdx +{ + typedef unsigned long UCS4Char; + + class Display + { + protected: + //fade-to-black-hack + bool black_screen; + + bool fade_enabled; // true if fading is enabled + bool fade_failed; + int fade_state; // fading state, 0 means that the fade texture must be initialized + unsigned int last_fade_time; // last fade update time + + GLuint fade_tex[2]; + + unsigned int fps_counter; + unsigned int last_fps; + unsigned int next_fps_swap; + + std::string osd_last_error; + + // software cursor data + double cursor_x; + double cursor_y; + bool cursor_pressed; + bool cursor_hidden_by_screen; // hides software cursor and deactivate auto fade in + + // used for cursor fade out when there is no movement + bool cursor_visible; + unsigned int cursor_last_move; + bool cursor_fade; + + void draw_debug_information(void); + + // called by MoveCursor and OnMouseButton to update last move and start fade in + void update_cursor_fade(void); + + // Singleton + Display(void); + + static Display* instance; + public: + static Display* get_instance(); + + Menu* next_screen; + Menu* current_screen; + + //popup data + Menu* next_screen_with_check; + bool check_ok; + + // FIXME: Fade is set to 0 in UMain and other files but not used here anymore. + float Fade; + + ~Display(void); + + void save_screen_shot(void); + + bool draw(void); + + // calls ParseInput of cur or next Screen if assigned + bool parse_input(unsigned int pressed_key, UCS4Char char_code, bool pressed_down); + + // sets SDL_ShowCursor depending on options set in Ini + void set_cursor(void); + + // called when cursor moves, positioning of software cursor + void move_cursor(double x, double y); + + // called when left or right mousebutton is pressed or released + void on_mouse_button(bool pressed); + + // draws software cursor + void draw_cursor(); + }; +}; + +#endif |