371 lines
13 KiB
C++
371 lines
13 KiB
C++
// SuperTuxKart - a fun racing game with go-kart
|
|
// Copyright (C) 2014-2015 Marc Coll
|
|
//
|
|
// 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 3
|
|
// of the License, or (at your option) 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, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
#include "states_screens/grand_prix_editor_screen.hpp"
|
|
|
|
#include "audio/sfx_manager.hpp"
|
|
#include "graphics/irr_driver.hpp"
|
|
#include "guiengine/widget.hpp"
|
|
#include "guiengine/widgets/label_widget.hpp"
|
|
#include "guiengine/widgets/text_box_widget.hpp"
|
|
#include "guiengine/widgets/dynamic_ribbon_widget.hpp"
|
|
#include "guiengine/widgets/icon_button_widget.hpp"
|
|
#include "io/file_manager.hpp"
|
|
#include "race/grand_prix_manager.hpp"
|
|
#include "states_screens/state_manager.hpp"
|
|
#include "states_screens/edit_gp_screen.hpp"
|
|
#include "states_screens/dialogs/general_text_field_dialog.hpp"
|
|
#include "tracks/track.hpp"
|
|
#include "tracks/track_manager.hpp"
|
|
#include "utils/string_utils.hpp"
|
|
#include "utils/translation.hpp"
|
|
|
|
using namespace GUIEngine;
|
|
using namespace irr::core;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
GrandPrixEditorScreen::GrandPrixEditorScreen()
|
|
: Screen("grand_prix_editor.stkgui"), m_selection(NULL),
|
|
m_gpgroup(GrandPrixData::GP_NONE)
|
|
{
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
void GrandPrixEditorScreen::beforeAddingWidget()
|
|
{
|
|
RibbonWidget* tabs = getWidget<RibbonWidget>("gpgroups");
|
|
assert (tabs != NULL);
|
|
|
|
tabs->clearAllChildren();
|
|
for (int i = 0; i < GrandPrixData::GP_GROUP_COUNT; i++)
|
|
{
|
|
core::stringw label = getGroupName((enum GrandPrixData::GPGroupType)i);
|
|
tabs->addTextChild(label.c_str(), StringUtils::toString(i));
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
void GrandPrixEditorScreen::loadedFromFile()
|
|
{
|
|
static const int MAX_LABEL_LENGTH = 35;
|
|
|
|
DynamicRibbonWidget* gplist_widget = getWidget<DynamicRibbonWidget>("gplist");
|
|
assert (gplist_widget != NULL);
|
|
gplist_widget->setMaxLabelLength(MAX_LABEL_LENGTH);
|
|
|
|
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
|
|
assert(tracks_widget != NULL);
|
|
tracks_widget->setMaxLabelLength(MAX_LABEL_LENGTH);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
void GrandPrixEditorScreen::eventCallback(Widget* widget, const std::string& name, const int playerID)
|
|
{
|
|
if (name == "gplist")
|
|
{
|
|
DynamicRibbonWidget* gplist_widget = getWidget<DynamicRibbonWidget>("gplist");
|
|
assert (gplist_widget != NULL);
|
|
std::string selected = gplist_widget->getSelectionIDString(PLAYER_ID_GAME_MASTER);
|
|
if (!selected.empty())
|
|
{
|
|
if (m_selection != NULL && selected == m_selection->getId() && m_selection->isEditable())
|
|
showEditScreen(m_selection);
|
|
else
|
|
setSelection (grand_prix_manager->getGrandPrix(selected));
|
|
}
|
|
}
|
|
else if (name == "menu")
|
|
{
|
|
RibbonWidget* menu = getWidget<RibbonWidget>("menu");
|
|
assert(menu != NULL);
|
|
m_action = menu->getSelectionIDString(PLAYER_ID_GAME_MASTER);
|
|
|
|
if (m_action == "new" || m_action == "copy")
|
|
{
|
|
new GeneralTextFieldDialog(_("Please enter the name of the grand prix"),
|
|
std::bind(&GrandPrixEditorScreen::setNewGPWithName,
|
|
this, std::placeholders::_1), validateName);
|
|
}
|
|
else if (m_action == "edit" && m_selection != NULL)
|
|
{
|
|
showEditScreen(m_selection);
|
|
}
|
|
else if (m_action == "remove" && m_selection != NULL)
|
|
{
|
|
new MessageDialog(
|
|
_("Are you sure you want to remove '%s'?", m_selection->getName().c_str()),
|
|
MessageDialog::MESSAGE_DIALOG_CONFIRM,
|
|
this, false);
|
|
}
|
|
else if (m_action == "rename" && m_selection != NULL)
|
|
{
|
|
new GeneralTextFieldDialog(_("Please enter the name of the grand prix"),
|
|
std::bind(&GrandPrixEditorScreen::setNewGPWithName,
|
|
this, std::placeholders::_1), validateName);
|
|
}
|
|
}
|
|
else if (name == "gpgroups")
|
|
{
|
|
RibbonWidget* tabs = getWidget<RibbonWidget>("gpgroups");
|
|
assert(tabs != NULL);
|
|
|
|
enum GrandPrixData::GPGroupType group = (enum GrandPrixData::GPGroupType)atoi(
|
|
tabs->getSelectionIDString(PLAYER_ID_GAME_MASTER).c_str());
|
|
if (m_gpgroup != group)
|
|
{
|
|
m_gpgroup = group;
|
|
loadGPList();
|
|
setSelection(NULL);
|
|
}
|
|
}
|
|
else if (name == "back")
|
|
{
|
|
m_gpgroup = GrandPrixData::GP_NONE;
|
|
setSelection(NULL);
|
|
StateManager::get()->escapePressed();
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
void GrandPrixEditorScreen::init()
|
|
{
|
|
RibbonWidget* tabs = getWidget<RibbonWidget>("gpgroups");
|
|
assert (tabs != NULL);
|
|
|
|
tabs->select (StringUtils::toString(m_gpgroup), PLAYER_ID_GAME_MASTER);
|
|
loadGPList();
|
|
setSelection(m_selection);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
void GrandPrixEditorScreen::setSelection (const GrandPrixData* gpdata)
|
|
{
|
|
LabelWidget* gpname_widget = getWidget<LabelWidget>("gpname");
|
|
assert(gpname_widget != NULL);
|
|
DynamicRibbonWidget* gplist_widget = getWidget<DynamicRibbonWidget>("gplist");
|
|
assert (gplist_widget != NULL);
|
|
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
|
|
assert(tracks_widget != NULL);
|
|
|
|
if (gpdata == NULL)
|
|
{
|
|
m_selection = NULL;
|
|
gpname_widget->setText (_("Please select a Grand Prix"), true);
|
|
tracks_widget->clearItems();
|
|
tracks_widget->updateItemDisplay();
|
|
}
|
|
else
|
|
{
|
|
m_selection = grand_prix_manager->editGrandPrix(gpdata->getId());
|
|
gpname_widget->setText(gpdata->getName(), true);
|
|
gplist_widget->setSelection(m_selection->getId(), PLAYER_ID_GAME_MASTER, true);
|
|
loadTrackList (gpdata->getId());
|
|
}
|
|
|
|
enableButtons();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
void GrandPrixEditorScreen::loadTrackList (const std::string& gpname)
|
|
{
|
|
if (gpname.empty())
|
|
return;
|
|
|
|
DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
|
|
assert(tracks_widget != NULL);
|
|
|
|
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(gpname);
|
|
const std::vector<std::string> tracks = gp->getTrackNames(true);
|
|
|
|
tracks_widget->clearItems();
|
|
tracks_widget->setItemCountHint((int)tracks.size());
|
|
for (unsigned int t = 0; t < tracks.size(); t++)
|
|
{
|
|
Track* curr = track_manager->getTrack(tracks[t]);
|
|
if (curr == NULL)
|
|
{
|
|
Log::warn("GrandPrixEditor",
|
|
"Grand Prix '%s' refers to track '%s', which does not exist\n",
|
|
gp->getId().c_str(), tracks[t].c_str());
|
|
}
|
|
else
|
|
{
|
|
tracks_widget->addItem(
|
|
StringUtils::toWString(t + 1) + ". " + curr->getName(),
|
|
curr->getIdent(), curr->getScreenshotFile(), 0,
|
|
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE );
|
|
}
|
|
}
|
|
|
|
tracks_widget->updateItemDisplay();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
void GrandPrixEditorScreen::loadGPList()
|
|
{
|
|
DynamicRibbonWidget* gplist_widget = getWidget<DynamicRibbonWidget>("gplist");
|
|
assert(gplist_widget != NULL);
|
|
|
|
// Reset GP list everytime (accounts for locking changes, etc.)
|
|
gplist_widget->clearItems();
|
|
|
|
// ensures that no GP and no track is NULL
|
|
grand_prix_manager->checkConsistency();
|
|
|
|
// Build GP list
|
|
for (unsigned int i = 0; i < grand_prix_manager->getNumberOfGrandPrix(); i++)
|
|
{
|
|
const GrandPrixData* gp = grand_prix_manager->getGrandPrix(i);
|
|
const std::vector<std::string> tracks = gp->getTrackNames(true);
|
|
|
|
std::vector<std::string> sshot_files;
|
|
for (unsigned int t=0; t<tracks.size(); t++)
|
|
{
|
|
Track* track = track_manager->getTrack(tracks[t]);
|
|
sshot_files.push_back(track->getScreenshotFile());
|
|
}
|
|
if (sshot_files.empty())
|
|
sshot_files.push_back(file_manager->getAsset(FileManager::GUI_ICON,"main_help.png"));
|
|
|
|
if (m_gpgroup == GrandPrixData::GP_NONE || m_gpgroup == gp->getGroup())
|
|
{
|
|
gplist_widget->addAnimatedItem(gp->getName(),
|
|
gp->getId(), sshot_files, 2.0f, 0,
|
|
IconButtonWidget::ICON_PATH_TYPE_ABSOLUTE );
|
|
}
|
|
}
|
|
|
|
gplist_widget->updateItemDisplay();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
void GrandPrixEditorScreen::showEditScreen(GrandPrixData* gp)
|
|
{
|
|
assert(gp != NULL);
|
|
EditGPScreen* edit = EditGPScreen::getInstance();
|
|
edit->setSelectedGP(gp);
|
|
edit->push();
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
void GrandPrixEditorScreen::enableButtons()
|
|
{
|
|
IconButtonWidget* copy_button = getWidget<IconButtonWidget>("copy");
|
|
IconButtonWidget* edit_button = getWidget<IconButtonWidget>("edit");
|
|
IconButtonWidget* remove_button = getWidget<IconButtonWidget>("remove");
|
|
IconButtonWidget* rename_button = getWidget<IconButtonWidget>("rename");
|
|
assert(copy_button != NULL);
|
|
assert(edit_button != NULL);
|
|
assert(remove_button != NULL);
|
|
assert(rename_button != NULL);
|
|
|
|
bool b = m_selection && m_selection->getNumberOfTracks() > 0;
|
|
copy_button->setActive(b);
|
|
|
|
b = m_selection && m_selection->isEditable();
|
|
edit_button->setActive(b);
|
|
remove_button->setActive(b);
|
|
rename_button->setActive(b);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
void GrandPrixEditorScreen::setNewGPWithName(const stringw& newName)
|
|
{
|
|
if (m_action == "copy" && m_selection != NULL)
|
|
{
|
|
setSelection(grand_prix_manager->copy(m_selection->getId(), newName));
|
|
}
|
|
else if (m_action == "rename" && m_selection != NULL)
|
|
{
|
|
m_selection->setName(newName);
|
|
m_selection->writeToFile();
|
|
setSelection(grand_prix_manager->getGrandPrix(m_selection->getId()));
|
|
}
|
|
else if (m_action == "new")
|
|
{
|
|
setSelection(grand_prix_manager->createNewGP(newName));
|
|
}
|
|
|
|
loadGPList();
|
|
if (m_action != "rename" && m_selection != NULL)
|
|
showEditScreen(m_selection);
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
void GrandPrixEditorScreen::onConfirm()
|
|
{
|
|
if (m_action == "remove" && m_selection != NULL)
|
|
{
|
|
grand_prix_manager->remove(m_selection->getId());
|
|
loadGPList();
|
|
|
|
if (grand_prix_manager->getNumberOfGrandPrix() > 0)
|
|
{
|
|
setSelection(grand_prix_manager->getGrandPrix(0));
|
|
}
|
|
else
|
|
{
|
|
setSelection(NULL);
|
|
}
|
|
}
|
|
ModalDialog::dismiss();
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
const core::stringw GrandPrixEditorScreen::getGroupName(enum GrandPrixData::GPGroupType group)
|
|
{
|
|
switch (group)
|
|
{
|
|
case GrandPrixData::GP_NONE: return _("All");
|
|
case GrandPrixData::GP_STANDARD: return _("Standard");
|
|
case GrandPrixData::GP_USER_DEFINED: return _("User defined");
|
|
case GrandPrixData::GP_ADDONS: return _("Add-Ons");
|
|
default: return L"???";
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
bool GrandPrixEditorScreen::validateName(LabelWidget* label,
|
|
TextBoxWidget* text)
|
|
{
|
|
stringw name = text->getText().trim();
|
|
if (name.size() == 0)
|
|
{
|
|
label->setText(_("Name is empty."), false);
|
|
SFXManager::get()->quickSound("anvil");
|
|
return false;
|
|
}
|
|
else if (grand_prix_manager->existsName(name) ||
|
|
name == GrandPrixData::getRandomGPName())
|
|
{
|
|
// check for duplicate names
|
|
label->setText(_("Another grand prix with this name already exists."), false);
|
|
SFXManager::get()->quickSound("anvil");
|
|
return false;
|
|
}
|
|
else if (name.size() > 30)
|
|
{
|
|
label->setText(_("Name is too long."), false);
|
|
SFXManager::get()->quickSound("anvil");
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
}
|