RenderWindow.cpp

00001 
00002 //
00003 // SFML - Simple and Fast Multimedia Library
00004 // Copyright (C) 2007 Laurent Gomila (laurent.gom@gmail.com)
00005 //
00006 // This software is provided 'as-is', without any express or implied warranty.
00007 // In no event will the authors be held liable for any damages arising from the use of this software.
00008 //
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it freely,
00011 // subject to the following restrictions:
00012 //
00013 // 1. The origin of this software must not be misrepresented;
00014 //    you must not claim that you wrote the original software.
00015 //    If you use this software in a product, an acknowledgment
00016 //    in the product documentation would be appreciated but is not required.
00017 //
00018 // 2. Altered source versions must be plainly marked as such,
00019 //    and must not be misrepresented as being the original software.
00020 //
00021 // 3. This notice may not be removed or altered from any source distribution.
00022 //
00024 
00026 // Headers
00028 #include <SFML/Graphics/RenderWindow.hpp>
00029 #include <SFML/Graphics/Drawable.hpp>
00030 #include <SFML/Graphics/GraphicsDevice.hpp>
00031 #include <SFML/Graphics/Image.hpp>
00032 #include <SFML/Graphics/OpenGL.hpp>
00033 #include <iostream>
00034 
00035 
00036 namespace sf
00037 {
00041 RenderWindow::RenderWindow() :
00042 myBackgroundColor(Color(0, 0, 0, 255)),
00043 myOpenGLMode     (false)
00044 {
00045 
00046 }
00047 
00048 
00052 RenderWindow::RenderWindow(VideoMode Mode, const std::string& Title, RenderWindow::Style WindowStyle, int AntialiasingLevel) :
00053 myBackgroundColor(Color(0, 0, 0, 255)),
00054 myOpenGLMode     (false)
00055 {
00056     Create(Mode, Title, WindowStyle, AntialiasingLevel);
00057 }
00058 
00059 
00063 RenderWindow::RenderWindow(WindowHandle Handle, int AntialiasingLevel) :
00064 myBackgroundColor(Color(0, 0, 0, 255)),
00065 myOpenGLMode     (false)
00066 {
00067     Create(Handle, AntialiasingLevel);
00068 }
00069 
00070 
00074 RenderWindow::~RenderWindow()
00075 {
00076     // Nothing to do...
00077 }
00078 
00079 
00083 void RenderWindow::Create(VideoMode Mode, const std::string& Title, RenderWindow::Style WindowStyle, int AntialiasingLevel)
00084 {
00085     // Let the base class do the job
00086     Window::Create(Mode, Title, WindowStyle, AntialiasingLevel);
00087 
00088     // Initialize the rendering states
00089     Initialize();
00090 }
00091 
00092 
00096 void RenderWindow::Create(WindowHandle Handle, int AntialiasingLevel)
00097 {
00098     // Let the base class do the job
00099     Window::Create(Handle, AntialiasingLevel);
00100 
00101     // Initialize the rendering states
00102     Initialize();
00103 }
00104 
00105 
00109 void RenderWindow::Display()
00110 {
00111     // Discard display if we are in OpenGL custom rendering mode (it would mess up the render states)
00112     if (myOpenGLMode)
00113     {
00114         std::cerr << "You cannot display a window while in OpenGL mode ; call EndOpenGL() before calling Display()" << std::endl;
00115         return;
00116     }
00117 
00118     // Set our window as the current target for rendering
00119     if (Window::SetCurrent())
00120     {
00121         // Display backbuffer on screen
00122         Window::Display();
00123 
00124         // Find which buffers we must clear
00125         GLbitfield                ClearBits  = GL_COLOR_BUFFER_BIT;
00126         if (GetDepthBits()   > 0) ClearBits |= GL_DEPTH_BUFFER_BIT;
00127         if (GetStencilBits() > 0) ClearBits |= GL_STENCIL_BUFFER_BIT;
00128         
00129         // Clear the color/depth/stencil buffers for next frame
00130         GLCheck(glClearColor(myBackgroundColor.r / 255.f,
00131                              myBackgroundColor.g / 255.f,
00132                              myBackgroundColor.b / 255.f,
00133                              myBackgroundColor.a / 255.f));
00134         GLCheck(glClear(ClearBits));
00135 
00136         // Reset transformations
00137         GLCheck(glMatrixMode(GL_MODELVIEW));
00138         GLCheck(glLoadIdentity());
00139     }
00140 }
00141 
00142 
00146 void RenderWindow::Draw(Drawable& Object)
00147 {
00148     // Discard draw if we are in OpenGL custom rendering mode (it would mess up the render states)
00149     if (myOpenGLMode)
00150     {
00151         std::cerr << "You cannot use SFML rendering while in OpenGL mode ; call EndOpenGL() before calling Draw()" << std::endl;
00152         return;
00153     }
00154 
00155     // Set our window as the current target for rendering
00156     if (Window::SetCurrent())
00157     {
00158         // Let the object draw itself
00159         Object.Draw(*this);
00160     }
00161 }
00162 
00163 
00167 Image RenderWindow::Capture() const
00168 {
00169     // Get the window dimensions
00170     const unsigned int Width  = GetWidth();
00171     const unsigned int Height = GetHeight();
00172 
00173     // Set our window as the current target for rendering
00174     if (Window::SetCurrent())
00175     {
00176         // Get pixels from the backbuffer
00177         std::vector<Uint32> Pixels(Width * Height);
00178         glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &Pixels[0]);
00179 
00180         // Create an image from it and return it
00181         return Image(Width, Height, &Pixels[0]);
00182     }
00183     else
00184     {
00185         return Image(Width, Height, Color::White);
00186     }
00187 }
00188 
00189 
00193 void RenderWindow::SetBackgroundColor(const Color& Col)
00194 {
00195     myBackgroundColor = Col;
00196 }
00197 
00198 
00202 bool RenderWindow::GetEvent(Event& EventReceived)
00203 {
00204     // Forward to base class
00205     if (Window::GetEvent(EventReceived))
00206     {
00207         // Intercept resize events, because we have to adjust the viewport to new size
00208         if (EventReceived.Type == Event::Resize)
00209             GLCheck(glViewport(0, 0, EventReceived.Size.Width, EventReceived.Size.Height));
00210 
00211         return true;
00212     }
00213 
00214     return false;
00215 }
00216 
00217 
00221 void RenderWindow::SetView(const View* NewView)
00222 {
00223     // Discard display if we are in OpenGL custom rendering mode (it would mess up the render states)
00224     if (myOpenGLMode)
00225     {
00226         std::cerr << "You cannot change the view while in OpenGL mode ; call EndOpenGL() before setting a new SFML view" << std::endl;
00227         return;
00228     }
00229 
00230     // Set our window as the current target for rendering
00231     if (Window::SetCurrent())
00232     {
00233         // If a null pointer is passed, switch to default view
00234         if (NewView == NULL)
00235             NewView = &myDefaultView;
00236 
00237         // Compute view rectangle coordinates
00238         float X = NewView->Left + NewView->Width  / 2;
00239         float Y = NewView->Top  + NewView->Height / 2;
00240         float HalfWidth  = NewView->Width  / (2 * NewView->Zoom);
00241         float HalfHeight = NewView->Height / (2 * NewView->Zoom);
00242 
00243         // Store view rectangle for optimization purpose
00244         myCurrentRect = FloatRect(X - HalfWidth, Y - HalfHeight, X + HalfWidth, Y + HalfHeight);
00245 
00246         // Update the projection matrix according to the new view
00247         GLCheck(glMatrixMode(GL_PROJECTION));
00248         GLCheck(glLoadIdentity());
00249         GLCheck(glOrtho(myCurrentRect.Left, myCurrentRect.Right, myCurrentRect.Bottom, myCurrentRect.Top, -1, 1));
00250     }
00251 }
00252 
00253 
00257 const FloatRect& RenderWindow::GetViewRect() const
00258 {
00259     return myCurrentRect;
00260 }
00261 
00262 
00266 void RenderWindow::BeginOpenGL()
00267 {
00268     if (!myOpenGLMode && Window::SetCurrent())
00269     {
00270         // Save the current matrices
00271         GLCheck(glMatrixMode(GL_PROJECTION));
00272         GLCheck(glPushMatrix());
00273         GLCheck(glMatrixMode(GL_MODELVIEW));
00274         GLCheck(glPushMatrix());
00275 
00276         // Save current render states
00277         GLCheck(glPushAttrib(GL_ALL_ATTRIB_BITS));
00278 
00279         // Set OpenGL mode flag
00280         myOpenGLMode = true;
00281     }
00282 }
00283 
00284 
00288 void RenderWindow::EndOpenGL()
00289 {
00290     if (myOpenGLMode && Window::SetCurrent())
00291     {
00292         // Restore render states
00293         GLCheck(glPopAttrib());
00294 
00295         // Restore the matrices
00296         GLCheck(glMatrixMode(GL_MODELVIEW));
00297         GLCheck(glPopMatrix());
00298         GLCheck(glMatrixMode(GL_PROJECTION));
00299         GLCheck(glPopMatrix());
00300 
00301         // Clear OpenGL mode flag
00302         myOpenGLMode = false;
00303     }
00304 }
00305 
00306 
00310 void RenderWindow::Initialize()
00311 {
00312     if (Window::SetCurrent())
00313     {
00314         // Set default OpenGL states
00315         GLCheck(glEnable(GL_ALPHA_TEST));
00316         GLCheck(glAlphaFunc(GL_GREATER, 0));
00317         GLCheck(glEnable(GL_BLEND));
00318         GLCheck(glEnable(GL_TEXTURE_2D));
00319         GLCheck(glDisable(GL_LIGHTING));
00320         GLCheck(glDisable(GL_DEPTH_TEST));
00321         GLCheck(glDisable(GL_CULL_FACE));
00322         GLCheck(glShadeModel(GL_SMOOTH));
00323         GLCheck(glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST));
00324         GLCheck(glClearDepth(1.f));
00325         GLCheck(glClearStencil(0));
00326 
00327         // Setup the default view
00328         myDefaultView.Left   = 0;
00329         myDefaultView.Top    = 0;
00330         myDefaultView.Width  = static_cast<float>(GetWidth());
00331         myDefaultView.Height = static_cast<float>(GetHeight());
00332         myDefaultView.Zoom   = 1.f;
00333         SetView(NULL);
00334     }
00335 }
00336 
00337 } // namespace sf