summaryrefslogblamecommitdiff
path: root/src/gui/setup_video.cpp
blob: 78e26e5e8a1ae0c0908ff4a47ae9a085ae175b99 (plain) (tree)


















                                                                             

   
                

                 
 
                          







                                    
                        
                   
                      


                             
                           
                   
                    
                        
 
                             

                              








































                                                                           
                                             
                                          
                                                    


                                         



                                                                              




                           


                                                             
                                                                   
                                                             
                                                    
                                               

                                               
                                           




                                                                                           
                                                              
                                       
                                                
                                    

                                                                         
                                             

                                                                    
                                            
                                      

                                                              
                                            
                                                                         

                                            

                     
                                                 

                                                       
                                                              
 
                                



                                       

                                                             
                                      
                                        
                                          
                                                   
                                                
                                                
                                                                

                                                          

                                                              

                                                                

                               
                                     
 



                                       
                                        
 
                                             
                                                            
                                                                  
                                                            
                                                   








                                                                    

                                                                    
 
                                       
                                                   
                                                      
                                                   
                                           
                                          


                                          



                                                   

                                                  

                                                   
 
                                                                       
                                                                       

                                                            



                                                                 
                                                                         
                                                                           

                                                              


                                                                     
 
                                                                        
                                                                     

                                               



                                      
                                                      

                  
                                                      

                  
                                                       



                                                   
                                                                         
                                                                           

                                                



                                       
                                                       

                  
                                                          

                  
                                                        

                  
                                                       



                                                     



                               
                                  
                               
                       

                      


                      





                               


                              


                               









                           
                                                

                                                          





                                                                           
 
            
                                  


                                                 





                                                         


                                                                             



                                               

                

                                                                     

         



                                                      
                                                        
     
                                                                         

                                                                           

                                                                  
     
 

                                      



                                                              

                                                                    
                                                     
                                                
                                                               


                                                  

                                                                         

















                                              

                          


                                                             


                                                                   
                                     
                                                   
                                                     
 




                                                                                

                                                                  
                                                                        
                                                                  
                                                         



                                                      
                                                       
 







                                                                                        
 


                                                                             

                                                                                   




                                                     
                             
                               
                                 

                                                                                

                                                                              




                                                


                                                              
                                             

                                       
                                                             
     



                                                                

                                                                                             
     




                                                             



                                                                          

                                            


                                                     
                                               
     
                                            

                                           
                                                   
     
                                                        


                                                   
                                                     
     
                                                          


                                                     
                                                    
     
                                                         


                    
                                                          

                      
                                                          

                      
                                                           



                                              





                                                          
                                                           

                      
                                                              

                      
                                                            

                      
                                                           




                                                        
                                                 
     
                                       
         
                                                











                                           
                                                  

                                                    
 

















                                           

                                                                                
 
/*
 *  The Mana World
 *  Copyright 2004 The Mana World Development Team
 *
 *  This file is part of The Mana World.
 *
 *  The Mana World 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
 *  any later version.
 *
 *  The Mana World 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 The Mana World; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <SDL.h>
#include <string>
#include <vector>

#include <guichan/key.hpp>
#include <guichan/listmodel.hpp>

#include <guichan/widgets/label.hpp>

#include "checkbox.h"
#include "listbox.h"
#include "ok_dialog.h"
#include "scrollarea.h"
#include "setup_video.h"
#include "slider.h"
#include "textfield.h"

#include "../configuration.h"
#include "../graphics.h"
#include "../localplayer.h"
#include "../log.h"
#include "../main.h"
#include "../particle.h"

#include "../utils/gettext.h"
#include "../utils/tostring.h"

extern Graphics *graphics;

/**
 * The list model for mode list.
 *
 * \ingroup Interface
 */
class ModeListModel : public gcn::ListModel
{
    public:
        /**
         * Constructor.
         */
        ModeListModel();

        /**
         * Destructor.
         */
        virtual ~ModeListModel() { }

        /**
         * Returns the number of elements in container.
         */
        int getNumberOfElements() { return mVideoModes.size(); }

        /**
         * Returns element from container.
         */
        std::string getElementAt(int i) { return mVideoModes[i]; }

    private:
        std::vector<std::string> mVideoModes;
};

ModeListModel::ModeListModel()
{
    /* Get available fullscreen/hardware modes */
    SDL_Rect **modes = SDL_ListModes(NULL, SDL_FULLSCREEN | SDL_HWSURFACE);

    /* Check which modes are available */
    if (modes == (SDL_Rect **)0) {
        logger->log(_("No modes available"));
    } else if (modes == (SDL_Rect **)-1) {
        logger->log(_("All resolutions available"));
    } else {
        //logger->log("Available Modes");
        for (int i = 0; modes[i]; ++i) {
            const std::string modeString =
                toString((int)modes[i]->w) + "x" + toString((int)modes[i]->h);
            //logger->log(modeString.c_str());
            mVideoModes.push_back(modeString);
        }
    }
}

Setup_Video::Setup_Video():
    mFullScreenEnabled(config.getValue("screen", 0)),
    mOpenGLEnabled(config.getValue("opengl", 0)),
    mCustomCursorEnabled(config.getValue("customcursor", 1)),
    mParticleEffectsEnabled(config.getValue("particleeffects", 1)),
    mSpeechBubbleEnabled(config.getValue("speechbubble", 1)),
    mNameEnabled(config.getValue("showownname", 0)),
    mOpacity(config.getValue("guialpha", 0.8)),
    mFps((int) config.getValue("fpslimit", 0)),
    mModeListModel(new ModeListModel),
    mModeList(new ListBox(mModeListModel)),
    mFsCheckBox(new CheckBox(_("Full screen"), mFullScreenEnabled)),
    mOpenGLCheckBox(new CheckBox(_("OpenGL"), mOpenGLEnabled)),
    mCustomCursorCheckBox(new CheckBox(_("Custom cursor"), mCustomCursorEnabled)),
    mParticleEffectsCheckBox(new CheckBox(_("Particle effects"), mParticleEffectsEnabled)),
    mSpeechBubbleCheckBox(new CheckBox(_("Speech bubbles"), mSpeechBubbleEnabled)),
    mNameCheckBox(new CheckBox(_("Show name"), mNameEnabled)),
    mAlphaSlider(new Slider(0.2, 1.0)),
    mFpsCheckBox(new CheckBox(_("FPS Limit:"))),
    mFpsSlider(new Slider(10, 200)),
    mFpsField(new TextField),
    mOriginalScrollLaziness((int) config.getValue("ScrollLaziness", 16)),
    mScrollLazinessSlider(new Slider(1, 64)),
    mScrollLazinessField(new TextField),
    mOriginalScrollRadius((int) config.getValue("ScrollRadius", 0)),
    mScrollRadiusSlider(new Slider(0, 128)),
    mScrollRadiusField(new TextField),
    mOverlayDetail((int) config.getValue("OverlayDetail", 2)),
    mOverlayDetailSlider(new Slider(0, 2)),
    mOverlayDetailField(new gcn::Label("")),
    mParticleDetail(3 - (int) config.getValue("particleEmitterSkip", 1)),
    mParticleDetailSlider(new Slider(0, 3)),
    mParticleDetailField(new gcn::Label(""))
{
    setOpaque(false);
    setDimension(gcn::Rectangle(0, 0, 290, 255));

    ScrollArea *scrollArea = new ScrollArea(mModeList);
    gcn::Label *alphaLabel = new gcn::Label(_("Gui opacity"));

    mModeList->setEnabled(true);
#ifndef USE_OPENGL
    mOpenGLCheckBox->setEnabled(false);
#endif

    mModeList->setDimension(gcn::Rectangle(0, 0, 60, 70));
    scrollArea->setDimension(gcn::Rectangle(10, 10, 90, 70));
    mFsCheckBox->setPosition(110, 10);
    mNameCheckBox->setPosition(195, 10);
    mOpenGLCheckBox->setPosition(110, 30);
    mParticleEffectsCheckBox->setPosition(180, 30);
    mCustomCursorCheckBox->setPosition(110, 50);
    mSpeechBubbleCheckBox->setPosition(110, 70);
    mAlphaSlider->setDimension(gcn::Rectangle(10, 100, 75, 10));
    alphaLabel->setPosition(20 + mAlphaSlider->getWidth(),
                            mAlphaSlider->getY());
    mFpsCheckBox->setPosition(90, 120);
    mFpsSlider->setDimension(gcn::Rectangle(10, 120, 75, 10));
    mFpsField->setPosition(100 + mFpsCheckBox->getWidth(), 100);
    mFpsField->setWidth(30);

    mModeList->setSelected(-1);
    mAlphaSlider->setValue(mOpacity);

    mFpsField->setText(toString(mFps));
    mFpsField->setEnabled(mFps > 0);
    mFpsSlider->setValue(mFps);
    mFpsSlider->setEnabled(mFps > 0);
    mFpsCheckBox->setSelected(mFps > 0);

    mModeList->setActionEventId("videomode");
    mCustomCursorCheckBox->setActionEventId("customcursor");
    mParticleEffectsCheckBox->setActionEventId("particleeffects");
    mSpeechBubbleCheckBox->setActionEventId("speechbubble");
    mNameCheckBox->setActionEventId("showownname");
    mAlphaSlider->setActionEventId("guialpha");
    mFpsCheckBox->setActionEventId("fpslimitcheckbox");
    mFpsSlider->setActionEventId("fpslimitslider");
    mScrollRadiusSlider->setActionEventId("scrollradiusslider");
    mScrollRadiusField->setActionEventId("scrollradiusfield");
    mScrollLazinessSlider->setActionEventId("scrolllazinessslider");
    mScrollLazinessField->setActionEventId("scrolllazinessfield");
    mOverlayDetailSlider->setActionEventId("overlaydetailslider");
    mOverlayDetailField->setActionEventId("overlaydetailfield");
    mParticleDetailSlider->setActionEventId("particledetailslider");
    mParticleDetailField->setActionEventId("particledetailfield");

    mModeList->addActionListener(this);
    mCustomCursorCheckBox->addActionListener(this);
    mParticleEffectsCheckBox->addActionListener(this);
    mSpeechBubbleCheckBox->addActionListener(this);
    mNameCheckBox->addActionListener(this);
    mAlphaSlider->addActionListener(this);
    mFpsCheckBox->addActionListener(this);
    mFpsSlider->addActionListener(this);
    mFpsField->addKeyListener(this);
    mScrollRadiusSlider->addActionListener(this);
    mScrollRadiusField->addKeyListener(this);
    mScrollLazinessSlider->addActionListener(this);
    mScrollLazinessField->addKeyListener(this);
    mOverlayDetailSlider->addActionListener(this);
    mOverlayDetailField->addKeyListener(this);
    mParticleDetailSlider->addActionListener(this);
    mParticleDetailField->addKeyListener(this);

    mScrollRadiusSlider->setDimension(gcn::Rectangle(10, 140, 75, 10));
    gcn::Label *scrollRadiusLabel = new gcn::Label(_("Scroll radius"));
    scrollRadiusLabel->setPosition(90, 140);
    mScrollRadiusField->setPosition(mFpsField->getX(), 140);
    mScrollRadiusField->setWidth(30);
    mScrollRadiusField->setText(toString(mOriginalScrollRadius));
    mScrollRadiusSlider->setValue(mOriginalScrollRadius);

    mScrollLazinessSlider->setDimension(gcn::Rectangle(10, 160, 75, 10));
    gcn::Label *scrollLazinessLabel = new gcn::Label(_("Scroll laziness"));
    scrollLazinessLabel->setPosition(90, 160);
    mScrollLazinessField->setPosition(mFpsField->getX(), 160);
    mScrollLazinessField->setWidth(30);
    mScrollLazinessField->setText(toString(mOriginalScrollLaziness));
    mScrollLazinessSlider->setValue(mOriginalScrollLaziness);

    mOverlayDetailSlider->setDimension(gcn::Rectangle(10, 180, 75, 10));
    gcn::Label *overlayDetailLabel = new gcn::Label(_("Ambient FX"));
    overlayDetailLabel->setPosition(90, 180);
    mOverlayDetailField->setPosition(180, 180);
    mOverlayDetailField->setWidth(30);
    switch (mOverlayDetail)
    {
        case 0:
            mOverlayDetailField->setCaption(_("off"));
            break;
        case 1:
            mOverlayDetailField->setCaption(_("low"));
            break;
        case 2:
            mOverlayDetailField->setCaption(_("high"));
            break;
    }
    mOverlayDetailSlider->setValue(mOverlayDetail);

    mParticleDetailSlider->setDimension(gcn::Rectangle(10, 200, 75, 10));
    gcn::Label *particleDetailLabel = new gcn::Label(_("Particle Detail"));
    particleDetailLabel->setPosition(90, 200);
    mParticleDetailField->setPosition(180, 200);
    mParticleDetailField->setWidth(60);
    switch (mParticleDetail)
    {
        case 0:
            mParticleDetailField->setCaption(_("low"));
            break;
        case 1:
            mParticleDetailField->setCaption(_("medium"));
            break;
        case 2:
            mParticleDetailField->setCaption(_("high"));
            break;
        case 3:
            mParticleDetailField->setCaption(_("max"));
            break;
    }
    mParticleDetailSlider->setValue(mParticleDetail);

    add(scrollArea);
    add(mFsCheckBox);
    add(mOpenGLCheckBox);
    add(mCustomCursorCheckBox);
    add(mParticleEffectsCheckBox);
    add(mSpeechBubbleCheckBox);
    add(mNameCheckBox);
    add(mAlphaSlider);
    add(alphaLabel);
    add(mFpsCheckBox);
    add(mFpsSlider);
    add(mFpsField);
    add(mScrollRadiusSlider);
    add(scrollRadiusLabel);
    add(mScrollRadiusField);
    add(mScrollLazinessSlider);
    add(scrollLazinessLabel);
    add(mScrollLazinessField);
    add(mOverlayDetailSlider);
    add(overlayDetailLabel);
    add(mOverlayDetailField);
    add(mParticleDetailSlider);
    add(particleDetailLabel);
    add(mParticleDetailField);
}

Setup_Video::~Setup_Video()
{
    delete mModeListModel;
}

void Setup_Video::apply()
{
    // Full screen changes
    bool fullscreen = mFsCheckBox->isSelected();
    if (fullscreen != (config.getValue("screen", 0) == 1))
    {
        /* The OpenGL test is only necessary on Windows, since switching
         * to/from full screen works fine on Linux. On Windows we'd have to
         * reinitialize the OpenGL state and reload all textures.
         *
         * See http://libsdl.org/cgi/docwiki.cgi/SDL_SetVideoMode
         */

#ifdef WIN32
        // checks for opengl usage
        if (!(config.getValue("opengl", 0) == 1))
        {
#endif
            if (!graphics->setFullscreen(fullscreen))
            {
                fullscreen = !fullscreen;
                if (!graphics->setFullscreen(fullscreen))
                {
                    std::stringstream error;
                    error << _("Failed to switch to ") <<
                        (fullscreen ? _("windowed") : _("fullscreen")) <<
                        _("mode and restoration of old mode also failed!") <<
                        std::endl;
                    logger->error(error.str());
                }
            }
#ifdef WIN32
        } else {
            new OkDialog(_("Switching to full screen"),
                    _("Restart needed for changes to take effect."));
        }
#endif
        config.setValue("screen", fullscreen ? 1 : 0);
    }

    // OpenGL change
    if (mOpenGLCheckBox->isSelected() != mOpenGLEnabled)
    {
        config.setValue("opengl", mOpenGLCheckBox->isSelected() ? 1 : 0);

        // OpenGL can currently only be changed by restarting, notify user.
        new OkDialog(_("Changing OpenGL"),
                _("Applying change to OpenGL requires restart."));
    }

    // FPS change
    config.setValue("fpslimit", mFps);

    // We sync old and new values at apply time
    mFullScreenEnabled = config.getValue("screen", 0);
    mCustomCursorEnabled = config.getValue("customcursor", 1);
    mParticleEffectsEnabled = config.getValue("particleeffects", 1);
    mSpeechBubbleEnabled = config.getValue("speechbubble", 1);
    mNameEnabled = config.getValue("showownname", 0);
    mOpacity = config.getValue("guialpha", 0.8);
    mOverlayDetail = (int) config.getValue("OverlayDetail", 2);
    mOpenGLEnabled = config.getValue("opengl", 0);
}

int Setup_Video::updateSlider(gcn::Slider *slider, gcn::TextField *field,
                              const std::string &configName)
{
    int value;
    std::stringstream temp(field->getText());
    temp >> value;
    if (value < slider->getScaleStart())
    {
        value = (int) slider->getScaleStart();
    }
    else if (value > slider->getScaleEnd())
    {
        value = (int) slider->getScaleEnd();
    }
    field->setText(toString(value));
    slider->setValue(value);
    config.setValue(configName, value);
    return value;
}

void Setup_Video::cancel()
{
    mFsCheckBox->setSelected(mFullScreenEnabled);
    mOpenGLCheckBox->setSelected(mOpenGLEnabled);
    mCustomCursorCheckBox->setSelected(mCustomCursorEnabled);
    mParticleEffectsCheckBox->setSelected(mParticleEffectsEnabled);
    mSpeechBubbleCheckBox->setSelected(mSpeechBubbleEnabled);
    mNameCheckBox->setSelected(mNameEnabled);
    mAlphaSlider->setValue(mOpacity);
    mOverlayDetailSlider->setValue(mOverlayDetail);
    mParticleDetailSlider->setValue(mParticleDetail);

    mScrollRadiusField->setText(toString(mOriginalScrollRadius));
    mScrollLazinessField->setText(toString(mOriginalScrollLaziness));
    updateSlider(mScrollRadiusSlider, mScrollRadiusField, "ScrollRadius");
    updateSlider(mScrollLazinessSlider, mScrollLazinessField, "ScrollLaziness");

    config.setValue("screen", mFullScreenEnabled ? 1 : 0);
    config.setValue("customcursor", mCustomCursorEnabled ? 1 : 0);
    config.setValue("particleeffects", mParticleEffectsEnabled ? 1 : 0);
    config.setValue("speechbubble", mSpeechBubbleEnabled ? 1 : 0);
    config.setValue("showownname", mNameEnabled ? 1 : 0);
    config.setValue("guialpha", mOpacity);
    config.setValue("opengl", mOpenGLEnabled ? 1 : 0);
}

void Setup_Video::action(const gcn::ActionEvent &event)
{
    if (event.getId() == "videomode")
    {
        const std::string mode = mModeListModel->getElementAt(mModeList->getSelected());
        const int width = atoi(mode.substr(0, mode.find("x")).c_str());
        const int height = atoi(mode.substr(mode.find("x") + 1).c_str());
        const int bpp = 0;
        const bool fullscreen = ((int) config.getValue("screen", 0) == 1);
        const bool hwaccel = ((int) config.getValue("hwaccel", 0) == 1);

        // Try to set the desired video mode
        if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel))
        {
            std::cerr << _("Couldn't set ")
                      << width << "x" << height << "x" << bpp << _(" video mode: ")
                      << SDL_GetError() << std::endl;
            exit(1);
        }

        // Initialize for drawing
        graphics->_endDraw();
        graphics->_beginDraw();
        graphics->updateScreen();

        // TODO: Find out why the drawing area doesn't resize without a restart.
        new OkDialog(_("Screen resolution changed"),
                     _("Restart your client for the change to take effect."));

        config.setValue("screenwidth", width);
        config.setValue("screenheight", height);
    }
    else if (event.getId() == "guialpha")
    {
        config.setValue("guialpha", mAlphaSlider->getValue());
    }
    else if (event.getId() == "customcursor")
    {
        config.setValue("customcursor",
                mCustomCursorCheckBox->isSelected() ? 1 : 0);
    }
    else if (event.getId() == "particleeffects")
    {
        config.setValue("particleeffects",
                mParticleEffectsCheckBox->isSelected() ? 1 : 0);
        new OkDialog(_("Particle effect settings changed"),
                     _("Restart your client or change maps for the change to take effect."));
    }
    else if (event.getId() == "speechbubble")
    {
        config.setValue("speechbubble",
                mSpeechBubbleCheckBox->isSelected() ? 1 : 0);
    }
    else if (event.getId() == "showownname")
    {
        // Notify the local player that settings have changed for the name
        // and requires an update
        if (player_node)
            player_node->mUpdateName = true;
        config.setValue("showownname",
                mNameCheckBox->isSelected() ? 1 : 0);
    }
    else if (event.getId() == "fpslimitslider")
    {
        mFps = (int) mFpsSlider->getValue();
        mFpsField->setText(toString(mFps));
    }
    else if (event.getId() == "scrollradiusslider")
    {
        int val = (int) mScrollRadiusSlider->getValue();
        mScrollRadiusField->setText(toString(val));
        config.setValue("ScrollRadius", val);
    }
    else if (event.getId() == "scrolllazinessslider")
    {
        int val = (int) mScrollLazinessSlider->getValue();
        mScrollLazinessField->setText(toString(val));
        config.setValue("ScrollLaziness", val);
    }
    else if (event.getId() == "overlaydetailslider")
    {
        int val = (int) mOverlayDetailSlider->getValue();
        switch (val)
        {
            case 0:
                mOverlayDetailField->setCaption(_("off"));
                break;
            case 1:
                mOverlayDetailField->setCaption(_("low"));
                break;
            case 2:
                mOverlayDetailField->setCaption(_("high"));
                break;
        }
        config.setValue("OverlayDetail", val);
    }
    else if (event.getId() == "particledetailslider")
    {
        int val = (int) mParticleDetailSlider->getValue();
        switch (val)
        {
            case 0:
                mParticleDetailField->setCaption(_("low"));
                break;
            case 1:
                mParticleDetailField->setCaption(_("medium"));
                break;
            case 2:
                mParticleDetailField->setCaption(_("high"));
                break;
            case 3:
                mParticleDetailField->setCaption(_("max"));
                break;
        }
        config.setValue("particleEmitterSkip", 3 - val);
        Particle::emitterSkip = 4 - val;
    }
    else if (event.getId() == "fpslimitcheckbox")
    {
        if (mFpsCheckBox->isSelected())
        {
            mFps = (int) mFpsSlider->getValue();
        }
        else
        {
            mFps = 0;
        }
        mFpsField->setEnabled(mFps > 0);
        mFpsField->setText(toString(mFps));
        mFpsSlider->setValue(mFps);
        mFpsSlider->setEnabled(mFps > 0);
    }
}

void Setup_Video::keyPressed(gcn::KeyEvent &event)
{
    std::stringstream tempFps(mFpsField->getText());

    if (tempFps >> mFps)
    {
        if (mFps < 10)
        {
            mFps = 10;
        }
        else if (mFps > 200)
        {
            mFps = 200;
        }
        mFpsField->setText(toString(mFps));
        mFpsSlider->setValue(mFps);
    }
    else
    {
        mFpsField->setText("");
        mFps = 0;
    }
    updateSlider(mScrollRadiusSlider, mScrollRadiusField, "ScrollRadius");
    updateSlider(mScrollLazinessSlider, mScrollLazinessField, "ScrollLaziness");
}