class pushButton

Acum ceva vreme (3 luni in urma cred…), am scris o clasa pentru butoane in Allegro. O consider invechita si nu tocmai eficienta insa cat de curand voi reveni cu imbunatatiri pentru a fii asa cum mi-am propus.

Ce face ea? Ofera un set de functii pentru a creea butoane cu imagini de care vrem noi pe care sa scrie ce vrem noi pe care le putem click-ui si folosi in jocuri sau programe facute cu Allegro 🙂

Momentan fiecare buton creeat este stocat intr-un array de X elemente, pe care il putem modifica din sursa, acesta fiind si primul lucru care vreau sa-l schimb (mult mai eficienta o lista inlantuita).

Am sa postez aici un “demo”, lasandu-va pe voi sa puneti intrebari daca sunteti interesati 🙂


/******************************************************************************
*** \file    pushButton.h
*** \author  Gilcescu-Ceia Claudiu
*** \brief   pushButton class interface.
***
*** This code provides an easy to use API to work with buttons
***
*** \note This code uses the following libraries:
***   -# Allegro 4.2.2, http://www.talula.demon.co.uk/allegro/
******************************************************************************/

#ifndef PUSHBUTTON_H
#define PUSHBUTTON_H

#include <Allegro.h>
#include "buttonData.h" // The header generated by grabber

/*! \def NORMAL
    \def HOVER
    \def CLICK
         These describe button states
*/
#define NORMAL      0
#define HOVER       1
#define CLICK       2

/*! \def MAX_BUTTONS
         Maximum number of buttons that can be used at the same time
    \todo {Change array of buttons with a linked-list}
*/
#define MAX_BUTTONS 100

/*! \struct buttonMask pushButton.h "engine\video\pushButton.h"
    \brief This contains all the variables needed to work with buttons
*/
typedef struct buttonMask {

    int pos_x, pos_y;
    int size_w, size_h;
    int pos_x2, pos_y2;

    short state;
    short type;
    short userID;

    bool mouse_in;
    bool clicked;
    int previous_mouse_b, delta_mouse_b;

} buttonMask;

/*! \class pushButton pushButton.h "engine\video\pushButton.h"
    \brief An API used to work with normal buttons.
    \todo {Solve the hover/click button issue, mouse input...}
*/
class pushButton {

public:
    pushButton();

    /*! \name setupButtons()
        \brief Loads the datafile and sets buttonIndex to 0
        \return True if successful, false otherwise
    */
    bool setupButtons();

    /*! \name newButton()
        \brief Creates a new button in the property array
        \param ID short
        \return True if successful, false otherwise
    */
    bool newButton(short ID);

    /*! \brief These methods are used to adjust some private values
        \param x integer
        \param y integer
        \param ID short
        \param type short
        \sa buttonMask
    */
    //@{
    void setX(int x, short ID);
    void setY(int y, short ID);
    void setType(short type, short ID);
    void setPosition(int x, int y, short ID);
    //@}

    /*! \name drawButton()
        \brief Overloaded buttons. These are used to draw the button on
               the screen and/or adjust some private members
        \param bmp BITMAP structure
        \param ID short
        \param type short
        \param x integer
        \param y integer
        \param w integer
        \param h integer
        \sa buttonMask
    */
    //@{
    bool drawButton(BITMAP* bmp, short ID, short type, int x, int y, int w, int h);
    bool drawButton(BITMAP* bmp, short ID, int w, int h);
    bool drawButton(BITMAP* bmp, short ID);
    //@}

    /*! \name setText()
        \brief This method draws a custom text on the top of the
               button image
        \note Text position changes according to button state
        \param bmp BITMAP structure
        \param ID short
        \param color makecol(r, g , b)
        \param text[] Character array
        \return True is successful, false otherwise
        \sa buttonMask
    */
    bool setText(BITMAP* bmp, short ID, int color, char text[]);

    /*! \name checkMouseIn()
        \brief Checks if mouse pointer hovers over the button
        \param ID short
        \return True if pointer is over the button, false otherwise
        \sa checkMouseClick()
    */
    bool checkMouseIn(short ID);

    /*! \name checkMouseClick()
        \brief Check if a button was clicked
        \note Calls checkMouseIn()
        \param ID short
        \return True if button was clicked, false otherwise
        \sa checkMouseClick
    */
    bool checkMouseClick(short ID);

    /*! \name freeMemory()
        \brief Frees memory occupied by the datafile
        \return True is successful, false otherwise
    */
    bool freeMemory();

protected:
    /*! \brief These methods are called by the public methods
               to return specific private members
        \param ID short
        \return Private buttonMask arguments
        \sa buttonMask
    */
    //@{
    int getX2(short ID);
    int getY2(short ID);

    /*! \name searchID()
        \brief Used throughout the class implementation
               to check which button is beeing used
        \param ID short
        \return The index of the button array where the
                buttonMask#ID was found
        \sa buttonMask
    */
    short searchID(short ID);

    /*! \brief These methods check the datafile to find out the
               button image real size
        \param type integer
    */
    //@{
    int searchObjectWidth(int type);
    int searchObjectHeight(int type);
    //@}

    int getY(short ID);
    int getX(short ID);

    /*! \brief These methods are used to change private variables
               width and height
        \param w integer
        \param h integer
        \param ID short
        \sa buttonMask
    */
    //@{
    void setW(int w, short ID);
    void setH(int h, short ID);
    //@}

    int getW(short ID);
    int getH(short ID);

    int getState(short ID);
    int getType(short ID);
    //@}
private:
    //! \brief Private class members
    //@{
    DATAFILE* buttonData;
    /*! \brief buttonMask array
        \sa buttonMask
        \sa MAX_BUTTONS
    */
    buttonMask property[MAX_BUTTONS];
    //! This is a counter for how many buttons are used at the time
    short buttonIndex;
    //2}
};

#endif // PUSHBUTTON_H

#include "pushButton.h"

// Init every button with neutral values
pushButton::pushButton() {

    for (int i = 0; i < MAX_BUTTONS; i++) {
        property&#91;i&#93;.clicked = false;

        property&#91;i&#93;.size_h = 0;
        property&#91;i&#93;.size_w = 0;
        property&#91;i&#93;.pos_x = 0;
        property&#91;i&#93;.pos_x = 0;
        property&#91;i&#93;.pos_x2 = 0;
        property&#91;i&#93;.pos_y = 0;
        property&#91;i&#93;.pos_y2 = 0;

        property&#91;i&#93;.mouse_in = false;
        property&#91;i&#93;.state = NORMAL;
        property&#91;i&#93;.previous_mouse_b = 0;
        property&#91;i&#93;.delta_mouse_b = 0;

        property&#91;i&#93;.type = 0;
        property&#91;i&#93;.userID = 0;
    }
    //click = false;
} //pushButton::pushButton()

// Load the datafile made with grabber
bool pushButton::setupButtons() {

    buttonData = load_datafile(&quot;Data\\GUI\\buttons.dat&quot;);
    buttonIndex = 0;
    return true;
}

// Search the array for the button with the sought ID
short pushButton::searchID(short ID) {

    int returnValue = -1;

    for (int i = 0; i  -1) {
        property&#91;index&#93;.pos_x = x;
    }
}

int pushButton::getX(short ID) {

    int index = searchID(ID);

    if (index > -1) {
        return property[index].pos_x;
    } else return -1;

}

void pushButton::setY(int y, short ID) {

    int index = searchID(ID);

    if (index > -1) {
        property[index].pos_y = y;
    }
}

int pushButton::getY(short ID) {

    int index = searchID(ID);

    if (index > -1) {
        return property[index].pos_y;
    } else return -1;
}

void pushButton::setW(int w, short ID) {

    int index = searchID(ID);

    if (index > -1) {
        property[index].size_w = w;
    }
}

int pushButton::getW(short ID) {

    int index = searchID(ID);

    if (index > -1) {
        return property[index].size_w;
    } else return -1;
}

void pushButton::setH(int h, short ID) {

    int index = searchID(ID);

    if (index > -1) {
        property[index].size_h = h;
    }
}

int pushButton::getH(short ID) {

    int index = searchID(ID);

    if (index > -1) {
        return property[index].size_h;
    } else return -1;
}

int pushButton::getX2(short ID) {

    int index = searchID(ID);

    if (index > -1) {
        return (property[index].pos_x + getW(ID));
    } else return -1;
}

int pushButton::getY2(short ID) {

    int index = searchID(ID);

    if (index > -1) {
        return (property[index].pos_y + getH(ID));
    } else return -1;
}

int pushButton::getState(short ID) {

    int index = searchID(ID);

    if (index > -1) {
        return property[index].state;
    } else return -1;
}

// Both searchObjectWidth() and searchObjectHeight()
// look for the desired values in the datafile that supplies the button images
int pushButton::searchObjectWidth(int type) {

    const char *returnValue = (get_datafile_property(buttonData + type, DAT_ID('X','S','I','Z')));
    if (returnValue != empty_string)
        return atoi(returnValue);
    return -1;
}

int pushButton::searchObjectHeight(int type) {

    const char *returnValue = (get_datafile_property(buttonData + type, DAT_ID('Y','S','I','Z')));
    if (returnValue != empty_string)
        return atoi(returnValue);
    return -1;
}

void pushButton::setType(short type, short ID) {

    int index = searchID(ID);

    if (index > -1) {
        property[index].type = type;

        property[index].size_w = searchObjectWidth(type);
        property[index].size_h = searchObjectHeight(type);

        property[index].pos_x2 = getX(ID) + getW(ID);
        property[index].pos_y2 = getY(ID) + getH(ID);
    }
}

int pushButton::getType(short ID) {

    int index = searchID(ID);

    if (index > -1) {
        return property[index].type;
    } else return -1;
}

void pushButton::setPosition(int x, int y, short ID) {

    int index = searchID(ID);

    if (index > -1) {
        property[index].pos_x = x;
        property[index].pos_x2 = x + getW(ID);
        property[index].pos_y = y;
        property[index].pos_y2 = y + getH(ID);
    }
}

// Three methods for drawing a button, two of them change the properties
// of the drawn button as well. Overloaded
bool pushButton::drawButton(BITMAP* bmp, short ID, short type, int x, int y, int w, int h) {

    int index = searchID(ID);

    if (index > -1) {
        if ((w < 1) || (h  0) && (h > 0)) {
        stretch_blit((BITMAP*)buttonData[type + getState(ID)].dat, bmp, 0, 0, getW(ID), getH(ID), x, y, w, h);

        setX(x, ID);
        setY(y, ID);
        setType(type, ID);
        setW(w, ID);
        setH(h, ID);
    }
    return true;
} //bool pushButton::drawButton(BITMAP* bmp, short ID, short type, int x, int y, int w, int h)

bool pushButton::drawButton(BITMAP* bmp, short ID, int w, int h) {

    int index = searchID(ID);

    if (index > -1) {
        if ((w < 1) || (h  0) && (h > 0)) {
            stretch_blit((BITMAP*)buttonData[getType(ID) + getState(ID)].dat, bmp, 0, 0,
                         searchObjectWidth(getType(ID)), searchObjectHeight(getType(ID)), getX(ID), getY(ID), w, h);
            setW(w, ID);
            setH(h, ID);
        }
    }

    return true;
} //bool pushButton::drawButton(BITMAP* bmp, short ID, int w, int h)

bool pushButton::drawButton(BITMAP* bmp, short ID) {

    int index = searchID(ID);

    if (index > -1) {
        blit((BITMAP*)buttonData[getType(ID) + getState(ID)].dat, bmp, 0, 0, getX(ID), getY(ID), getW(ID), getH(ID));
    }

    return true;
} //bool pushButton::drawButton(BITMAP* bmp, short ID)

// If your image doesn't have text on, this function uses the default Allegro font
// and custom text and color to be displayed
bool pushButton::setText(BITMAP* bmp, short ID, int color, char text[]) {

    checkMouseClick(ID);
    int index = searchID(ID);

    if (index > -1) {
        switch (getState(ID)) {
        case NORMAL:
        case HOVER: {
            textprintf_centre_ex(bmp, font, getX(ID) + getW(ID)/2, getY(ID) + getH(ID)/2-2,
                                 color, -1, text);
            break;
        }
        case CLICK: {
            textprintf_centre_ex(bmp, font, getX(ID) + getW(ID)/2 + 1, getY(ID) + getH(ID)/2 - 4,
                                 color, -1, text);
            break;
        }
        }
    }

    return true;
} //bool pushButton::setText(BITMAP* bmp, short ID, int color, char text[])

// Checks if mouse is on button
bool pushButton::checkMouseIn(short ID) {
    int index = searchID(ID);

    if (index > -1) {
        property[index].previous_mouse_b = mouse_b;

        if ((mouse_x > getX(ID)) && (mouse_y > getY(ID)) &&
                mouse_x < getX2(ID) && (mouse_y  -1) {
        property&#91;index&#93;.delta_mouse_b = mouse_b ^ property&#91;index&#93;.previous_mouse_b;

        if (checkMouseIn(ID) && (property&#91;index&#93;.delta_mouse_b & 1)) {
            if (mouse_b & 1) {
                property&#91;index&#93;.clicked = true;
                property&#91;index&#93;.state = CLICK;
                return true;
            }
        } else {
            property&#91;index&#93;.clicked = false;
            property&#91;index&#93;.state = HOVER;
            return false;
        }
    } else {
        property&#91;index&#93;.clicked = false;
        property&#91;index&#93;.state = NORMAL;
        return false;
    }
    return property&#91;index&#93;.clicked;
} //bool pushButton::checkMouseClick(short ID)

// Simply release the memory
bool pushButton::freeMemory() {
    unload_datafile(buttonData);
    return true;
}
&#91;/sourcecode&#93;

<hr />
#include "pushButton.h"

#define TEST 0

BITMAP* buffer; // Used for the backbuffer
pushButton button;
int init();

int main(void) {
    init();

    button.setupButtons();
    button.newButton(TEST);
    button.setType(BIG_RED, TEST);
    button.setPosition(10, 10, TEST);

    // Main loop
    while (!key[KEY_ESC]) {

    button.drawButton(buffer, TEST);
    blit(buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
    vsync();

    }
    button.freeMemory();
    destroy_bitmap(buffer);
    return 0;

}
END_OF_MAIN();

int init() {
    allegro_init();         // Initialize allegro.
    install_keyboard();     // Enable keyboard.
    install_mouse();        // Enable mouse.

    // Create a 800x600 non-fullscreen window.
    set_color_depth(32);
    set_gfx_mode(GFX_AUTODETECT_WINDOWED, 800, 600, 0, 0);
    // Backbuffer
    buffer = create_bitmap( 800, 600);

    return 0;
}

Scuze pentru postul prea lung, daca vreti codul uploadat undeva va rog sa ma anuntati si revin cu un link spre un site de download.

O zi buna 😉

Advertisements

About this entry