/*
* 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$
*/
#if 0
#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);
}
};
#endif