mirror of
https://github.com/AquariaOSE/Aquaria.git
synced 2024-12-03 00:15:46 +00:00
b32ce853e7
Why did this never happen before??!
938 lines
20 KiB
C++
938 lines
20 KiB
C++
/*
|
|
Copyright (C) 2007, 2010 - Bit-Blot
|
|
|
|
This file is part of Aquaria.
|
|
|
|
Aquaria 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 2
|
|
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 "../BBGE/DebugFont.h"
|
|
|
|
#include "DSQ.h"
|
|
#include "AquariaProgressBar.h"
|
|
#include "ModSelector.h"
|
|
#include <algorithm>
|
|
|
|
#ifdef BBGE_BUILD_VFS
|
|
#include "ModDownloader.h"
|
|
#endif
|
|
|
|
#include "tinyxml2.h"
|
|
using namespace tinyxml2;
|
|
|
|
#define MOD_ICON_SIZE 150
|
|
#define MINI_ICON_SIZE 32
|
|
|
|
|
|
static bool _modname_cmp(const ModIcon *a, const ModIcon *b)
|
|
{
|
|
return a->fname < b->fname;
|
|
}
|
|
|
|
ModSelectorScreen::ModSelectorScreen() : Quad(), ActionMapper(),
|
|
currentPanel(-1), gotServerList(false), dlText(&dsq->smallFont), subtext(&dsq->subsFont)
|
|
{
|
|
followCamera = 1;
|
|
shareAlphaWithChildren = false;
|
|
alpha = 1;
|
|
alphaMod = 0.1f;
|
|
color = 0;
|
|
globeIcon = NULL;
|
|
modsIcon = NULL;
|
|
subFadeT = -1;
|
|
}
|
|
|
|
void ModSelectorScreen::moveUp()
|
|
{
|
|
move(5);
|
|
}
|
|
|
|
void ModSelectorScreen::moveDown()
|
|
{
|
|
move(-5);
|
|
}
|
|
|
|
void ModSelectorScreen::move(int ud, bool instant /* = false */)
|
|
{
|
|
IconGridPanel *grid = panels[currentPanel];
|
|
InterpolatedVector& v = grid->position;
|
|
const float ch = ud * 42;
|
|
const float t = instant ? 0.0f : 0.2f;
|
|
if(!instant && v.isInterpolating())
|
|
{
|
|
v.data->from = v;
|
|
v.data->target.y += ch;
|
|
v.data->timePassed = 0;
|
|
|
|
if(v.data->target.y > 200)
|
|
v.data->target.y = 200;
|
|
else if(v.data->target.y < -grid->getUsedY())
|
|
v.data->target.y = -grid->getUsedY();
|
|
}
|
|
else
|
|
{
|
|
Vector v2 = grid->position;
|
|
v2.y += ch; // scroll down == grid pos y gets negative (grid scrolls up)
|
|
|
|
if(v2.y > 200)
|
|
grid->position.interpolateTo(Vector(v2.x, 200), t);
|
|
else if(v2.y < -grid->getUsedY())
|
|
grid->position.interpolateTo(Vector(v2.x, -grid->getUsedY()), t);
|
|
else
|
|
grid->position.interpolateTo(v2, t, 0, false, true);
|
|
}
|
|
}
|
|
|
|
void ModSelectorScreen::onUpdate(float dt)
|
|
{
|
|
Quad::onUpdate(dt);
|
|
|
|
// mouse wheel scroll
|
|
if(dsq->mouse.scrollWheelChange)
|
|
{
|
|
move(dsq->mouse.scrollWheelChange * 2);
|
|
}
|
|
|
|
if(subFadeT >= 0)
|
|
{
|
|
subFadeT = subFadeT - dt;
|
|
if(subFadeT <= 0)
|
|
{
|
|
subbox.alpha.interpolateTo(0, 1.0f);
|
|
subtext.alpha.interpolateTo(0, 1.2f);
|
|
}
|
|
}
|
|
|
|
if(!AquariaGuiElement::currentFocus && dsq->inputMode == INPUT_JOYSTICK)
|
|
{
|
|
AquariaGuiElement *closest = AquariaGuiElement::getClosestGuiElement(core->mouse.position);
|
|
if(closest)
|
|
{
|
|
debugLog("Lost focus, setting nearest gui element");
|
|
closest->setFocus(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void ModSelectorScreen::showPanel(int id)
|
|
{
|
|
if(id == currentPanel)
|
|
return;
|
|
|
|
const float t = 0.2f;
|
|
IconGridPanel *newgrid = panels[id];
|
|
|
|
// fade in selected panel
|
|
if(currentPanel < 0) // just bringing up?
|
|
{
|
|
newgrid->scale = Vector(0.8f,0.8f);
|
|
newgrid->alpha = 0;
|
|
}
|
|
|
|
currentPanel = id;
|
|
|
|
updateFade();
|
|
}
|
|
|
|
void ModSelectorScreen::updateFade()
|
|
{
|
|
// fade out background panels
|
|
// necessary to do all of them, that icon alphas are 0... they would trigger otherwise, even if invisible because parent panel is not shown
|
|
for(int i = 0; i < panels.size(); ++i)
|
|
panels[i]->fade(i == currentPanel, true);
|
|
}
|
|
|
|
static void _MenuIconClickCallback(int id, void *user)
|
|
{
|
|
ModSelectorScreen *ms = (ModSelectorScreen*)user;
|
|
switch(id) // see MenuIconBar::init()
|
|
{
|
|
case 2: // network
|
|
ms->initNetPanel();
|
|
break;
|
|
|
|
case 3: // exit
|
|
dsq->quitNestedMain();
|
|
return;
|
|
}
|
|
|
|
ms->showPanel(id);
|
|
}
|
|
|
|
// can be called multiple times without causing trouble
|
|
void ModSelectorScreen::init()
|
|
{
|
|
leftbar.width = 100;
|
|
leftbar.height = height;
|
|
leftbar.alpha = 0;
|
|
leftbar.alpha.interpolateTo(1, 0.2f);
|
|
leftbar.position = Vector((leftbar.width - width) / 2, 0);
|
|
leftbar.followCamera = 1;
|
|
if(!leftbar.getParent())
|
|
{
|
|
leftbar.init();
|
|
addChild(&leftbar, PM_STATIC);
|
|
|
|
panels.resize(leftbar.icons.size());
|
|
std::fill(panels.begin(), panels.end(), (IconGridPanel*)NULL);
|
|
}
|
|
|
|
rightbar.width = 100;
|
|
rightbar.height = height;
|
|
rightbar.alpha = 0;
|
|
rightbar.alpha.interpolateTo(1, 0.2f);
|
|
rightbar.position = Vector(((width - rightbar.width) / 2), 0);
|
|
rightbar.followCamera = 1;
|
|
if(!rightbar.getParent())
|
|
{
|
|
rightbar.init();
|
|
addChild(&rightbar, PM_STATIC);
|
|
}
|
|
|
|
for(int i = 0; i < panels.size(); ++i)
|
|
{
|
|
if(panels[i])
|
|
continue;
|
|
panels[i] = new IconGridPanel();
|
|
panels[i]->followCamera = 1;
|
|
panels[i]->width = width - leftbar.width - rightbar.width;
|
|
panels[i]->height = 750;
|
|
panels[i]->position = Vector(0, 0);
|
|
panels[i]->alpha = 0;
|
|
panels[i]->spacing = 20; // for the grid
|
|
panels[i]->scale = Vector(0.8f, 0.8f);
|
|
leftbar.icons[i]->cb = _MenuIconClickCallback;
|
|
leftbar.icons[i]->cb_data = this;
|
|
addChild(panels[i], PM_POINTER);
|
|
}
|
|
|
|
arrowUp.useQuad("Gui/arrow-left");
|
|
arrowUp.useSound("click");
|
|
arrowUp.useGlow("particles/glow", 128, 64);
|
|
arrowUp.position = Vector(0, -230);
|
|
arrowUp.followCamera = 1;
|
|
arrowUp.rotation.z = 90;
|
|
arrowUp.event.set(MakeFunctionEvent(ModSelectorScreen, moveUp));
|
|
arrowUp.guiInputLevel = 100;
|
|
arrowUp.alpha = 0;
|
|
arrowUp.alpha.interpolateTo(1, 0.2f);
|
|
arrowUp.setDirMove(DIR_DOWN, &arrowDown);
|
|
rightbar.addChild(&arrowUp, PM_STATIC);
|
|
|
|
arrowDown.useQuad("Gui/arrow-right");
|
|
arrowDown.useSound("click");
|
|
arrowDown.useGlow("particles/glow", 128, 64);
|
|
arrowDown.position = Vector(0, 170);
|
|
arrowDown.followCamera = 1;
|
|
arrowDown.rotation.z = 90;
|
|
arrowDown.event.set(MakeFunctionEvent(ModSelectorScreen, moveDown));
|
|
arrowDown.guiInputLevel = 100;
|
|
arrowDown.alpha = 0;
|
|
arrowDown.alpha.interpolateTo(1, 0.2f);
|
|
arrowDown.setDirMove(DIR_UP, &arrowUp);
|
|
rightbar.addChild(&arrowDown, PM_STATIC);
|
|
|
|
dlText.alpha = 0;
|
|
dlText.position = Vector(0, 0);
|
|
dlText.setFontSize(15);
|
|
dlText.scale = Vector(1.5f, 1.5f);
|
|
dlText.followCamera = 1;
|
|
addChild(&dlText, PM_STATIC);
|
|
|
|
initModAndPatchPanel();
|
|
// net panel inited on demand
|
|
|
|
showPanel(0);
|
|
|
|
subbox.position = Vector(0,260);
|
|
subbox.alpha = 0;
|
|
subbox.alphaMod = 0.7;
|
|
subbox.followCamera = 1;
|
|
subbox.autoWidth = AUTO_VIRTUALWIDTH;
|
|
subbox.setHeight(80);
|
|
subbox.color = Vector(0, 0, 0);
|
|
addChild(&subbox, PM_STATIC);
|
|
|
|
subtext.position = Vector(0,230);
|
|
subtext.followCamera = 1;
|
|
subtext.alpha = 0;
|
|
subtext.setFontSize(12);
|
|
subtext.setWidth(800);
|
|
subtext.setAlign(ALIGN_CENTER);
|
|
addChild(&subtext, PM_STATIC);
|
|
|
|
dsq->toggleVersionLabel(false);
|
|
|
|
modsIcon->setFocus(true);
|
|
}
|
|
|
|
void ModSelectorScreen::initModAndPatchPanel()
|
|
{
|
|
IconGridPanel *modgrid = panels[0];
|
|
IconGridPanel *patchgrid = panels[1];
|
|
ModIcon *ico;
|
|
std::vector<ModIcon*> tv; // for sorting
|
|
tv.resize(dsq->modEntries.size());
|
|
for(unsigned int i = 0; i < tv.size(); ++i)
|
|
{
|
|
ico = NULL;
|
|
for(RenderObject::Children::iterator it = modgrid->children.begin(); it != modgrid->children.end(); ++it)
|
|
if(ModIcon* other = dynamic_cast<ModIcon*>(*it))
|
|
if(other->modId == i)
|
|
{
|
|
ico = other;
|
|
break;
|
|
}
|
|
|
|
if(!ico)
|
|
{
|
|
for(RenderObject::Children::iterator it = patchgrid->children.begin(); it != patchgrid->children.end(); ++it)
|
|
if(ModIcon* other = dynamic_cast<ModIcon*>(*it))
|
|
if(other->modId == i)
|
|
{
|
|
ico = other;
|
|
break;
|
|
}
|
|
|
|
if(!ico) // ok, its really not there.
|
|
{
|
|
ico = new ModIcon;
|
|
ico->followCamera = 1;
|
|
std::ostringstream os;
|
|
os << "Created ModIcon " << i;
|
|
debugLog(os.str());
|
|
}
|
|
}
|
|
|
|
tv[i] = ico;
|
|
ico->loadEntry(dsq->modEntries[i]);
|
|
}
|
|
std::sort(tv.begin(), tv.end(), _modname_cmp);
|
|
|
|
for(int i = 0; i < tv.size(); ++i)
|
|
{
|
|
if(!tv[i]->getParent()) // ensure it was not added earlier
|
|
{
|
|
if(tv[i]->modType == MODTYPE_PATCH)
|
|
patchgrid->add(tv[i]);
|
|
else
|
|
modgrid->add(tv[i]);
|
|
}
|
|
}
|
|
updateFade();
|
|
}
|
|
|
|
void ModSelectorScreen::initNetPanel()
|
|
{
|
|
#ifdef BBGE_BUILD_VFS
|
|
if(!gotServerList)
|
|
{
|
|
moddl.init();
|
|
std::string serv = dsq->user.network.masterServer;
|
|
if(serv.empty())
|
|
serv = DEFAULT_MASTER_SERVER;
|
|
moddl.GetModlist(serv, true, true);
|
|
|
|
gotServerList = true; // try this only once (is automatically reset on failure)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ModSelectorScreen::setSubText(const std::string& s)
|
|
{
|
|
subtext.setText(s);
|
|
subtext.alpha.interpolateTo(1, 0.2f);
|
|
subbox.alpha.interpolateTo(1, 0.2f);
|
|
subFadeT = 1;
|
|
}
|
|
|
|
static void _FadeOutAll(RenderObject *r, float t)
|
|
{
|
|
r->alpha.interpolateTo(0, t);
|
|
for(RenderObject::Children::iterator it = r->children.begin(); it != r->children.end(); ++it)
|
|
_FadeOutAll(*it, t);
|
|
}
|
|
|
|
void ModSelectorScreen::close()
|
|
{
|
|
const float t = 0.5f;
|
|
_FadeOutAll(this, t);
|
|
dsq->user.save();
|
|
dsq->toggleVersionLabel(true);
|
|
}
|
|
|
|
JuicyProgressBar::JuicyProgressBar() : Quad(), txt(&dsq->smallFont)
|
|
{
|
|
setTexture("modselect/tube");
|
|
followCamera = 1;
|
|
alpha = 1;
|
|
|
|
juice.setTexture("loading/juice");
|
|
juice.alpha = 0.8;
|
|
juice.followCamera = 1;
|
|
addChild(&juice, PM_STATIC);
|
|
|
|
txt.alpha = 0.7;
|
|
txt.followCamera = 1;
|
|
addChild(&txt, PM_STATIC);
|
|
|
|
progress(0);
|
|
}
|
|
|
|
void JuicyProgressBar::progress(float p)
|
|
{
|
|
juice.width = p * width;
|
|
juice.height = height - 4;
|
|
perc = p;
|
|
}
|
|
|
|
BasicIcon::BasicIcon()
|
|
: mouseDown(false), scaleNormal(1,1), scaleBig(scaleNormal * 1.1f), _isRecCall(false)
|
|
{
|
|
// HACK: Because AquariaMenuItem assigns onClick() in it's ctor,
|
|
// but we handle this ourselves.
|
|
clearCreatedEvents();
|
|
clearActions();
|
|
shareAlpha = true;
|
|
guiInputLevel = 100;
|
|
}
|
|
|
|
bool BasicIcon::isGuiVisible()
|
|
{
|
|
return !isHidden() && alpha.x > 0.1f && alphaMod > 0.1f && (!parent || parent->alpha.x == 1);
|
|
}
|
|
|
|
bool BasicIcon::isCursorInMenuItem()
|
|
{
|
|
if(quad)
|
|
return quad->isCoordinateInside(core->mouse.position);
|
|
return AquariaMenuItem::isCursorInMenuItem();
|
|
}
|
|
|
|
void BasicIcon::onUpdate(float dt)
|
|
{
|
|
AquariaMenuItem::onUpdate(dt);
|
|
|
|
// Autoscroll if selecting icon outside of screen
|
|
if(hasFocus() && dsq->modSelectorScr && !_isRecCall)
|
|
{
|
|
Vector pos = getRealPosition();
|
|
if(pos.y < 20 || pos.y > 580)
|
|
{
|
|
if(pos.y < 300)
|
|
dsq->modSelectorScr->move(5, true);
|
|
else
|
|
dsq->modSelectorScr->move(-5, true);
|
|
_isRecCall = true;
|
|
core->run(FRAME_TIME); // HACK: this is necessary to correctly position the mouse on the object after moving the panel
|
|
_isRecCall = false;
|
|
setFocus(true); // re-position mouse
|
|
}
|
|
}
|
|
|
|
if(!quad)
|
|
return;
|
|
|
|
if (hasInput() && quad->isCoordinateInside(core->mouse.position))
|
|
{
|
|
scale.interpolateTo(scaleBig, 0.1f);
|
|
const bool anyButton = core->mouse.buttons.left || core->mouse.buttons.right;
|
|
if (anyButton && !mouseDown)
|
|
{
|
|
mouseDown = true;
|
|
}
|
|
else if (!anyButton && mouseDown)
|
|
{
|
|
if(isGuiVisible()) // do not trigger if invis
|
|
onClick();
|
|
mouseDown = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
scale.interpolateTo(scaleNormal, 0.1f);
|
|
mouseDown = false;
|
|
}
|
|
}
|
|
|
|
void SubtitleIcon::onUpdate(float dt)
|
|
{
|
|
BasicIcon::onUpdate(dt);
|
|
|
|
if (dsq->modSelectorScr && isGuiVisible() && quad && quad->isCoordinateInside(core->mouse.position))
|
|
dsq->modSelectorScr->setSubText(label);
|
|
}
|
|
|
|
void BasicIcon::onClick()
|
|
{
|
|
dsq->sound->playSfx("denied");
|
|
}
|
|
|
|
MenuIcon::MenuIcon(int id) : SubtitleIcon(), iconId(id), cb(0), cb_data(0)
|
|
{
|
|
}
|
|
|
|
void MenuIcon::onClick()
|
|
{
|
|
dsq->sound->playSfx("click");
|
|
if(cb)
|
|
cb(iconId, cb_data);
|
|
}
|
|
|
|
|
|
ModIcon::ModIcon(): SubtitleIcon(), modId(-1)
|
|
{
|
|
}
|
|
|
|
void ModIcon::onClick()
|
|
{
|
|
dsq->sound->playSfx("click");
|
|
|
|
switch(modType)
|
|
{
|
|
case MODTYPE_MOD:
|
|
{
|
|
dsq->sound->playSfx("pet-on");
|
|
core->quitNestedMain();
|
|
dsq->modIsSelected = true;
|
|
dsq->selectedMod = modId;
|
|
break;
|
|
}
|
|
|
|
case MODTYPE_PATCH:
|
|
{
|
|
#ifdef AQUARIA_DEMO
|
|
dsq->sound->playSfx("denied");
|
|
core->quitNestedMain();
|
|
dsq->modIsSelected = true; // HACK: trigger nag screen
|
|
dsq->selectedMod = -1;
|
|
break;
|
|
#endif
|
|
|
|
bool on = false;
|
|
for(size_t i = 0; i < dsq->activePatches.size(); ++i)
|
|
if(dsq->activePatches[i] == fname)
|
|
{
|
|
on = true;
|
|
break;
|
|
}
|
|
|
|
if(on)
|
|
{
|
|
dsq->sound->playSfx("pet-off");
|
|
dsq->disablePatch(fname);
|
|
}
|
|
else
|
|
{
|
|
dsq->sound->playSfx("pet-on");
|
|
dsq->activatePatch(fname);
|
|
}
|
|
updateStatus();
|
|
break;
|
|
}
|
|
|
|
default:
|
|
errorLog("void ModIcon::onClick() -- unknown modType");
|
|
}
|
|
}
|
|
|
|
void ModIcon::loadEntry(const ModEntry& entry)
|
|
{
|
|
modId = entry.id;
|
|
modType = entry.type;
|
|
fname = entry.path;
|
|
|
|
std::string texToLoad = entry.path + "/" + "mod-icon";
|
|
|
|
texToLoad = dsq->mod.getBaseModPath() + texToLoad;
|
|
|
|
if(!quad)
|
|
useQuad(texToLoad);
|
|
quad->setWidthHeight(MOD_ICON_SIZE, MOD_ICON_SIZE);
|
|
|
|
XMLDocument d;
|
|
|
|
dsq->mod.loadModXML(&d, entry.path);
|
|
|
|
std::string ds = dsq->continuity.stringBank.get(2009);
|
|
|
|
XMLElement *top = d.FirstChildElement("AquariaMod");
|
|
if (top)
|
|
{
|
|
XMLElement *desc = top->FirstChildElement("Description");
|
|
if (desc)
|
|
{
|
|
if (desc->Attribute("text"))
|
|
{
|
|
ds = desc->Attribute("text");
|
|
}
|
|
}
|
|
XMLElement *fullname = top->FirstChildElement("Fullname");
|
|
if (fullname)
|
|
{
|
|
if (fullname->Attribute("text"))
|
|
{
|
|
modname = fullname->Attribute("text");
|
|
if (modname.size() > 60)
|
|
modname.resize(60);
|
|
}
|
|
}
|
|
}
|
|
|
|
label = "--[ " + modname + " ]--\n" + ds;
|
|
|
|
updateStatus();
|
|
}
|
|
|
|
void ModIcon::updateStatus()
|
|
{
|
|
if(modType == MODTYPE_PATCH)
|
|
{
|
|
if(dsq->isPatchActive(fname))
|
|
{
|
|
// enabled
|
|
quad->color.interpolateTo(Vector(1,1,1), 0.1f);
|
|
alpha.interpolateTo(1, 0.2f);
|
|
scaleNormal = Vector(1,1);
|
|
}
|
|
else
|
|
{
|
|
// disabled
|
|
quad->color.interpolateTo(Vector(0.5f, 0.5f, 0.5f), 0.1f);
|
|
alpha.interpolateTo(0.6f, 0.2f);
|
|
scaleNormal = Vector(0.8f,0.8f);
|
|
}
|
|
scaleBig = scaleNormal * 1.1f;
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef BBGE_BUILD_VFS
|
|
|
|
|
|
ModIconOnline::ModIconOnline()
|
|
: SubtitleIcon(), pb(0), extraIcon(0), statusIcon(0), clickable(true), pkgtype(MPT_MOD), hasUpdate(false)
|
|
{
|
|
label = desc;
|
|
}
|
|
|
|
bool ModIconOnline::hasPkgOnDisk()
|
|
{
|
|
if(localname.empty())
|
|
return false;
|
|
std::string modfile = dsq->mod.getBaseModPath() + localname + ".aqmod";
|
|
return exists(modfile.c_str(), false, true);
|
|
}
|
|
|
|
// return true if the desired texture could be set
|
|
bool ModIconOnline::fixIcon()
|
|
{
|
|
bool result = false;
|
|
if(exists(iconfile, false, true))
|
|
{
|
|
if(quad)
|
|
{
|
|
quad->fadeAlphaWithLife = true;
|
|
quad->setLife(1);
|
|
quad->setDecayRate(2);
|
|
quad = 0;
|
|
}
|
|
result = useQuad(iconfile);
|
|
}
|
|
if(!quad)
|
|
{
|
|
//useQuad("bitblot/logo");
|
|
int i = (rand() % 7) + 1;
|
|
std::stringstream ss;
|
|
ss << "fish-000" << i;
|
|
useQuad(ss.str());
|
|
}
|
|
|
|
quad->alpha = 0.001;
|
|
quad->setWidthHeight(MOD_ICON_SIZE, MOD_ICON_SIZE);
|
|
quad->alpha.interpolateTo(1, 0.5f);
|
|
|
|
if(!extraIcon && pkgtype == MPT_PATCH)
|
|
{
|
|
Vector pos(-MOD_ICON_SIZE/2 + MINI_ICON_SIZE/2, MOD_ICON_SIZE/2 - MINI_ICON_SIZE/2);
|
|
extraIcon = new Quad("modselect/ico_patch", pos);
|
|
extraIcon->setWidthHeight(MINI_ICON_SIZE, MINI_ICON_SIZE);
|
|
quad->addChild(extraIcon, PM_POINTER);
|
|
}
|
|
|
|
if(statusIcon)
|
|
{
|
|
statusIcon->fadeAlphaWithLife = true;
|
|
statusIcon->setLife(1);
|
|
statusIcon->setDecayRate(2);
|
|
statusIcon = 0;
|
|
}
|
|
|
|
if(!statusIcon)
|
|
{
|
|
Vector pos(MOD_ICON_SIZE/2 - MINI_ICON_SIZE/2, MOD_ICON_SIZE/2 - MINI_ICON_SIZE/2);
|
|
if(dsq->modIsKnown(localname))
|
|
{
|
|
// installed manually?
|
|
if(!hasPkgOnDisk())
|
|
{
|
|
statusIcon = new Quad("modselect/ico_locked", pos);
|
|
}
|
|
else if(hasUpdate)
|
|
{
|
|
statusIcon = new Quad("modselect/ico_update", pos);
|
|
statusIcon->alpha.interpolateTo(0.5f, 0.5f, -1, true, true);
|
|
}
|
|
else
|
|
statusIcon = new Quad("modselect/ico_check", pos);
|
|
}
|
|
|
|
if(statusIcon)
|
|
{
|
|
statusIcon->setWidthHeight(MINI_ICON_SIZE, MINI_ICON_SIZE);
|
|
quad->addChild(statusIcon, PM_POINTER);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
void ModIconOnline::onClick()
|
|
{
|
|
dsq->sound->playSfx("click");
|
|
|
|
#ifdef AQUARIA_DEMO
|
|
core->quitNestedMain();
|
|
dsq->modIsSelected = true; // HACK: trigger nag screen
|
|
dsq->selectedMod = -1;
|
|
return;
|
|
#endif
|
|
|
|
bool success = false;
|
|
|
|
if(clickable && !packageUrl.empty())
|
|
{
|
|
bool proceed = true;
|
|
if(pkgtype == MPT_MOD || pkgtype == MPT_PATCH)
|
|
{
|
|
if(dsq->modIsKnown(localname))
|
|
{
|
|
mouseDown = false; // HACK: do this here else stack overflow!
|
|
if(hasPkgOnDisk())
|
|
{
|
|
if(hasUpdate)
|
|
proceed = dsq->confirm(dsq->continuity.stringBank.get(2024));
|
|
else
|
|
proceed = dsq->confirm(dsq->continuity.stringBank.get(2025));
|
|
}
|
|
else
|
|
{
|
|
dsq->confirm(dsq->continuity.stringBank.get(2026), "", true);
|
|
proceed = false;
|
|
}
|
|
|
|
}
|
|
|
|
if(proceed && confirmStr.length())
|
|
{
|
|
mouseDown = false; // HACK: do this here else stack overflow!
|
|
dsq->sound->playSfx("spirit-beacon");
|
|
proceed = dsq->confirm(confirmStr);
|
|
}
|
|
|
|
if(proceed)
|
|
{
|
|
moddl.GetMod(packageUrl, localname);
|
|
setDownloadProgress(0);
|
|
success = true;
|
|
clickable = false;
|
|
}
|
|
else
|
|
success = true; // we didn't want, anyway
|
|
}
|
|
else if(pkgtype == MPT_WEBLINK)
|
|
{
|
|
mouseDown = false;
|
|
proceed = dsq->confirm(dsq->continuity.stringBank.get(2034));
|
|
if(proceed)
|
|
{
|
|
openURL(packageUrl);
|
|
success = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(!success)
|
|
{
|
|
SubtitleIcon::onClick(); // denied
|
|
}
|
|
}
|
|
|
|
void ModIconOnline::setDownloadProgress(float p, float barheight /* = 20 */)
|
|
{
|
|
if(p >= 0 && p <= 1)
|
|
{
|
|
if(!pb)
|
|
{
|
|
pb = new JuicyProgressBar;
|
|
addChild(pb, PM_POINTER);
|
|
pb->width = quad->width;
|
|
pb->height = 0;
|
|
pb->alpha = 0;
|
|
}
|
|
|
|
if(barheight != pb->height)
|
|
{
|
|
pb->height = barheight;
|
|
pb->width = quad->width;
|
|
pb->position = Vector(0, (quad->height - pb->height + 1) / 2); // +1 skips a pixel row and looks better
|
|
}
|
|
|
|
pb->alpha.interpolateTo(1, 0.2f);
|
|
pb->progress(p);
|
|
}
|
|
else if(pb)
|
|
{
|
|
pb->fadeAlphaWithLife = true;
|
|
pb->setLife(1);
|
|
pb->setDecayRate(2);
|
|
pb = 0;
|
|
}
|
|
}
|
|
|
|
#endif // BBGE_BUILD_VFS
|
|
|
|
MenuBasicBar::MenuBasicBar()
|
|
{
|
|
setTexture("modselect/bar");
|
|
repeatTextureToFill(true);
|
|
shareAlphaWithChildren = false;
|
|
}
|
|
|
|
void MenuBasicBar::init()
|
|
{
|
|
}
|
|
|
|
void MenuIconBar::init()
|
|
{
|
|
MenuIcon *ico;
|
|
int y = (-height / 2) - 35;
|
|
|
|
|
|
ico = new MenuIcon(0);
|
|
ico->label = dsq->continuity.stringBank.get(2027);
|
|
ico->useQuad("modselect/installed");
|
|
y += ico->quad->height;
|
|
ico->position = Vector(0, y);
|
|
add(ico);
|
|
dsq->modSelectorScr->modsIcon = ico; // HACK
|
|
|
|
MenuIcon *prev = ico;
|
|
ico = new MenuIcon(1);
|
|
ico->label = dsq->continuity.stringBank.get(2028);
|
|
ico->useQuad("modselect/patches");
|
|
y += ico->quad->height;
|
|
ico->position = Vector(0, y);
|
|
ico->setDirMove(DIR_UP, prev);
|
|
prev->setDirMove(DIR_DOWN, ico);
|
|
add(ico);
|
|
|
|
prev = ico;
|
|
ico = new MenuIcon(2);
|
|
ico->label = dsq->continuity.stringBank.get(2029);
|
|
ico->useQuad("modselect/download");
|
|
y += ico->quad->height;
|
|
ico->position = Vector(0, y);
|
|
ico->setDirMove(DIR_UP, prev);
|
|
prev->setDirMove(DIR_DOWN, ico);
|
|
add(ico);
|
|
dsq->modSelectorScr->globeIcon = ico; // HACK
|
|
|
|
prev = ico;
|
|
ico = new MenuIcon(3);
|
|
ico->label = dsq->continuity.stringBank.get(2030);
|
|
ico->useQuad("modselect/exit");
|
|
ico->repeatTextureToFill(false);
|
|
y += ico->quad->height;
|
|
ico->position = Vector(0, y);
|
|
ico->setDirMove(DIR_UP, prev);
|
|
prev->setDirMove(DIR_DOWN, ico);
|
|
add(ico);
|
|
}
|
|
|
|
void MenuIconBar::add(MenuIcon *ico)
|
|
{
|
|
ico->quad->setWidthHeight(width, width);
|
|
ico->followCamera = 1;
|
|
icons.push_back(ico);
|
|
addChild(ico, PM_POINTER);
|
|
}
|
|
|
|
IconGridPanel::IconGridPanel()
|
|
: spacing(0), y(0), x(0)
|
|
{
|
|
shareAlphaWithChildren = false; // patch selection icons need their own alpha, use fade() instead
|
|
alphaMod = 0.01f;
|
|
color = 0;
|
|
}
|
|
|
|
void IconGridPanel::add(BasicIcon *obj)
|
|
{
|
|
const int xoffs = (-width / 2) + (obj->quad->width / 2) + spacing;
|
|
const int yoffs = (-height / 2) + obj->quad->height + spacing;
|
|
const int xlim = width - obj->quad->width;
|
|
Vector newpos;
|
|
|
|
if(x >= xlim)
|
|
{
|
|
x = 0;
|
|
y += (obj->quad->height + spacing);
|
|
}
|
|
|
|
newpos = Vector(x + xoffs, y + yoffs);
|
|
x += (obj->quad->width + spacing);
|
|
|
|
obj->position = newpos;
|
|
addChild(obj, PM_POINTER);
|
|
}
|
|
|
|
void IconGridPanel::fade(bool in, bool sc)
|
|
{
|
|
const float t = 0.2f;
|
|
Vector newalpha;
|
|
if(in)
|
|
{
|
|
newalpha.x = 1;
|
|
if(sc)
|
|
scale.interpolateTo(Vector(1, 1), t);
|
|
}
|
|
else
|
|
{
|
|
newalpha.x = 0;
|
|
if(sc)
|
|
scale.interpolateTo(Vector(0.8f, 0.8f), t);
|
|
}
|
|
alpha.interpolateTo(newalpha, t);
|
|
|
|
for(Children::iterator it = children.begin(); it != children.end(); ++it)
|
|
{
|
|
(*it)->alpha.interpolateTo(newalpha, t);
|
|
|
|
if(in)
|
|
if(ModIcon *ico = dynamic_cast<ModIcon*>(*it))
|
|
ico->updateStatus();
|
|
}
|
|
}
|
|
|