summaryrefslogblamecommitdiff
path: root/src/touchmanager.cpp
blob: af90c65e38087f2826de16ad97ef225f6a72f7ac (plain) (tree)




















                                                                         
                          
                     
                             
                       






                          
                      
                              
                  
                     
                                   


                         
                     
 
                                          
                            


                             
                                 
            
                        


                         
                                                   
                                                   

                                                              


                                                             
 
              
                                                                          

                                                  


                      
 
                                                                    
                                                                               


                                                                           

                                     



                                                              
             
                                       
                  


                                             
                                               

                          
                                                              
                           
                                                                  



                            
                                                      
                                                   
                                                        
                                      

                            
                   


                          

                                     

                                                                             
                    
                     
                   


                         
                        
     







                                                            
                                                                           
                 
                                                                         










                                                        
                                                                       


                                                              
         

     
                                                             
 
                                         



                                                                             
                                                     

                                                
         

                                                    
                              

                                         
             








                                                  

                        


                                      

                 





                                                        


































                                                                 




































                                                                            
                                                          



                                                





















                                                                           






























                                                                       






















                                                                      
 




                                    
/*
 *  The ManaPlus Client
 *  Copyright (C) 2012  The ManaPlus Developers
 *
 *  This file is part of The ManaPlus Client.
 *
 *  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
 *  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.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "touchmanager.h"

#include "configuration.h"
#include "graphics.h"
#include "graphicsvertexes.h"
#include "mouseinput.h"
#include "touchactions.h"

#include "gui/theme.h"

#include "debug.h"

TouchManager touchManager;

extern int openGLMode;

TouchManager::TouchManager() :
    mKeyboard(nullptr),
    mPad(nullptr),
    mAttack(nullptr),
    mVertexes(new ImageCollection),
    mRedraw(true),
    mShowJoystick(false),
    mShowButtons(false),
    mButtonsSize(1),
    mJoystickSize(1),
    mInGame(false)
{
    for (int f = 0; f < actionsSize; f ++)
        mActions[f] = false;
}

TouchManager::~TouchManager()
{
    config.removeListeners(this);
    clear();
    delete mVertexes;
    mVertexes = nullptr;
}

void TouchManager::init()
{
    config.addListener("showScreenJoystick", this);
    config.addListener("showScreenButtons", this);
    config.addListener("screenButtonsSize", this);
    config.addListener("screenJoystickSize", this);

    mShowJoystick = config.getBoolValue("showScreenJoystick");
    mShowButtons = config.getBoolValue("showScreenButtons");
    mButtonsSize = config.getIntValue("screenButtonsSize");
    mJoystickSize = config.getIntValue("screenJoystickSize");

    setHalfJoyPad(getPadSize() / 2);

#ifdef ANDROID
    loadTouchItem(&mKeyboard, "keyboard_icon.xml", -1, -1, 28, 28, NORMAL,
        nullptr, nullptr, &showKeyboard, nullptr);
#endif

    if (mShowJoystick)
        loadPad();
    if (mShowButtons)
        loadButtons();
}

void TouchManager::loadTouchItem(TouchItem **item, std::string name,
                                 int x, int y, int width, int height, int type,
                                 TouchFuncPtr fAll, TouchFuncPtr fPressed,
                                 TouchFuncPtr fReleased, TouchFuncPtr fOut)
{
    *item = nullptr;
    Theme *theme = Theme::instance();
    if (!theme)
        return;
    ImageRect *images = new ImageRect;
    for (int f = 0; f < 9; f ++)
        images->grid[f] = nullptr;

    Skin *const skin = theme->loadSkinRect(*images, name, "");
    if (skin)
    {
        Image *image = images->grid[0];
        if (image)
        {
            if (x == -1)
                x = skin->getOption("x", 10);
            if (y == -1)
                y = skin->getOption("y", 10);
            const int pad = skin->getPadding();
            const int pad2 = 2 * pad;
            switch (type)
            {
                case LEFT:
                    y += (mainGraphics->mHeight - height) / 2;
                    break;
                case RIGHT:
                    x = mainGraphics->mWidth - width - pad2 - x;
                    y = mainGraphics->mHeight - height - pad2 - y;
                    break;
                case NORMAL:
                default:
                    break;
            }
            *item = new TouchItem(gcn::Rectangle(x, y,
                width + pad2, height + pad2), type,
                images, x + pad, y + pad, width, height,
                fAll, fPressed, fReleased, fOut);
            mObjects.push_back(*item);
        }
        theme->unload(skin);
    }
    mRedraw = true;
}

void TouchManager::clear()
{
    Theme *theme = Theme::instance();
    if (!theme)
        return;
    for (TouchItemVectorCIter it = mObjects.begin(), it_end = mObjects.end();
         it != it_end; ++ it)
    {
        unload(*it);
    }
    mObjects.clear();
    mRedraw = true;
}

void TouchManager::draw()
{
    if (openGLMode != 2)
    {
        if (mRedraw)
        {
            mRedraw = false;
            mVertexes->clear();
            for (TouchItemVectorCIter it = mObjects.begin(),
                 it_end = mObjects.end();
                 it != it_end; ++ it)
            {
                const TouchItem *const item = *it;
                if (item && item->images && (mInGame || item == mKeyboard))
                {
                    mainGraphics->calcWindow(mVertexes, item->x, item->y,
                        item->width, item->height, *item->images);
                }
            }
        }
        mainGraphics->drawTile(mVertexes);
    }
    else
    {
        for (TouchItemVectorCIter it = mObjects.begin(),
             it_end = mObjects.end();
             it != it_end; ++ it)
        {
            const TouchItem *const item = *it;
            if (item && item->images && (mInGame || item == mKeyboard))
            {
                mainGraphics->drawImageRect(item->x, item->y,
                    item->width, item->height, *item->images);
            }
        }
    }
}

bool TouchManager::processEvent(const MouseInput &mouseInput)
{
    const int x = mouseInput.getTouchX();
    const int y = mouseInput.getTouchY();

    for (TouchItemVectorCIter it = mObjects.begin(), it_end = mObjects.end();
         it != it_end; ++ it)
    {
        const TouchItem *const item = *it;
        if (!item || (!mInGame && item != mKeyboard))
            continue;
        const gcn::Rectangle &rect = item->rect;
        if (rect.isPointInRect(x, y))
        {
            MouseInput event = mouseInput;
            event.setX(event.getTouchX() - item->x);
            event.setY(event.getTouchY() - item->y);
            if (item->funcAll)
                item->funcAll(event);

            switch (mouseInput.getType())
            {
                case gcn::MouseInput::PRESSED:
                    if (item->funcPressed)
                        item->funcPressed(event);
                    break;
                case gcn::MouseInput::RELEASED:
                    if (item->funcReleased)
                        item->funcReleased(event);
                    break;
                default:
                    break;
            }
            return true;
        }
        else if (item->funcOut)
        {
            item->funcOut(mouseInput);
        }
    }
    return false;
}

bool TouchManager::isActionActive(const int index) const
{
    if (index < 0 || index > actionsSize)
        return false;
    return mActions[index];
}

void TouchManager::resize(int width, int height)
{
    mRedraw = true;
    for (TouchItemVectorCIter it = mObjects.begin(),
         it_end = mObjects.end(); it != it_end; ++ it)
    {
        TouchItem *const item = *it;
        if (!item)
            continue;

        switch (item->type)
        {
            case LEFT:
                if (height != mainGraphics->mHeight)
                {
                    item->y += (height - item->height) / 2;
                    item->rect.y += (height - item->rect.y) / 2;
                }
                break;
            case RIGHT:
            {
                const int diffW = width - mainGraphics->mWidth;
                const int diffH = height - mainGraphics->mHeight;
                item->x += diffW;
                item->rect.x += diffW;
                item->y += diffH;
                item->rect.y += diffH;
                break;
            }
            case NORMAL:
            default:
                break;
        }
    }
}

void TouchManager::unload(TouchItem *item)
{
    if (item)
    {
        Theme *const theme = Theme::instance();
        if (!theme)
            return;
        if (item->images)
        {
            theme->unloadRect(*item->images);
            delete item->images;
            item->images = nullptr;
        }
        delete item;
    }
}

void TouchManager::unloadTouchItem(TouchItem **unloadItem)
{
    Theme *theme = Theme::instance();
    if (!theme)
        return;
    for (TouchItemVectorIter it = mObjects.begin(), it_end = mObjects.end();
         it != it_end; ++ it)
    {
        TouchItem *item = *it;
        if (item && *unloadItem == item)
        {
            mObjects.erase(it);
            unload(item);
            return;
        }
    }
}

void TouchManager::loadPad()
{
    const int sz = (mJoystickSize + 2) * 50;
    loadTouchItem(&mPad, "dpad.xml", -1, -1, sz, sz, LEFT,
        &padEvents, &padClick, &padUp, &padOut);
}

void TouchManager::loadButtons()
{
    const int sz = (mButtonsSize + 1) * 50;
    Theme *theme = Theme::instance();
    if (!theme)
        return;
    Skin *const skin = theme->load("dbutton.xml", "");

    if (skin)
    {
        const int x = skin->getOption("x", 10);
        const int y = skin->getOption("y", 10);
        const int pad = skin->getPadding();
        const int pad2 = 2 * pad;
        const int skipWidth = pad2 + sz + x;

        loadTouchItem(&mAttack, "dbutton.xml", x, y, sz, sz, RIGHT,
            nullptr, &attackClick, nullptr, nullptr);

        loadTouchItem(&mCancel, "dbutton.xml", skipWidth, y, sz, sz, RIGHT,
            nullptr, &cancelClick, nullptr, nullptr);

        theme->unload(skin);
    }

}

void TouchManager::optionChanged(const std::string &value)
{
    logger->log("changed");
    if (value == "showScreenJoystick")
    {
        if (mShowJoystick == config.getBoolValue("showScreenJoystick"))
            return;
        mShowJoystick = config.getBoolValue("showScreenJoystick");
        if (mShowJoystick)
            loadPad();
        else
            unloadTouchItem(&mPad);
        mRedraw = true;
    }
    else if (value == "showScreenButtons")
    {
        if (mShowButtons == config.getBoolValue("showScreenButtons"))
            return;
        mShowButtons = config.getBoolValue("showScreenButtons");
        if (mShowButtons)
        {
            loadButtons();
        }
        else
        {
            unloadTouchItem(&mAttack);
            unloadTouchItem(&mCancel);
        }
        mRedraw = true;
    }
    else if (value == "screenButtonsSize")
    {
        if (mButtonsSize == config.getIntValue("screenButtonsSize"))
            return;
        mButtonsSize = config.getIntValue("screenButtonsSize");
        if (mShowButtons)
        {
            unloadTouchItem(&mAttack);
            unloadTouchItem(&mCancel);
            loadButtons();
        }
    }
    else if (value == "screenJoystickSize")
    {
        if (mJoystickSize == config.getIntValue("screenJoystickSize"))
            return;
        mJoystickSize = config.getIntValue("screenJoystickSize");
        setHalfJoyPad(getPadSize() / 2);
        if (mShowJoystick)
        {
            unloadTouchItem(&mPad);
            loadPad();
        }
    }
}

void TouchManager::setInGame(bool b)
{
    mInGame = b;
    mRedraw = true;
}