1
0
mirror of https://github.com/blupi-games/planetblupi synced 2024-12-30 10:15:36 +01:00
planetblupi/src/button.cpp
Mathieu Schroeter 49289cac8c Redraw everything with each iteration
It prevents glitches with some drivers like Intel. The performances are
not a problem.
2017-02-13 22:07:09 +01:00

400 lines
8.3 KiB
C++

#include <stdlib.h>
#include <stdio.h>
#include "gettext.h"
#include "def.h"
#include "pixmap.h"
#include "sound.h"
#include "decor.h"
#include "button.h"
#include "misc.h"
#include "event.h"
CButton::CButton()
{
m_type = 0;
m_bEnable = true;
m_bHide = false;
m_state = 0;
m_mouseState = 0;
m_nbMenu = 0;
m_nbToolTips = 0;
m_selMenu = 0;
m_bMouseDown = false;
m_message = static_cast<Uint32> (-1);
}
CButton::~CButton () {}
// Crée un nouveau bouton.
bool CButton::Create (CPixmap *pPixmap, CSound *pSound,
POINT pos, Sint32 type,
Sint32 *pMenu, Sint32 nbMenu,
const char **pToolTips,
Sint32 region, Uint32 message)
{
POINT iconDim;
Sint32 i, icon;
static Sint32 ttypes[] =
{
DIMBUTTONX, DIMBUTTONY, // button00.bmp
};
if (type < 0 || type > 0)
return false;
iconDim.x = ttypes[type * 2 + 0];
iconDim.y = ttypes[type * 2 + 1];
m_pPixmap = pPixmap;
m_pSound = pSound;
m_type = type;
m_bEnable = true;
m_bHide = false;
m_message = message;
m_pos = pos;
m_dim = iconDim;
m_nbMenu = nbMenu;
m_selMenu = 0;
m_state = 0;
m_mouseState = 0;
m_bMouseDown = false;
m_nbToolTips = 0;
while (pToolTips[m_nbToolTips])
++m_nbToolTips;
for (i = 0 ; i < nbMenu ; i++)
{
icon = pMenu[i];
if (region == 1) // palmiers ?
{
if (icon == 0)
icon = 90; // sol normal
if (icon == 1)
icon = 91; // sol inflammable
if (icon == 2)
icon = 92; // sol inculte
if (icon == 7)
icon = 9; // plante
if (icon == 8)
icon = 10; // arbre
}
if (region == 2) // hiver ?
{
if (icon == 0)
icon = 96; // sol normal
if (icon == 1)
icon = 97; // sol inflammable
if (icon == 2)
icon = 98; // sol inculte
if (icon == 8)
icon = 99; // arbre
}
if (region == 3) // sapin ?
{
if (icon == 0)
icon = 102; // sol normal
if (icon == 1)
icon = 103; // sol inflammable
if (icon == 2)
icon = 104; // sol inculte
if (icon == 8)
icon = 105; // arbre
}
m_iconMenu[i] = icon;
}
m_toolTips = pToolTips;
return true;
}
// Dessine un bouton dans son état.
void CButton::Draw ()
{
Sint32 i;
POINT pos;
RECT rect;
if (m_bHide) // bouton caché ?
{
rect.left = m_pos.x;
rect.right = m_pos.x + m_dim.x;
rect.top = m_pos.y;
rect.bottom = m_pos.y + m_dim.y;
m_pPixmap->DrawPart (-1, CHBACK, m_pos, rect, 1); // dessine le fond
return;
}
if (m_bEnable) // bouton actif ?
m_pPixmap->DrawIcon (-1, CHBUTTON + m_type, m_mouseState, m_pos);
else
m_pPixmap->DrawIcon (-1, CHBUTTON + m_type, 4, m_pos);
if (m_nbMenu == 0)
return;
pos = m_pos;
if (m_nbMenu > 0)
{
m_pPixmap->DrawIcon (-1, CHBUTTON + m_type,
m_iconMenu[m_selMenu] + 6, pos);
}
if (m_nbMenu == 1 || !m_bEnable || !m_bMouseDown)
return;
pos = m_pos;
pos.x += m_dim.x + 2;
for (i = 0 ; i < m_nbMenu ; i++)
{
m_pPixmap->DrawIcon (-1, CHBUTTON + m_type, i == m_selMenu ? 1 : 0, pos);
m_pPixmap->DrawIcon (-1, CHBUTTON + m_type, m_iconMenu[i] + 6, pos);
pos.x += m_dim.x - 1;
}
}
Sint32 CButton::GetState ()
{
return m_state;
}
void CButton::SetState (Sint32 state)
{
m_state = state;
m_mouseState = state;
}
Sint32 CButton::GetMenu ()
{
return m_selMenu;
}
void CButton::SetMenu (Sint32 menu)
{
m_selMenu = menu;
}
bool CButton::GetEnable ()
{
return m_bEnable;
}
void CButton::SetEnable (bool bEnable)
{
m_bEnable = bEnable;
}
bool CButton::GetHide ()
{
return m_bHide;
}
void CButton::SetHide (bool bHide)
{
m_bHide = bHide;
}
// Traitement d'un événement.
bool CButton::TreatEvent (const SDL_Event &event)
{
POINT pos;
if (m_bHide || !m_bEnable)
return false;
//pos = ConvLongToPos(lParam);
switch (event.type)
{
case SDL_MOUSEBUTTONDOWN:
if (event.button.button != SDL_BUTTON_LEFT
&& event.button.button != SDL_BUTTON_RIGHT)
break;
pos.x = event.button.x;
pos.y = event.button.y;
if (MouseDown (pos))
return true;
break;
case SDL_MOUSEMOTION:
pos.x = event.motion.x;
pos.y = event.motion.y;
if (MouseMove (pos))
return true;
break;
case SDL_MOUSEBUTTONUP:
if (event.button.button != SDL_BUTTON_LEFT
&& event.button.button != SDL_BUTTON_RIGHT)
break;
pos.x = event.button.x;
pos.y = event.button.y;
if (MouseUp (pos))
return false; // (*)
break;
}
return false;
}
// (*) Tous les boutons doivent recevoir l'événement BUTTONUP !
// Indique si la souris est sur ce bouton.
bool CButton::MouseOnButton (POINT pos)
{
return Detect (pos);
}
// Retourne le tooltips pour un bouton, en fonction
// de la position de la souris.
const char *CButton::GetToolTips (POINT pos)
{
Sint32 width = m_dim.x;
Sint32 rank;
if (m_bHide || !m_bEnable)
return nullptr;
if (m_nbMenu > 1 && m_bMouseDown) // sous-menu déroulé ?
width += 2 + (m_dim.x - 1) * m_nbMenu;
if (pos.x < m_pos.x
|| pos.x > m_pos.x + width
|| pos.y < m_pos.y
|| pos.y > m_pos.y + m_dim.y)
return nullptr;
rank = (pos.x - (m_pos.x + 2 + 1)) / (m_dim.x - 1);
if (rank < 0)
rank = 0;
if (rank > m_nbToolTips)
return nullptr;
if (m_nbMenu > 1)
{
if (m_bMouseDown && rank > 0)
rank --;
else
rank = m_selMenu;
}
return gettext (m_toolTips[rank]);
}
// Détecte si la souris est dans le bouton.
bool CButton::Detect (POINT pos)
{
Sint32 width = m_dim.x;
if (m_bHide || !m_bEnable)
return false;
if (m_nbMenu > 1 && m_bMouseDown) // sous-menu déroulé ?
width += 2 + (m_dim.x - 1) * m_nbMenu;
if (pos.x < m_pos.x ||
pos.x > m_pos.x + width ||
pos.y < m_pos.y ||
pos.y > m_pos.y + m_dim.y)
return false;
return true;
}
// Bouton de la souris pressé.
bool CButton::MouseDown (POINT pos)
{
if (!Detect (pos))
return false;
m_mouseState = 1;
m_bMouseDown = true;
CEvent::PushUserEvent (WM_UPDATE);
m_pSound->PlayImage (SOUND_CLICK, pos);
return true;
}
// Souris déplacés.
bool CButton::MouseMove (POINT pos)
{
bool bDetect;
Sint32 iState, iMenu;
iState = m_mouseState;
iMenu = m_selMenu;
bDetect = Detect (pos);
if (m_bMouseDown)
{
if (bDetect)
m_mouseState = 1; // pressé
else
m_mouseState = m_state;
}
else
{
if (bDetect)
m_mouseState = m_state + 2; // survollé
else
m_mouseState = m_state;
}
if (m_nbMenu > 1 &&
m_bMouseDown &&
pos.x > m_pos.x + m_dim.x + 2) // dans sous-menu ?
{
m_selMenu = (pos.x - (m_pos.x + m_dim.x + 2)) / (m_dim.x - 1);
if (m_selMenu >= m_nbMenu)
m_selMenu = m_nbMenu - 1;
}
if (iState != m_mouseState ||
iMenu != m_selMenu)
CEvent::PushUserEvent (WM_UPDATE);
return m_bMouseDown;
}
// Bouton de la souris relâché.
bool CButton::MouseUp (POINT pos)
{
bool bDetect;
bDetect = Detect (pos);
m_mouseState = m_state;
m_bMouseDown = false;
if (!bDetect)
return false;
if (m_message != static_cast<Uint32> (-1))
CEvent::PushUserEvent (m_message);
return true;
}