334 lines
10 KiB
C++
334 lines
10 KiB
C++
#include "dialog.h"
|
|
#include "graphics.h"
|
|
|
|
|
|
namespace Dialog
|
|
{
|
|
int _uniqueItemId = 0;
|
|
|
|
std::map<std::string, Dialog> _dialogMap;
|
|
|
|
|
|
//*****************************************************************************************************************
|
|
// Item object
|
|
//*****************************************************************************************************************
|
|
Item::Item()
|
|
{
|
|
_index = _uniqueItemId++;
|
|
}
|
|
|
|
Item::Item(bool isInteractable, const std::string& text)
|
|
{
|
|
_index = _uniqueItemId++;
|
|
_isInteractable = isInteractable;
|
|
_text = text;
|
|
}
|
|
|
|
Item::Item(int index, bool isInteractable, const std::string& text)
|
|
{
|
|
_index = index;
|
|
_isInteractable = isInteractable;
|
|
_text = text;
|
|
}
|
|
|
|
Item::Item(bool isInteractable, const std::string& text, int jstX) : Item(isInteractable, text)
|
|
{
|
|
_jstX = jstX;
|
|
}
|
|
|
|
Item::Item(bool isInteractable, const std::string& text, int jstX, Colour colour) : Item(isInteractable, text, jstX)
|
|
{
|
|
_colour = colour;
|
|
}
|
|
|
|
Item::Item(bool isInteractable, const std::string& text, int jstX, int jstY) : Item(isInteractable, text, jstX)
|
|
{
|
|
_jstY = jstY;
|
|
}
|
|
|
|
Item::Item(bool isInteractable, const std::string& text, int jstX, int jstY, Colour colour) : Item(isInteractable, text, jstX, jstY)
|
|
{
|
|
_colour = colour;
|
|
}
|
|
|
|
|
|
int Item::getIndex(void) {return _index;}
|
|
int Item::getJstX(void) {return _jstX;}
|
|
int Item::getJstY(void) {return _jstY;}
|
|
int Item::getPosX(void) {return _posX;}
|
|
int Item::getPosY(void) {return _posY;}
|
|
Item::Colour Item::getColour(void) {return _colour;}
|
|
const std::string& Item::getText(void) {return _text;}
|
|
bool Item::getIsInteractable(void) {return _isInteractable;}
|
|
|
|
void Item::setIndex(int index) {_index = index;}
|
|
void Item::setPosX(int posX) {_posX = posX;}
|
|
void Item::setPosY(int posY) {_posY = posY;}
|
|
void Item::setColour(Item::Colour colour) {_colour = colour;}
|
|
void Item::setText(const std::string& text) {_text = text;}
|
|
|
|
|
|
//*****************************************************************************************************************
|
|
// Dialog object
|
|
//*****************************************************************************************************************
|
|
int Dialog::getDialogX(void) {return _dialogX;}
|
|
int Dialog::getDialogY(void) {return _dialogY;}
|
|
bool Dialog::getIsActive(void) {return _isActive;}
|
|
Dialog::Size Dialog::getSize(void) {return _size;}
|
|
|
|
std::vector<Item>& Dialog::getItems(void) {return _items;}
|
|
|
|
void Dialog::setIsActive(bool isActive) {_isActive = isActive;}
|
|
void Dialog::setMaxColsRows(int maxCols, int maxRows) {_maxCols = maxCols; _maxRows = maxRows;}
|
|
void Dialog::setSize(Dialog::Size size) {_size = size;}
|
|
|
|
bool Dialog::getDialogItem(int index, Item& item)
|
|
{
|
|
if(index >=0 && index < int(_items.size()))
|
|
{
|
|
item = _items[index];
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int Dialog::getDialogItemIndex(int mouseX, int mouseY)
|
|
{
|
|
for(int i=0; i<int(_items.size()); i++)
|
|
{
|
|
if(_items[i].getIsInteractable())
|
|
{
|
|
int dx, dy;
|
|
mouseToDialogSpace(mouseX, mouseY, dx, dy);
|
|
|
|
int x = _items[i].getPosX();
|
|
int y = _items[i].getPosY();
|
|
int ox = int(_items[i].getText().size()) * FONT_WIDTH;
|
|
if(dx >= x && dx < x + ox && dy >= y && dy < y + FONT_HEIGHT)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
bool Dialog::setDialogItem(int index, Item& item)
|
|
{
|
|
if(index >=0 && index < int(_items.size()))
|
|
{
|
|
_items[index] = item;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Dialog::setDialogItemText(int index, const std::string& text)
|
|
{
|
|
if(index >=0 && index < int(_items.size()))
|
|
{
|
|
_items[index].setText(text);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool Dialog::create(const std::string& text, const std::vector<Item>& items, int numCols, int numRows, Size size, int offsetX, int offsetY, int maxCols, int maxRows)
|
|
{
|
|
_text = text;
|
|
_items = items;
|
|
_numCols = numCols;
|
|
_numRows = numRows;
|
|
_size = size;
|
|
_offsetX = offsetX;
|
|
_offsetY = offsetY;
|
|
_maxCols = maxCols;
|
|
_maxRows = maxRows;
|
|
|
|
return true;
|
|
}
|
|
|
|
void Dialog::gigaToDialog(int gigaX, int gigaY)
|
|
{
|
|
// Convert to dialog space
|
|
_dialogX = int(float(gigaX) * 4.0f / FONT_WIDTH);
|
|
_dialogY = int(float(gigaY) * 4.0f / FONT_HEIGHT);
|
|
|
|
_gigaX = gigaX;
|
|
_gigaY = gigaY;
|
|
|
|
if(_dialogX > (_maxCols-_numCols)) _dialogX = (_maxCols-_numCols);
|
|
if(_dialogY > (_maxRows-_numRows)) _dialogY = (_maxRows-_numRows);
|
|
}
|
|
|
|
void Dialog::mouseToDialogSpace(int mouseX, int mouseY, int& dspaceX, int& dspaceY)
|
|
{
|
|
// Normalise mouse coords and convert to dialog space
|
|
float mx = float(mouseX) / float(Graphics::getWidth());
|
|
float my = float(mouseY) / float(Graphics::getHeight());
|
|
dspaceX = int(mx * float(SCREEN_WIDTH));
|
|
dspaceY = int(my * float(SCREEN_HEIGHT));
|
|
}
|
|
|
|
void Dialog::render(int mouseX, int mouseY)
|
|
{
|
|
// Width and height in giga coords
|
|
int w = 0;
|
|
int h = _offsetY*2;
|
|
for(int i=0; i<int(_items.size()); i++)
|
|
{
|
|
if(_items[i].getJstY() == Item::NextY) h += 2;
|
|
|
|
int size = int(_items[i].getText().size());
|
|
if(size > w) w = size;
|
|
}
|
|
if(_items.size() > 1 && (w == 0 || int(_text.size()) > w))
|
|
{
|
|
w = int(_text.size());
|
|
}
|
|
w += _offsetX*2;
|
|
|
|
// Size
|
|
int scale = (_size == DoubleWidth) ? 2 : 1;
|
|
|
|
// Border and interior
|
|
Graphics::drawDialog(int16_t(_gigaX), int16_t(_gigaY), int16_t(w*2*scale), int16_t(h), 0x55555555, 0x88888888);
|
|
|
|
int tx = _gigaX*3 + 1;
|
|
int ty = (_gigaY + _offsetY + 1)*4;
|
|
|
|
// Title
|
|
int ox = (w*FONT_WIDTH - int(_text.size())*FONT_WIDTH/2);
|
|
|
|
// Items
|
|
for(int i=0; i<int(_items.size()); i++)
|
|
{
|
|
// Justification
|
|
switch(_items[i].getJstX())
|
|
{
|
|
case Item::LeftX: ox = (w*FONT_WIDTH*scale/4 - int(_items[i].getText().size())*FONT_WIDTH/2); break;
|
|
case Item::CenterX: ox = (w*FONT_WIDTH*scale/2 - int(_items[i].getText().size())*FONT_WIDTH/2); break;
|
|
case Item::RightX: ox = (w*FONT_WIDTH*scale*3/4 - int(_items[i].getText().size())*FONT_WIDTH/2); break;
|
|
|
|
default: break;
|
|
}
|
|
|
|
// Different background colour for interactable items
|
|
uint32_t bgColour = 0x55555555;
|
|
switch(_items[i].getColour())
|
|
{
|
|
case Item::Bg: bgColour = 0x55555555; break;
|
|
case Item::Fg: bgColour = 0xFFFFFFFF; break;
|
|
case Item::Bd: bgColour = 0x88888888; break;
|
|
|
|
default: break;
|
|
}
|
|
|
|
// Highlight interactable item for mouse over
|
|
uint32_t fgColour = 0xFFFFFFFF;
|
|
if(_items[i].getIsInteractable())
|
|
{
|
|
int index = getDialogItemIndex(mouseX, mouseY);
|
|
if(index == i) std::swap(fgColour, bgColour);
|
|
}
|
|
else
|
|
{
|
|
fgColour = 0xAAAAAAAA;
|
|
}
|
|
|
|
// Multiple items per line
|
|
if(_items[i].getJstY() == Item::CurrentY)
|
|
{
|
|
ty -= (FONT_HEIGHT);
|
|
}
|
|
|
|
// Save item position in screen coords
|
|
_items[i].setPosX((tx + ox));
|
|
_items[i].setPosY(ty);
|
|
|
|
Graphics::drawDialogItem(_items[i].getText(), tx + ox, ty, fgColour, bgColour);
|
|
|
|
// Next line
|
|
ty += (FONT_HEIGHT);
|
|
}
|
|
}
|
|
|
|
|
|
//*****************************************************************************************************************
|
|
// Dialog
|
|
//*****************************************************************************************************************
|
|
void initialise(void)
|
|
{
|
|
}
|
|
|
|
bool getDialog(const std::string& name, Dialog& dialog)
|
|
{
|
|
if(_dialogMap.find(name) == _dialogMap.end()) return false;
|
|
|
|
dialog = _dialogMap[name];
|
|
|
|
return true;
|
|
}
|
|
|
|
bool getDialogItem(const std::string& name, int index, Item& item)
|
|
{
|
|
if(_dialogMap.find(name) == _dialogMap.end()) return false;
|
|
|
|
return _dialogMap[name].getDialogItem(index, item);
|
|
}
|
|
|
|
int getDialogItemIndex(const std::string& name, int mouseX, int mouseY)
|
|
{
|
|
if(_dialogMap.find(name) == _dialogMap.end()) return false;
|
|
|
|
return _dialogMap[name].getDialogItemIndex(mouseX, mouseY);
|
|
}
|
|
|
|
bool setDialogItem(const std::string& name, int index, Item& item)
|
|
{
|
|
if(_dialogMap.find(name) == _dialogMap.end()) return false;
|
|
|
|
return _dialogMap[name].setDialogItem(index, item);
|
|
}
|
|
|
|
bool setDialogItemText(const std::string& name, int index, const std::string& text)
|
|
{
|
|
if(_dialogMap.find(name) == _dialogMap.end()) return false;
|
|
|
|
return _dialogMap[name].setDialogItemText(index, text);
|
|
}
|
|
|
|
bool createDialog(const std::string& name, const std::string& text, const std::vector<Item>& items, int numCols, int numRows, Dialog::Size size, int offsetX, int offsetY, int maxCols, int maxRows)
|
|
{
|
|
if(_dialogMap.find(name) != _dialogMap.end()) return false;
|
|
|
|
Dialog dialog;
|
|
dialog.create(text, items, numCols, numRows, size, offsetX, offsetY, maxCols, maxRows);
|
|
_dialogMap[name] = dialog;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool positionDialog(const std::string& name, int gigaX, int gigaY)
|
|
{
|
|
if(_dialogMap.find(name) == _dialogMap.end()) return false;
|
|
|
|
_dialogMap[name].gigaToDialog(gigaX, gigaY);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool renderDialog(const std::string& name, int mouseX, int mouseY)
|
|
{
|
|
if(_dialogMap.find(name) == _dialogMap.end()) return false;
|
|
|
|
_dialogMap[name].render(mouseX, mouseY);
|
|
_dialogMap[name].setIsActive(true);
|
|
|
|
return true;
|
|
}
|
|
} |