mirror of
https://github.com/blupi-games/planetblupi
synced 2024-12-30 10:15:36 +01:00
509 lines
12 KiB
C++
509 lines
12 KiB
C++
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include "blupi.h"
|
|
#include "def.h"
|
|
#include "resource.h"
|
|
#include "pixmap.h"
|
|
#include "sound.h"
|
|
#include "decor.h"
|
|
#include "button.h"
|
|
#include "menu.h"
|
|
#include "text.h"
|
|
#include "misc.h"
|
|
#include "event.h"
|
|
#include "gettext.h"
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#define MARGMENU 0
|
|
|
|
|
|
static const Sint16 table_button_icon[] =
|
|
{
|
|
24, // go
|
|
40, // stop
|
|
32, // mange
|
|
30, // carry
|
|
31, // depose
|
|
22, // abat
|
|
27, // roc
|
|
28, // cultive
|
|
19, // build1 (cabane)
|
|
25, // build2 (couveuse)
|
|
35, // build3 (laboratoire)
|
|
61, // build4 (mine)
|
|
59, // build5 (usine)
|
|
101, // build6 (téléporteur)
|
|
20, // mur
|
|
26, // palis
|
|
42, // abat n
|
|
43, // roc n
|
|
23, // pont
|
|
33, // tour
|
|
34, // boit
|
|
39, // labo
|
|
54, // fleur
|
|
55, // fleur n
|
|
41, // dynamite
|
|
58, // bateau
|
|
60, // djeep
|
|
64, // drapeau
|
|
62, // extrait du fer
|
|
65, // fabrique jeep
|
|
63, // fabrique mine
|
|
83, // fabrique disciple
|
|
100, // repeat
|
|
107, // qarmure
|
|
106, // fabarmure
|
|
};
|
|
|
|
static const char *GetText (Sint32 rank)
|
|
{
|
|
static const char *list[] = {
|
|
translate ("Go"),
|
|
translate ("Stop"),
|
|
translate ("Eat"),
|
|
translate ("Take"),
|
|
translate ("Drop"),
|
|
translate ("Cut down a tree"),
|
|
translate ("Carve a rock"),
|
|
translate ("Grow tomatoes"),
|
|
translate ("Garden shed"),
|
|
translate ("Incubator"),
|
|
translate ("Laboratory"),
|
|
translate ("Mine"),
|
|
translate ("Workshop"),
|
|
translate ("Teleporter"),
|
|
translate ("Wall"),
|
|
translate ("Palisade"),
|
|
translate ("Cut down trees"),
|
|
translate ("Carve rocks"),
|
|
translate ("Bridge"),
|
|
translate ("Protection tower"),
|
|
translate ("Drink"),
|
|
translate ("Transform"),
|
|
translate ("Make bunch of flowers"),
|
|
translate ("Make bunches of flowers"),
|
|
translate ("Blow up"),
|
|
translate ("Boat"),
|
|
translate ("Leave Jeep"),
|
|
translate ("Prospect for iron"),
|
|
translate ("Extract iron"),
|
|
translate ("Make a Jeep"),
|
|
translate ("Make a time bomb"),
|
|
translate ("Make a helper robot"),
|
|
translate ("Repeat"),
|
|
translate ("Quit"),
|
|
translate ("Make armour"),
|
|
};
|
|
|
|
return gettext (list[rank]);
|
|
}
|
|
|
|
static const char *GetErr (Sint32 rank)
|
|
{
|
|
static const char *list[] = {
|
|
translate ("Impossible"),
|
|
translate ("Inadequate ground"),
|
|
translate ("Occupied ground"),
|
|
translate ("Opposite bank no good"),
|
|
translate ("Bridge finished"),
|
|
translate ("(isolated tower)"),
|
|
translate ("Too close to water"),
|
|
translate ("Already two teleporters"),
|
|
};
|
|
|
|
return gettext (list[rank]);
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Constructeur.
|
|
|
|
CMenu::CMenu()
|
|
{
|
|
m_nbButtons = 0;
|
|
m_selRank = -1;
|
|
}
|
|
|
|
// Destructeur.
|
|
|
|
CMenu::~CMenu()
|
|
{
|
|
}
|
|
|
|
|
|
// Crée un nouveau bouton.
|
|
|
|
bool CMenu::Create (CPixmap *pPixmap, CSound *pSound,
|
|
POINT pos, Sint32 nb, Sint32 *pButtons, Sint32 *pErrors,
|
|
std::unordered_map<Sint32, const char *> &texts,
|
|
Sint32 perso)
|
|
{
|
|
pos.x -= DIMBUTTONX / 2;
|
|
pos.y -= DIMBUTTONY / 2;
|
|
|
|
m_pPixmap = pPixmap;
|
|
m_pSound = pSound;
|
|
m_nbButtons = nb;
|
|
m_pos = pos;
|
|
m_perso = perso;
|
|
|
|
Update (nb, pButtons, pErrors, texts);
|
|
|
|
if (m_pos.x < POSDRAWX)
|
|
m_pos.x = POSDRAWX;
|
|
if (m_pos.y < POSDRAWY)
|
|
m_pos.y = POSDRAWY;
|
|
|
|
if (m_pos.x > POSDRAWX + DIMDRAWX - 2 - m_dim.x)
|
|
m_pos.x = POSDRAWX + DIMDRAWX - 2 - m_dim.x;
|
|
if (m_pos.y > POSDRAWY + DIMDRAWY - 2 - m_dim.y)
|
|
m_pos.y = POSDRAWY + DIMDRAWY - 2 - m_dim.y;
|
|
|
|
if (m_pos.x != pos.x || m_pos.y != pos.y)
|
|
{
|
|
pos = m_pos;
|
|
pos.x += DIMBUTTONX / 2;
|
|
pos.y += DIMBUTTONY / 2;
|
|
SDL_WarpMouseInWindow (g_window, pos.x, pos.y);
|
|
}
|
|
|
|
m_selRank = Detect (pos);
|
|
|
|
return true;
|
|
}
|
|
|
|
// Met à jour le menu.
|
|
|
|
void CMenu::Update (Sint32 nb, Sint32 *pButtons, Sint32 *pErrors,
|
|
std::unordered_map<Sint32, const char *> &texts)
|
|
{
|
|
Sint32 i;
|
|
|
|
m_nbButtons = nb;
|
|
|
|
if (nb < 5)
|
|
m_nbCel.x = 1;
|
|
else
|
|
m_nbCel.x = 2;
|
|
|
|
m_nbCel.y = (nb + m_nbCel.x - 1) / m_nbCel.x;
|
|
|
|
m_dim.x = (DIMBUTTONX + MARGMENU) * m_nbCel.x;
|
|
m_dim.y = (DIMBUTTONY + MARGMENU) * m_nbCel.y;
|
|
|
|
for (i = 0 ; i < nb ; i++)
|
|
{
|
|
m_buttons[i] = pButtons[i];
|
|
m_errors[i] = pErrors[i];
|
|
}
|
|
m_texts = texts;
|
|
}
|
|
|
|
// Détruit le menu.
|
|
|
|
void CMenu::Delete()
|
|
{
|
|
m_nbButtons = 0;
|
|
m_selRank = -1;
|
|
}
|
|
|
|
// Dessine un bouton dans son état.
|
|
|
|
void CMenu::Draw()
|
|
{
|
|
Sint32 i, state, icon;
|
|
POINT pos;
|
|
RECT oldClip, clipRect;
|
|
char text[50];
|
|
char *pText;
|
|
|
|
if (m_nbButtons == 0)
|
|
return;
|
|
|
|
oldClip = m_pPixmap->GetClipping();
|
|
clipRect.left = POSDRAWX;
|
|
clipRect.top = POSDRAWY;
|
|
clipRect.right = POSDRAWX + DIMDRAWX;
|
|
clipRect.bottom = POSDRAWY + DIMDRAWY;
|
|
m_pPixmap->SetClipping (clipRect);
|
|
|
|
for (i = 0 ; i < m_nbButtons ; i++)
|
|
{
|
|
pos.x = m_pos.x + ((i / m_nbCel.y) * (DIMBUTTONX + MARGMENU));
|
|
pos.y = m_pos.y + ((i % m_nbCel.y) * (DIMBUTTONY + MARGMENU));
|
|
|
|
if (i == m_selRank)
|
|
state = 2; // hilite
|
|
else
|
|
state = 0; // release
|
|
if (m_errors[i] != 0 &&
|
|
m_errors[i] != ERROR_TOURISOL &&
|
|
m_errors[i] < 100)
|
|
{
|
|
state = 4; // disable
|
|
}
|
|
m_pPixmap->DrawIcon (-1, CHBUTTON, state, pos);
|
|
|
|
icon = table_button_icon[m_buttons[i]];
|
|
if (m_perso == 8) // disciple ?
|
|
{
|
|
if (icon == 30)
|
|
icon = 88; // prend
|
|
if (icon == 31)
|
|
icon = 89; // dépose
|
|
}
|
|
m_pPixmap->DrawIcon (-1, CHBUTTON, icon + 6, pos);
|
|
}
|
|
|
|
// Affiche le texte d'aide.
|
|
if (m_selRank != -1)
|
|
{
|
|
i = m_selRank;
|
|
pos.y = m_pos.y + ((i % m_nbCel.y) * (DIMBUTTONY + MARGMENU));
|
|
|
|
if (m_errors[i] == 0)
|
|
pos.y += (DIMBUTTONY - DIMTEXTY) / 2;
|
|
else
|
|
pos.y += (DIMBUTTONY - DIMTEXTY * 2) / 2;
|
|
|
|
if (m_errors[i] >= 100) // no ressource au lieu erreur ?
|
|
{
|
|
snprintf (text, sizeof (text), m_texts[i]);
|
|
pText = strchr (text, '\n');
|
|
if (pText != nullptr)
|
|
*pText = 0;
|
|
}
|
|
else
|
|
{
|
|
const auto tr = GetText (m_buttons[i]);
|
|
snprintf (text, sizeof (text), tr);
|
|
}
|
|
|
|
if (m_nbCel.x > 1 && i < m_nbCel.y)
|
|
{
|
|
// if ( bLeft )
|
|
// {
|
|
pos.x = m_pos.x - 4 - GetTextWidth (text); // texte à gauche
|
|
// }
|
|
// else
|
|
// {
|
|
// pos.x = m_pos.x+((i/m_nbCel.y)+1)+(DIMBUTTONX+MARGMENU)+4;
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
// if ( bRight )
|
|
// {
|
|
pos.x = m_pos.x + m_dim.x + 4; // texte à droite
|
|
// }
|
|
// else
|
|
// {
|
|
// pos.x = m_pos.x+(i/m_nbCel.y)*(DIMBUTTONX+MARGMENU)-4-GetTextWidth(text);
|
|
// }
|
|
}
|
|
|
|
DrawText (m_pPixmap, pos, text, FONTWHITE);
|
|
|
|
if (m_errors[i] != 0)
|
|
{
|
|
if (m_errors[i] >= 100) // no ressource au lieu erreur ?
|
|
{
|
|
snprintf (text, sizeof (text), m_texts[i]);
|
|
pText = strchr (text, '\n');
|
|
if (pText != nullptr)
|
|
strcpy (text, pText + 1);
|
|
}
|
|
else
|
|
{
|
|
const auto tr = GetErr (m_errors[i] - 1); // impossible ici
|
|
snprintf (text, sizeof (text), tr);
|
|
}
|
|
|
|
if (m_nbCel.x > 1 && i < m_nbCel.y)
|
|
{
|
|
// if ( bLeft )
|
|
// {
|
|
pos.x = m_pos.x - 4 - GetTextWidth (text); // texte à gauche
|
|
// }
|
|
// else
|
|
// {
|
|
// pos.x = m_pos.x+((i/m_nbCel.y)+1)+(DIMBUTTONX+MARGMENU)+4;
|
|
// }
|
|
}
|
|
else
|
|
{
|
|
// if ( bRight )
|
|
// {
|
|
pos.x = m_pos.x + m_dim.x + 4; // texte à droite
|
|
// }
|
|
// else
|
|
// {
|
|
// pos.x = m_pos.x+(i/m_nbCel.y)*(DIMBUTTONX+MARGMENU)-4-GetTextWidth(text);
|
|
// }
|
|
}
|
|
|
|
pos.y += DIMTEXTY;
|
|
if (m_errors[i] >= 100) // no ressource au lieu erreur ?
|
|
DrawText (m_pPixmap, pos, text, FONTWHITE);
|
|
else
|
|
DrawText (m_pPixmap, pos, text, FONTRED);
|
|
}
|
|
}
|
|
|
|
m_pPixmap->SetClipping (oldClip);
|
|
}
|
|
|
|
// Retourne le bouton sélectionné.
|
|
|
|
Sint32 CMenu::GetSel()
|
|
{
|
|
if (m_selRank == -1)
|
|
return -1;
|
|
|
|
return m_buttons[m_selRank];
|
|
}
|
|
|
|
// Retourne le rang sélectionné.
|
|
|
|
Sint32 CMenu::GetRank()
|
|
{
|
|
return m_selRank;
|
|
}
|
|
|
|
// Retourne true si le bouton sélectionné a une erreur.
|
|
|
|
bool CMenu::IsError()
|
|
{
|
|
if (m_selRank == -1)
|
|
return true;
|
|
|
|
if (m_errors[m_selRank] != 0 &&
|
|
m_errors[m_selRank] < 100)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
// Indique si le menu existe.
|
|
|
|
bool CMenu::IsExist()
|
|
{
|
|
return (m_nbButtons == 0) ? false : true;
|
|
}
|
|
|
|
|
|
// Traitement d'un événement.
|
|
|
|
bool CMenu::TreatEvent (const SDL_Event &event)
|
|
{
|
|
POINT pos;
|
|
|
|
if (m_nbButtons == 0)
|
|
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 true;
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Détecte dans quel bouton est la souris.
|
|
|
|
Sint32 CMenu::Detect (POINT pos)
|
|
{
|
|
Sint32 rank;
|
|
|
|
if (pos.x < m_pos.x || pos.x > m_pos.x + m_dim.x ||
|
|
pos.y < m_pos.y || pos.y > m_pos.y + m_dim.y)
|
|
return -1;
|
|
|
|
rank = (pos.y - m_pos.y) / (DIMBUTTONY + MARGMENU);
|
|
rank += ((pos.x - m_pos.x) / (DIMBUTTONX + MARGMENU)) * m_nbCel.y;
|
|
|
|
if (rank >= m_nbButtons)
|
|
return -1;
|
|
return rank;
|
|
}
|
|
|
|
// Bouton de la souris pressé.
|
|
|
|
bool CMenu::MouseDown (POINT pos)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Souris déplacés.
|
|
|
|
bool CMenu::MouseMove (POINT pos)
|
|
{
|
|
m_selRank = Detect (pos);
|
|
|
|
if (pos.x < m_pos.x - (DIMBUTTONX + MARGMENU) ||
|
|
pos.x > m_pos.x + m_dim.x + (DIMBUTTONX + MARGMENU) ||
|
|
pos.y < m_pos.y - (DIMBUTTONY + MARGMENU) ||
|
|
pos.y > m_pos.y + m_dim.y + (DIMBUTTONY + MARGMENU))
|
|
{
|
|
Delete(); // enlève le menu si souris trop loin !
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Bouton de la souris relâché.
|
|
|
|
bool CMenu::MouseUp (POINT pos)
|
|
{
|
|
m_selRank = Detect (pos);
|
|
|
|
return false;
|
|
}
|
|
|
|
// Envoie le message.
|
|
|
|
void CMenu::Message()
|
|
{
|
|
if (m_selRank != -1)
|
|
CEvent::PushUserEvent (WM_BUTTON0 + m_selRank);
|
|
}
|
|
|
|
|