Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
30977b7913
@ -17,11 +17,11 @@
|
||||
|
||||
|
||||
// motion_blur.frag
|
||||
#version 330
|
||||
|
||||
// The actual boost amount (which linearly scales the blur to be shown).
|
||||
// should be in the range [0.0, 1.0], though a larger value might make
|
||||
// the blurring too string. Atm we are using [0, 0.5].
|
||||
#version 330 compatibility
|
||||
uniform float boost_amount;
|
||||
|
||||
// The color buffer to use.
|
||||
@ -41,6 +41,7 @@ uniform float mask_radius;
|
||||
// Maximum height of texture used
|
||||
uniform float max_tex_height;
|
||||
|
||||
in vec2 uv;
|
||||
out vec4 FragColor;
|
||||
|
||||
// Number of samples used for blurring
|
||||
@ -48,7 +49,7 @@ out vec4 FragColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texcoords = gl_TexCoord[0].st;
|
||||
vec2 texcoords = uv;
|
||||
|
||||
// Sample the color buffer
|
||||
vec3 color = texture(color_buffer, texcoords).rgb;
|
||||
|
@ -3,7 +3,7 @@ set(STK_SOURCES
|
||||
src/achievements/achievement.cpp
|
||||
src/achievements/achievement_info.cpp
|
||||
src/achievements/achievements_manager.cpp
|
||||
src/achievements/achievements_slot.cpp
|
||||
src/achievements/achievements_status.cpp
|
||||
src/addons/addon.cpp
|
||||
src/addons/addons_manager.cpp
|
||||
src/addons/news_manager.cpp
|
||||
@ -64,6 +64,7 @@ src/graphics/stars.cpp
|
||||
src/graphics/stkanimatedmesh.cpp
|
||||
src/graphics/stkbillboard.cpp
|
||||
src/graphics/stkmesh.cpp
|
||||
src/graphics/stkmeshscenenode.cpp
|
||||
src/graphics/sun.cpp
|
||||
src/graphics/water.cpp
|
||||
src/graphics/wind.cpp
|
||||
@ -328,7 +329,7 @@ set(STK_HEADERS
|
||||
src/achievements/achievement.hpp
|
||||
src/achievements/achievement_info.hpp
|
||||
src/achievements/achievements_manager.hpp
|
||||
src/achievements/achievements_slot.hpp
|
||||
src/achievements/achievements_status.hpp
|
||||
src/addons/addon.hpp
|
||||
src/addons/addons_manager.hpp
|
||||
src/addons/news_manager.hpp
|
||||
@ -395,6 +396,7 @@ src/graphics/stars.hpp
|
||||
src/graphics/stkanimatedmesh.hpp
|
||||
src/graphics/stkbillboard.hpp
|
||||
src/graphics/stkmesh.hpp
|
||||
src/graphics/stkmeshscenenode.hpp
|
||||
src/graphics/sun.hpp
|
||||
src/graphics/water.hpp
|
||||
src/graphics/wind.hpp
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include "achievements/achievement_info.hpp"
|
||||
#include "guiengine/dialog_queue.hpp"
|
||||
#include "io/utf_writer.hpp"
|
||||
#include "states_screens/dialogs/notification_dialog.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
@ -31,28 +32,46 @@
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
|
||||
// ============================================================================
|
||||
|
||||
Achievement::Achievement(const AchievementInfo * info)
|
||||
:m_achievement_info(info)
|
||||
{
|
||||
m_id = info->getID();
|
||||
m_achieved = false;
|
||||
}
|
||||
} // Achievement
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
Achievement::~Achievement()
|
||||
{
|
||||
} // ~Achievement
|
||||
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Loads the value from an XML node.
|
||||
* \param input*/
|
||||
void Achievement::load(const XMLNode *node)
|
||||
{
|
||||
node->get("id", &m_id );
|
||||
node->get("achieved", &m_achieved);
|
||||
} // load
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Saves the achievement status to a file.
|
||||
* \param Output stream.
|
||||
*/
|
||||
void Achievement::save(UTFWriter &out)
|
||||
{
|
||||
out << L" <achievement id=\"" << m_id << L"\" "
|
||||
<< L"achieved=\"" << m_achieved << "\"";
|
||||
} // save
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void Achievement::onRaceEnd()
|
||||
{
|
||||
if(m_achievement_info->needsResetAfterRace())
|
||||
this->reset();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
void Achievement::check()
|
||||
{
|
||||
if(m_achieved)
|
||||
@ -71,105 +90,120 @@ void Achievement::check()
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor for a SingleAchievement.
|
||||
*/
|
||||
SingleAchievement::SingleAchievement(const AchievementInfo * info)
|
||||
: Achievement(info)
|
||||
{
|
||||
m_progress = 0;
|
||||
m_achieved = false;
|
||||
}
|
||||
} // SingleAchievement
|
||||
|
||||
// ============================================================================
|
||||
void SingleAchievement::load(XMLNode * input)
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Loads the state from an xml node.
|
||||
* \param node The XML data.
|
||||
*/
|
||||
void SingleAchievement::load(const XMLNode *node)
|
||||
{
|
||||
std::string achieved("");
|
||||
input->get("achieved", &achieved);
|
||||
if(achieved == "true")
|
||||
{
|
||||
m_achieved = true;
|
||||
return;
|
||||
}
|
||||
input->get("value", &m_progress);
|
||||
}
|
||||
// ============================================================================
|
||||
void SingleAchievement::save(std::ofstream & out)
|
||||
Achievement::load(node);
|
||||
if (!isAchieved())
|
||||
node->get("progress", &m_progress);
|
||||
} // load
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Save the state to a file. The progress is only saved if the achievement
|
||||
* has not been achieved yet.
|
||||
* \param out The output file.
|
||||
*/
|
||||
void SingleAchievement::save(UTFWriter &out)
|
||||
{
|
||||
out << " <achievement id=\"" << m_id << "\" "
|
||||
<< "achieved=\"" << StringUtils::toString(m_achieved) << "\"";
|
||||
if(!m_achieved)
|
||||
Achievement::save(out);
|
||||
if (!m_achieved)
|
||||
{
|
||||
out << " value=\"" << StringUtils::toString(m_progress) << "\"";
|
||||
out << L" progress=\"" << m_progress << L"\"";
|
||||
}
|
||||
out << "/>\n";
|
||||
out << L"/>\n";
|
||||
} // save
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Resets the challenge. Calls if necessary (i.e. if a challenge needs to
|
||||
* be fulfilled in a single race).
|
||||
*/
|
||||
void SingleAchievement::reset()
|
||||
{
|
||||
m_progress = 0;
|
||||
} // reset
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Adds a value to this counter.
|
||||
* \param increase Value to add.
|
||||
*/
|
||||
void SingleAchievement::increase(int increase)
|
||||
{
|
||||
m_progress += increase;
|
||||
check();
|
||||
}
|
||||
} // increase
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Returns a "k/n" string indicating how much of an achievement was achieved.
|
||||
*/
|
||||
irr::core::stringw SingleAchievement::getProgressAsString()
|
||||
{
|
||||
return StringUtils::toWString(m_progress) + "/" + StringUtils::toWString(((SingleAchievementInfo *) m_achievement_info)->getGoalValue());
|
||||
}
|
||||
// The info class returns the goal value
|
||||
return StringUtils::toWString(m_progress) + "/"
|
||||
+getInfo()->toString();
|
||||
} // getProgressAsString
|
||||
|
||||
// ============================================================================
|
||||
|
||||
/** Constructor for a MapAchievement.
|
||||
*/
|
||||
MapAchievement::MapAchievement(const AchievementInfo * info)
|
||||
: Achievement(info)
|
||||
{
|
||||
}
|
||||
} // MapAchievement
|
||||
|
||||
// ============================================================================
|
||||
void MapAchievement::load(XMLNode * input)
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Loads the status from an XML node.
|
||||
* \param node The XML data to load the status from.
|
||||
*/
|
||||
void MapAchievement::load(const XMLNode *node)
|
||||
{
|
||||
bool achieved = false;
|
||||
input->get("achieved", &achieved);
|
||||
if(achieved)
|
||||
Achievement::load(node);
|
||||
for (unsigned int i = 0; i < node->getNumNodes(); i++)
|
||||
{
|
||||
m_achieved = true;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<XMLNode*> xml_entries;
|
||||
input->getNodes("entry", xml_entries);
|
||||
for (unsigned int n=0; n < xml_entries.size(); n++)
|
||||
{
|
||||
std::string key("");
|
||||
xml_entries[n]->get("key", &key);
|
||||
int value(0);
|
||||
xml_entries[n]->get("value", &value);
|
||||
const XMLNode *n = node->getNode(i);
|
||||
std::string key = n->getName();
|
||||
int value = 0;
|
||||
n->get("value", &value);
|
||||
m_progress_map[key] = value;
|
||||
}
|
||||
}
|
||||
} // load
|
||||
|
||||
// ============================================================================
|
||||
void MapAchievement::save(std::ofstream & out)
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Saves the status of this achievement to a file.
|
||||
* \param out The file to write the state to.
|
||||
*/
|
||||
void MapAchievement::save(UTFWriter &out)
|
||||
{
|
||||
out << " <achievement id=\"" << m_id << "\" achieved=\""
|
||||
<< StringUtils::toString(m_achieved) << "\">\n";
|
||||
if(!m_achieved)
|
||||
Achievement::save(out);
|
||||
if (isAchieved())
|
||||
{
|
||||
std::map<std::string, int>::iterator i;
|
||||
for ( i = m_progress_map.begin(); i != m_progress_map.end(); ++i )
|
||||
{
|
||||
out << " <entry key=\"" << i->first.c_str()
|
||||
<< "\" value=\"" << StringUtils::toString(i->second)
|
||||
<< "\"/>\n";
|
||||
}
|
||||
out << "/>\n";
|
||||
return;
|
||||
}
|
||||
out << ">\n";
|
||||
std::map<std::string, int>::iterator i;
|
||||
for (i = m_progress_map.begin(); i != m_progress_map.end(); ++i)
|
||||
{
|
||||
out << " <" << i->first
|
||||
<< " value=\"" << i->second << "\"/>\n";
|
||||
}
|
||||
out << " </achievement>\n";
|
||||
} // save
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int MapAchievement::getValue(const std::string & key)
|
||||
{
|
||||
@ -178,8 +212,7 @@ int MapAchievement::getValue(const std::string & key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
void MapAchievement::reset()
|
||||
{
|
||||
std::map<std::string, int>::iterator iter;
|
||||
@ -189,27 +222,27 @@ void MapAchievement::reset()
|
||||
}
|
||||
} // reset
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
void MapAchievement::increase(const std::string & key, int increase)
|
||||
{
|
||||
if ( m_progress_map.find(key) != m_progress_map.end())
|
||||
if (m_progress_map.find(key) != m_progress_map.end())
|
||||
{
|
||||
m_progress_map[key] += increase;
|
||||
check();
|
||||
}
|
||||
else
|
||||
m_progress_map[key] = increase;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
irr::core::stringw MapAchievement::getProgressAsString()
|
||||
{
|
||||
int progress(0);
|
||||
int goal(0);
|
||||
const std::map<std::string, int> goal_values = ((MapAchievementInfo *) m_achievement_info)->getGoalValues();
|
||||
{
|
||||
int progress = 0;
|
||||
std::map<std::string, int>::const_iterator iter;
|
||||
for ( iter = goal_values.begin(); iter != goal_values.end(); ++iter ) {
|
||||
goal += iter->second;
|
||||
progress += m_progress_map[iter->first];
|
||||
for ( iter = m_progress_map.begin(); iter != m_progress_map.end(); ++iter)
|
||||
{
|
||||
progress += iter->second;
|
||||
}
|
||||
return StringUtils::toWString(progress) + "/" + StringUtils::toWString(goal);
|
||||
return StringUtils::toWString(progress) + "/" + getInfo()->toString();
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 Glenn De Jonghe
|
||||
// Copyright (C) 2013-2014 Glenn De Jonghe
|
||||
// 2014 Joerg Henrichs
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
@ -22,46 +23,69 @@
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <irrString.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "io/xml_node.hpp"
|
||||
|
||||
class UTFWriter;
|
||||
class XMLNode;
|
||||
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* \brief
|
||||
* \ingroup
|
||||
*/
|
||||
/** This is the base class for any achievement. It allows achievement status
|
||||
* to be saved, and detects when an achievement is fulfilled.
|
||||
* \ingroup achievements
|
||||
*/
|
||||
class AchievementInfo;
|
||||
|
||||
class Achievement
|
||||
{
|
||||
protected:
|
||||
uint32_t m_id;
|
||||
bool m_achieved;
|
||||
const AchievementInfo * m_achievement_info;
|
||||
void check ();
|
||||
/** The id of this achievement. */
|
||||
uint32_t m_id;
|
||||
|
||||
/** True if this achievement has been achieved. */
|
||||
bool m_achieved;
|
||||
|
||||
/** A pointer to the corresponding AchievementInfo instance. */
|
||||
const AchievementInfo *m_achievement_info;
|
||||
|
||||
void check();
|
||||
|
||||
public:
|
||||
Achievement (const AchievementInfo * info);
|
||||
virtual ~Achievement ();
|
||||
uint32_t getID () const { return m_id; }
|
||||
const AchievementInfo * getInfo () const { return m_achievement_info;}
|
||||
virtual void load (XMLNode * input) = 0;
|
||||
virtual void save (std::ofstream & out) = 0;
|
||||
virtual void reset () = 0;
|
||||
void onRaceEnd ();
|
||||
void setAchieved () {m_achieved = true; };
|
||||
virtual irr::core::stringw getProgressAsString () = 0;
|
||||
|
||||
enum AchievementType
|
||||
{
|
||||
AT_SINGLE,
|
||||
AT_MAP
|
||||
};
|
||||
|
||||
Achievement(const AchievementInfo * info);
|
||||
virtual ~Achievement ();
|
||||
virtual void load (const XMLNode *node) ;
|
||||
virtual void save (UTFWriter &out) ;
|
||||
virtual void reset () = 0;
|
||||
virtual irr::core::stringw getProgressAsString() = 0;
|
||||
void onRaceEnd();
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the id of this achievement. */
|
||||
uint32_t getID() const { return m_id; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the AchievementInfo for this achievement. */
|
||||
const AchievementInfo * getInfo() const { return m_achievement_info; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Sets this achievement to be fulfilled. */
|
||||
void setAchieved() { m_achieved = true; };
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns if this achievement has been fulfilled. */
|
||||
bool isAchieved() const { return m_achieved; }
|
||||
|
||||
}; // class Achievement
|
||||
|
||||
// ============================================================================
|
||||
/** This is a base class for an achievement that counts how often an event
|
||||
* happened, and triggers the achievement to be fulfilled when a certain
|
||||
* goal value is reached.
|
||||
* \ingroup achievements
|
||||
*/
|
||||
class SingleAchievement : public Achievement
|
||||
{
|
||||
protected:
|
||||
@ -71,27 +95,34 @@ public:
|
||||
SingleAchievement (const AchievementInfo * info);
|
||||
virtual ~SingleAchievement () {};
|
||||
|
||||
void load (XMLNode * input);
|
||||
void load (const XMLNode *node);
|
||||
int getValue () const { return m_progress; }
|
||||
void save (std::ofstream & out);
|
||||
void save (UTFWriter &out);
|
||||
void increase (int increase = 1);
|
||||
void reset ();
|
||||
virtual irr::core::stringw getProgressAsString ();
|
||||
}; // class SingleAchievement
|
||||
|
||||
// ============================================================================
|
||||
/** This achievement can keep track of a set of key-value pairs. Fulfillment is
|
||||
* triggered when all values defined in the data/achievements.xml file have
|
||||
* been reached.
|
||||
* \ingroup achievements
|
||||
*/
|
||||
class MapAchievement : public Achievement
|
||||
{
|
||||
protected:
|
||||
/** The map of key-value pairs. */
|
||||
std::map<std::string, int> m_progress_map;
|
||||
|
||||
public:
|
||||
MapAchievement (const AchievementInfo * info);
|
||||
virtual ~MapAchievement () {};
|
||||
|
||||
void load (XMLNode * input);
|
||||
void load (const XMLNode *node);
|
||||
int getValue (const std::string & key);
|
||||
void increase (const std::string & key, int increase = 1);
|
||||
void save (std::ofstream & out);
|
||||
void save (UTFWriter &out);
|
||||
void reset ();
|
||||
virtual irr::core::stringw getProgressAsString ();
|
||||
}; // class MapAchievement
|
||||
|
@ -25,27 +25,42 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
// ============================================================================
|
||||
|
||||
AchievementInfo::AchievementInfo(const XMLNode * input)
|
||||
{
|
||||
input->get("id", &m_id);
|
||||
input->get("title", &m_title);
|
||||
input->get("description", &m_description);
|
||||
|
||||
std::string reset_after_race("");
|
||||
input->get("reset_after_race", &reset_after_race);
|
||||
m_reset_after_race = reset_after_race == "true";
|
||||
|
||||
}
|
||||
m_reset_after_race = false;
|
||||
m_id = 0;
|
||||
m_title = "";
|
||||
m_description = "";
|
||||
bool all;
|
||||
all = input->get("id", &m_id ) &&
|
||||
input->get("title", &m_title ) &&
|
||||
input->get("description", &m_description );
|
||||
if (!all)
|
||||
{
|
||||
Log::error("AchievementInfo",
|
||||
"Not all necessary values for achievement defined.");
|
||||
Log::error("AchievementInfo",
|
||||
"ID %d title '%s' description '%s'", m_id, m_title.c_str(),
|
||||
m_description.c_str());
|
||||
}
|
||||
input->get("reset-after-race", &m_reset_after_race);
|
||||
} // AchievementInfo
|
||||
|
||||
// ============================================================================
|
||||
SingleAchievementInfo::SingleAchievementInfo(const XMLNode * input)
|
||||
: AchievementInfo(input)
|
||||
{
|
||||
input->get("goal", &m_goal_value);
|
||||
}
|
||||
} // SingleAchievementInfo
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
irr::core::stringw SingleAchievementInfo::toString() const
|
||||
{
|
||||
return StringUtils::toWString(m_goal_value);
|
||||
} // toString
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
bool SingleAchievementInfo::checkCompletion(Achievement * achievement) const
|
||||
{
|
||||
SingleAchievement * single_achievement = (SingleAchievement *) achievement;
|
||||
@ -71,13 +86,25 @@ MapAchievementInfo::MapAchievementInfo(const XMLNode * input)
|
||||
if(m_goal_values.size() != xml_entries.size())
|
||||
Log::error("MapAchievementInfo","Duplicate keys for the entries of a MapAchievement found.");
|
||||
}
|
||||
// ----------------------------------------------------------------------------
|
||||
irr::core::stringw MapAchievementInfo::toString() const
|
||||
{
|
||||
int count = 0;
|
||||
std::map<std::string, int>::const_iterator iter;
|
||||
for (iter = m_goal_values.begin(); iter != m_goal_values.end(); iter++)
|
||||
{
|
||||
count += iter->second;
|
||||
}
|
||||
return StringUtils::toWString(count);
|
||||
} // toString
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
bool MapAchievementInfo::checkCompletion(Achievement * achievement) const
|
||||
{
|
||||
MapAchievement * map_achievement = (MapAchievement *) achievement;
|
||||
std::map<std::string, int>::const_iterator iter;
|
||||
for ( iter = m_goal_values.begin(); iter != m_goal_values.end(); iter++ ) {
|
||||
for ( iter = m_goal_values.begin(); iter != m_goal_values.end(); iter++ )
|
||||
{
|
||||
if(map_achievement->getValue(iter->first) < iter->second)
|
||||
return false;
|
||||
}
|
||||
|
@ -21,65 +21,110 @@
|
||||
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <irrString.h>
|
||||
#include <string>
|
||||
#include "io/xml_node.hpp"
|
||||
#include "achievements/achievement.hpp"
|
||||
|
||||
#include <irrString.h>
|
||||
#include <string>
|
||||
|
||||
// ============================================================================
|
||||
|
||||
class Achievement;
|
||||
|
||||
/**
|
||||
* \brief
|
||||
* \ingroup
|
||||
/** This is the base class for storing the definition of an achievement, e.g.
|
||||
* title, description (which is common for all achievements), but also how
|
||||
* to achieve this achievement.
|
||||
* \ingroup achievements
|
||||
*/
|
||||
class AchievementInfo
|
||||
{
|
||||
protected:
|
||||
uint32_t m_id;
|
||||
/** The id of this Achievement. */
|
||||
uint32_t m_id;
|
||||
|
||||
/** The title of this achievement. */
|
||||
irr::core::stringw m_title;
|
||||
|
||||
/** The description of this achievement. */
|
||||
irr::core::stringw m_description;
|
||||
|
||||
/** True if the achievement needs to be reset after each race. */
|
||||
bool m_reset_after_race;
|
||||
|
||||
public:
|
||||
AchievementInfo (const XMLNode * input);
|
||||
virtual ~AchievementInfo () {};
|
||||
uint32_t getID () const { return m_id; }
|
||||
irr::core::stringw getDescription () const { return m_description; }
|
||||
irr::core::stringw getTitle () const { return m_title; }
|
||||
virtual Achievement::AchievementType getType () const = 0;
|
||||
virtual bool checkCompletion (Achievement * achievement) const = 0;
|
||||
bool needsResetAfterRace() const {return m_reset_after_race; }
|
||||
virtual Achievement::AchievementType getType() const = 0;
|
||||
virtual irr::core::stringw toString() const = 0;
|
||||
virtual bool checkCompletion(Achievement * achievement) const = 0;
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the id of this achievement. */
|
||||
uint32_t getID() const { return m_id; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the description of this achievement. */
|
||||
irr::core::stringw getDescription() const { return m_description; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the title of this achievement. */
|
||||
irr::core::stringw getTitle() const { return m_title; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool needsResetAfterRace() const { return m_reset_after_race; }
|
||||
}; // class AchievementInfo
|
||||
|
||||
|
||||
// ============================================================================
|
||||
/** This class stores the information about an achievement that count a
|
||||
* single value.
|
||||
*/
|
||||
class SingleAchievementInfo : public AchievementInfo
|
||||
{
|
||||
protected:
|
||||
private:
|
||||
/** Which value must be reached in order to achieve this achievement. */
|
||||
int m_goal_value;
|
||||
|
||||
public:
|
||||
SingleAchievementInfo (const XMLNode * input);
|
||||
virtual ~SingleAchievementInfo () {};
|
||||
int getGoalValue () const { return m_goal_value; }
|
||||
virtual bool checkCompletion (Achievement * achievement) const;
|
||||
|
||||
virtual Achievement::AchievementType getType() const { return Achievement::AT_SINGLE; };
|
||||
SingleAchievementInfo(const XMLNode * input);
|
||||
virtual ~SingleAchievementInfo() {};
|
||||
virtual irr::core::stringw toString() const;
|
||||
virtual bool checkCompletion(Achievement * achievement) const;
|
||||
// ------------------------------------------------------------------------
|
||||
int getGoalValue() const { return m_goal_value; }
|
||||
// ------------------------------------------------------------------------
|
||||
virtual Achievement::AchievementType getType() const
|
||||
{
|
||||
return Achievement::AT_SINGLE;
|
||||
} // getType
|
||||
}; // class SingleAchievementInfo
|
||||
|
||||
|
||||
// ============================================================================
|
||||
/** This class stores a set of key-value pairs.
|
||||
*/
|
||||
class MapAchievementInfo : public AchievementInfo
|
||||
{
|
||||
protected:
|
||||
|
||||
/** The target values needed to be reached. */
|
||||
std::map<std::string, int> m_goal_values;
|
||||
|
||||
public:
|
||||
MapAchievementInfo (const XMLNode * input);
|
||||
virtual ~MapAchievementInfo () {};
|
||||
int getGoalValue (const std::string & key) { return m_goal_values[key];}
|
||||
const std::map<std::string, int> & getGoalValues() const {return m_goal_values;}
|
||||
virtual bool checkCompletion (Achievement * achievement) const;
|
||||
virtual Achievement::AchievementType getType() const { return Achievement::AT_MAP; };
|
||||
MapAchievementInfo(const XMLNode * input);
|
||||
virtual ~MapAchievementInfo() {};
|
||||
virtual bool checkCompletion(Achievement * achievement) const;
|
||||
virtual irr::core::stringw toString() const;
|
||||
// ------------------------------------------------------------------------
|
||||
int getGoalValue(const std::string & key) { return m_goal_values[key]; }
|
||||
// ------------------------------------------------------------------------
|
||||
const std::map<std::string, int> & getGoalValues() const
|
||||
{
|
||||
return m_goal_values;
|
||||
} // getGoalValues
|
||||
// ------------------------------------------------------------------------
|
||||
virtual Achievement::AchievementType getType() const
|
||||
{
|
||||
return Achievement::AT_MAP;
|
||||
} // getType
|
||||
|
||||
}; // class MapAchievementInfo
|
||||
|
||||
#endif
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
#include "achievements/achievements_manager.hpp"
|
||||
|
||||
#include "achievements/achievement_info.hpp"
|
||||
#include "achievements/achievements_status.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/player_profile.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
@ -30,47 +32,30 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
static AchievementsManager* achievements_manager_singleton(NULL);
|
||||
AchievementsManager* AchievementsManager::m_achievements_manager = NULL;
|
||||
|
||||
AchievementsManager* AchievementsManager::get()
|
||||
{
|
||||
if (achievements_manager_singleton == NULL)
|
||||
achievements_manager_singleton = new AchievementsManager();
|
||||
return achievements_manager_singleton;
|
||||
}
|
||||
|
||||
void AchievementsManager::deallocate()
|
||||
{
|
||||
delete achievements_manager_singleton;
|
||||
achievements_manager_singleton = NULL;
|
||||
} // deallocate
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Constructor, which reads data/achievements.xml.
|
||||
*/
|
||||
AchievementsManager::AchievementsManager()
|
||||
{
|
||||
parseAssetFile();
|
||||
}
|
||||
} // AchievementsManager
|
||||
|
||||
|
||||
// ============================================================================
|
||||
void AchievementsManager::init()
|
||||
{
|
||||
parseUserConfigFile();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
AchievementsManager::~AchievementsManager()
|
||||
{
|
||||
save();
|
||||
m_slots.clearAndDeleteAll();
|
||||
std::map<uint32_t, AchievementInfo *>::iterator it;
|
||||
for ( it = m_achievements_info.begin(); it != m_achievements_info.end(); ++it ) {
|
||||
delete it->second;
|
||||
}
|
||||
m_achievements_info.clear();
|
||||
}
|
||||
} // ~AchievementsManager
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Parses the data/achievements.xml file and stores the information about
|
||||
* all achievements in its internal map.
|
||||
*/
|
||||
void AchievementsManager::parseAssetFile()
|
||||
{
|
||||
const std::string file_name = file_manager->getAsset("achievements.xml");
|
||||
@ -92,9 +77,10 @@ void AchievementsManager::parseAssetFile()
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("AchievementsManager::parseAchievements",
|
||||
"Non-existent achievement type. Skipping - "
|
||||
"definitely results in unwanted behaviour.");
|
||||
Log::error("AchievementsManager",
|
||||
"Non-existent achievement type '%s'. Skipping - "
|
||||
"definitely results in unwanted behaviour.",
|
||||
type.c_str());
|
||||
continue;
|
||||
}
|
||||
m_achievements_info[achievement_info->getID()] = achievement_info;
|
||||
@ -104,149 +90,56 @@ void AchievementsManager::parseAssetFile()
|
||||
"Multiple achievements with the same id!");
|
||||
|
||||
delete root;
|
||||
}
|
||||
} // parseAssetFile
|
||||
|
||||
|
||||
// ============================================================================
|
||||
void AchievementsManager::parseUserConfigFile()
|
||||
{
|
||||
const std::string filename=file_manager->getUserConfigFile("achievements.xml");
|
||||
XMLNode* root = file_manager->createXMLTree(filename);
|
||||
if(!root || root->getName() != "achievements")
|
||||
{
|
||||
Log::info("AchievementsManager",
|
||||
"Achievements file '%s' will be created.",filename.c_str());
|
||||
createSlotsIfNeeded();
|
||||
if (root) delete root;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<XMLNode*> xml_slots;
|
||||
root->getNodes("slot", xml_slots);
|
||||
for (unsigned int n=0; n < xml_slots.size(); n++)
|
||||
{
|
||||
AchievementsSlot * slot = new AchievementsSlot(xml_slots[n]);
|
||||
if(!slot->isValid())
|
||||
{
|
||||
Log::warn("AchievementsManager", "Found game slot with faulty or missing information. Discarding it.");
|
||||
delete slot;
|
||||
continue;
|
||||
}
|
||||
m_slots.push_back(slot);
|
||||
}
|
||||
delete root;
|
||||
} // load
|
||||
|
||||
|
||||
AchievementsSlot * AchievementsManager::createNewSlot(unsigned int id, bool online)
|
||||
{
|
||||
AchievementsSlot* slot = new AchievementsSlot(id, online);
|
||||
m_slots.push_back(slot);
|
||||
return slot;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Creates a slot for players that don't have one yet
|
||||
* \return true if any were created
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Create a new AchievementStatus object that stores all achievement status
|
||||
* information for a single player.
|
||||
* \param node The XML of saved data, or NULL if no saved data exists.
|
||||
*/
|
||||
void AchievementsManager::createSlotsIfNeeded()
|
||||
AchievementsStatus*
|
||||
AchievementsManager::createAchievementsStatus(const XMLNode *node)
|
||||
{
|
||||
bool something_changed = false;
|
||||
AchievementsStatus *status = new AchievementsStatus();
|
||||
|
||||
// make sure all players have at least one game slot associated
|
||||
for (unsigned int i=0; i<PlayerManager::get()->getNumPlayers(); i++)
|
||||
// First add all achievements, before restoring the saved data.
|
||||
std::map<uint32_t, AchievementInfo *>::const_iterator it;
|
||||
for (it = m_achievements_info.begin();
|
||||
it != m_achievements_info.end(); ++it)
|
||||
{
|
||||
const PlayerProfile *player = PlayerManager::get()->getPlayer(i);
|
||||
if (getSlot(player->getUniqueID(), false) == NULL )
|
||||
Achievement::AchievementType achievement_type = it->second->getType();
|
||||
Achievement * achievement;
|
||||
if (achievement_type == Achievement::AT_SINGLE)
|
||||
{
|
||||
createNewSlot(player->getUniqueID(), false);
|
||||
something_changed = true;
|
||||
achievement = new SingleAchievement(it->second);
|
||||
}
|
||||
else if (achievement_type == Achievement::AT_MAP)
|
||||
{
|
||||
achievement = new MapAchievement(it->second);
|
||||
}
|
||||
status->add(achievement);
|
||||
}
|
||||
|
||||
if(something_changed){
|
||||
save();
|
||||
}
|
||||
} // UnlockManager::createSlotsIfNeeded
|
||||
if (node)
|
||||
status->load(node);
|
||||
|
||||
return status;
|
||||
} // createAchievementStatus
|
||||
|
||||
// ============================================================================
|
||||
void AchievementsManager::save()
|
||||
{
|
||||
std::string filename = file_manager->getUserConfigFile("achievements.xml");
|
||||
|
||||
std::ofstream achievements_file(filename.c_str(), std::ios::out);
|
||||
|
||||
if (!achievements_file.is_open())
|
||||
{
|
||||
Log::warn("AchievementsManager::save",
|
||||
"Failed to open '%s' for writing, achievements won't be saved\n",
|
||||
filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
achievements_file << "<?xml version=\"1.0\"?>\n";
|
||||
achievements_file << "<achievements>\n";
|
||||
|
||||
for (unsigned int i = 0; i < m_slots.size(); i++)
|
||||
{
|
||||
m_slots[i].save(achievements_file);
|
||||
}
|
||||
|
||||
achievements_file << "</achievements>\n\n";
|
||||
achievements_file.close();
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// ----------------------------------------------------------------------------
|
||||
void AchievementsManager::onRaceEnd()
|
||||
{
|
||||
//reset all values that need to be reset
|
||||
m_active_slot->onRaceEnd();
|
||||
}
|
||||
PlayerManager::get()->getCurrentPlayer()
|
||||
->getAchievementsStatus()->onRaceEnd();
|
||||
} // onRaceEnd
|
||||
|
||||
// ============================================================================
|
||||
AchievementsSlot * AchievementsManager::getSlot(unsigned int id, bool online)
|
||||
// ----------------------------------------------------------------------------
|
||||
AchievementInfo * AchievementsManager::getAchievementInfo(uint32_t id) const
|
||||
{
|
||||
for(unsigned int i = 0; i < m_slots.size(); i++)
|
||||
{
|
||||
if(m_slots[i].isOnline() == online && m_slots[i].getID() == id)
|
||||
{
|
||||
return m_slots.get(i);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
void AchievementsManager::updateCurrentPlayer()
|
||||
{
|
||||
if(Online::CurrentUser::get()->isRegisteredUser())
|
||||
{
|
||||
m_active_slot = getSlot(Online::CurrentUser::get()->getID(), true);
|
||||
if(m_active_slot == NULL)
|
||||
{
|
||||
m_active_slot = createNewSlot(Online::CurrentUser::get()->getID(), true);
|
||||
save();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_active_slot = getSlot(PlayerManager::get()->getCurrentPlayer()->getUniqueID(), false);
|
||||
if(m_active_slot == NULL)
|
||||
{
|
||||
m_active_slot = createNewSlot(PlayerManager::get()->getCurrentPlayer()->getUniqueID(), false);
|
||||
save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
AchievementInfo * AchievementsManager::getAchievementInfo(uint32_t id)
|
||||
{
|
||||
if ( m_achievements_info.find(id) != m_achievements_info.end())
|
||||
return m_achievements_info[id];
|
||||
std::map<uint32_t, AchievementInfo*>::const_iterator info =
|
||||
m_achievements_info.find(id);
|
||||
if (info != m_achievements_info.end())
|
||||
return info->second;
|
||||
return NULL;
|
||||
}
|
||||
|
@ -19,50 +19,67 @@
|
||||
#ifndef HEADER_ACHIEVEMENTS_MANAGER_HPP
|
||||
#define HEADER_ACHIEVEMENTS_MANAGER_HPP
|
||||
|
||||
#include "achievements/achievements_status.hpp"
|
||||
|
||||
#include "utils/types.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
#include "achievements/achievement_info.hpp"
|
||||
#include "achievements/achievements_slot.hpp"
|
||||
|
||||
class AchievementInfo;
|
||||
class AchievementsStatus;
|
||||
|
||||
#include <irrString.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* \brief Class that takes care of online profiles
|
||||
* \ingroup online
|
||||
*/
|
||||
class AchievementsManager
|
||||
{
|
||||
private :
|
||||
AchievementsSlot * m_active_slot;
|
||||
PtrVector<AchievementsSlot> m_slots;
|
||||
private:
|
||||
/** Pointer to the single instance. */
|
||||
static AchievementsManager* m_achievements_manager;
|
||||
|
||||
std::map<uint32_t, AchievementInfo *> m_achievements_info;
|
||||
|
||||
AchievementsManager ();
|
||||
~AchievementsManager ();
|
||||
AchievementsSlot * createNewSlot(unsigned int id, bool online);
|
||||
AchievementsStatus * createNewSlot(unsigned int id, bool online);
|
||||
void parseAssetFile();
|
||||
void parseUserConfigFile();
|
||||
|
||||
public:
|
||||
/**Singleton */
|
||||
static AchievementsManager * get();
|
||||
static void deallocate();
|
||||
/** Static function to create the instance of the achievement manager. */
|
||||
static void create()
|
||||
{
|
||||
assert(!m_achievements_manager);
|
||||
m_achievements_manager = new AchievementsManager();
|
||||
} // create
|
||||
// ------------------------------------------------------------------------
|
||||
/** Static function to get the achievement manager. */
|
||||
static AchievementsManager* get()
|
||||
{
|
||||
assert(m_achievements_manager);
|
||||
return m_achievements_manager;
|
||||
} // get
|
||||
// ------------------------------------------------------------------------
|
||||
static void destroy()
|
||||
{
|
||||
assert(m_achievements_manager);
|
||||
delete m_achievements_manager;
|
||||
m_achievements_manager = NULL;
|
||||
} // destroy
|
||||
// ========================================================================
|
||||
|
||||
void init();
|
||||
void save();
|
||||
void onRaceEnd();
|
||||
void updateCurrentPlayer();
|
||||
AchievementsSlot * getActive() const { return m_active_slot; }
|
||||
AchievementsSlot * getSlot(unsigned int id, bool online);
|
||||
void createSlotsIfNeeded();
|
||||
AchievementInfo * getAchievementInfo(uint32_t id);
|
||||
const std::map<uint32_t, AchievementInfo *> & getAllInfo() { return m_achievements_info;}
|
||||
AchievementInfo* getAchievementInfo(uint32_t id) const;
|
||||
AchievementsStatus* createAchievementsStatus(const XMLNode *node=NULL);
|
||||
// ------------------------------------------------------------------------
|
||||
const std::map<uint32_t, AchievementInfo *> & getAllInfo()
|
||||
{
|
||||
return m_achievements_info;
|
||||
} // getAllInfo
|
||||
|
||||
}; // class AchievementsManager
|
||||
|
||||
#endif
|
||||
|
@ -1,154 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 Glenn De Jonghe
|
||||
//
|
||||
// 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 "achievements/achievements_slot.hpp"
|
||||
|
||||
#include "achievements/achievement_info.hpp"
|
||||
#include "achievements/achievements_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
// ============================================================================
|
||||
AchievementsSlot::AchievementsSlot(const XMLNode * input)
|
||||
{
|
||||
int fetched_user_id = input->get("user_id", &m_id);
|
||||
std::string online;
|
||||
int fetched_online = input->get("online", &online);
|
||||
if(!fetched_user_id || !fetched_online || !(online == "true" || online == "false"))
|
||||
{
|
||||
m_valid = false;
|
||||
}
|
||||
m_valid = true;
|
||||
m_online = online == "true";
|
||||
|
||||
createFreshSlot();
|
||||
|
||||
std::vector<XMLNode*> xml_achievements;
|
||||
input->getNodes("achievement", xml_achievements);
|
||||
for( unsigned int i=0; i<xml_achievements.size(); i++)
|
||||
{
|
||||
uint32_t achievement_id(0);
|
||||
xml_achievements[i]->get("id", &achievement_id);
|
||||
Achievement * achievement = getAchievement(achievement_id);
|
||||
if(achievement == NULL)
|
||||
{
|
||||
Log::warn("AchievementsSlot", "Found saved achievement data for a non-existent achievement. Discarding.");
|
||||
continue;
|
||||
}
|
||||
achievement->load(xml_achievements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
AchievementsSlot::AchievementsSlot(unsigned int id, bool online)
|
||||
{
|
||||
m_valid = true;
|
||||
m_online = online;
|
||||
m_id = id;
|
||||
|
||||
createFreshSlot();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
AchievementsSlot::~AchievementsSlot()
|
||||
{
|
||||
deleteAchievements();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
void AchievementsSlot::deleteAchievements()
|
||||
{
|
||||
std::map<uint32_t, Achievement *>::iterator it;
|
||||
for ( it = m_achievements.begin(); it != m_achievements.end(); ++it ) {
|
||||
delete it->second;
|
||||
}
|
||||
m_achievements.clear();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
void AchievementsSlot::createFreshSlot()
|
||||
{
|
||||
deleteAchievements();
|
||||
const std::map<uint32_t, AchievementInfo *> all_info = AchievementsManager::get()->getAllInfo();
|
||||
std::map<uint32_t, AchievementInfo *>::const_iterator it;
|
||||
for ( it = all_info.begin(); it != all_info.end(); ++it ) {
|
||||
Achievement::AchievementType achievement_type = it->second->getType();
|
||||
Achievement * achievement;
|
||||
if(achievement_type == Achievement::AT_SINGLE)
|
||||
{
|
||||
achievement = new SingleAchievement(it->second);
|
||||
}
|
||||
else if(achievement_type == Achievement::AT_MAP)
|
||||
{
|
||||
achievement = new MapAchievement(it->second);
|
||||
}
|
||||
m_achievements[achievement->getID()] = achievement;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
void AchievementsSlot::save(std::ofstream & out)
|
||||
{
|
||||
out << " <slot user_id=\"" << m_id
|
||||
<< "\" online=\"" << StringUtils::toString(m_online)
|
||||
<< "\"> \n";
|
||||
std::map<uint32_t, Achievement*>::const_iterator i;
|
||||
for(i = m_achievements.begin(); i != m_achievements.end(); i++)
|
||||
{
|
||||
if (i->second != NULL)
|
||||
i->second->save(out);
|
||||
}
|
||||
out << " </slot>\n";
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
Achievement * AchievementsSlot::getAchievement(uint32_t id)
|
||||
{
|
||||
if ( m_achievements.find(id) != m_achievements.end())
|
||||
return m_achievements[id];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
void AchievementsSlot::sync(const std::vector<uint32_t> & achieved_ids)
|
||||
{
|
||||
for(unsigned int i =0; i < achieved_ids.size(); ++i)
|
||||
{
|
||||
Achievement * achievement = getAchievement(achieved_ids[i]);
|
||||
if(achievement != NULL)
|
||||
achievement->setAchieved();
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
void AchievementsSlot::onRaceEnd()
|
||||
{
|
||||
//reset all values that need to be reset
|
||||
std::map<uint32_t, Achievement *>::iterator iter;
|
||||
for ( iter = m_achievements.begin(); iter != m_achievements.end(); ++iter ) {
|
||||
iter->second->onRaceEnd();
|
||||
}
|
||||
}
|
134
src/achievements/achievements_status.cpp
Normal file
134
src/achievements/achievements_status.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 Glenn De Jonghe
|
||||
//
|
||||
// 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 "achievements/achievements_status.hpp"
|
||||
|
||||
#include "achievements/achievement_info.hpp"
|
||||
#include "achievements/achievements_manager.hpp"
|
||||
#include "io/utf_writer.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
AchievementsStatus::AchievementsStatus()
|
||||
{
|
||||
m_valid = true;
|
||||
m_online = true;
|
||||
} // AchievementsStatus
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
AchievementsStatus::~AchievementsStatus()
|
||||
{
|
||||
deleteAchievements();
|
||||
} // ~AchievementsStatus
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Loads the saved state of all achievements from an XML file.
|
||||
* \param input The XML node to load the data from.
|
||||
*/
|
||||
void AchievementsStatus::load(const XMLNode * input)
|
||||
{
|
||||
std::vector<XMLNode*> xml_achievements;
|
||||
input->getNodes("achievement", xml_achievements);
|
||||
for (unsigned int i = 0; i < xml_achievements.size(); i++)
|
||||
{
|
||||
uint32_t achievement_id(0);
|
||||
xml_achievements[i]->get("id", &achievement_id);
|
||||
Achievement * achievement = getAchievement(achievement_id);
|
||||
if (achievement == NULL)
|
||||
{
|
||||
Log::warn("AchievementsStatus",
|
||||
"Found saved achievement data for a non-existent "
|
||||
"achievement. Discarding.");
|
||||
continue;
|
||||
}
|
||||
achievement->load(xml_achievements[i]);
|
||||
} // for i in xml_achievements
|
||||
|
||||
} // load
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AchievementsStatus::add(Achievement *achievement)
|
||||
{
|
||||
m_achievements[achievement->getID()] = achievement;
|
||||
} // add
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AchievementsStatus::deleteAchievements()
|
||||
{
|
||||
std::map<uint32_t, Achievement *>::iterator it;
|
||||
for ( it = m_achievements.begin(); it != m_achievements.end(); ++it ) {
|
||||
delete it->second;
|
||||
}
|
||||
m_achievements.clear();
|
||||
} // deleteAchievements
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Saves the achievement status to a file. Achievements are stored as part
|
||||
* of the player data file players.xml.
|
||||
* \param out File to write to.
|
||||
*/
|
||||
void AchievementsStatus::save(UTFWriter &out)
|
||||
{
|
||||
out << L" <achievements online=\"" << m_online << L"\"> \n";
|
||||
std::map<uint32_t, Achievement*>::const_iterator i;
|
||||
for(i = m_achievements.begin(); i != m_achievements.end(); i++)
|
||||
{
|
||||
if (i->second != NULL)
|
||||
i->second->save(out);
|
||||
}
|
||||
out << L" </achievements>\n";
|
||||
} // save
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
Achievement * AchievementsStatus::getAchievement(uint32_t id)
|
||||
{
|
||||
if ( m_achievements.find(id) != m_achievements.end())
|
||||
return m_achievements[id];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AchievementsStatus::sync(const std::vector<uint32_t> & achieved_ids)
|
||||
{
|
||||
for(unsigned int i =0; i < achieved_ids.size(); ++i)
|
||||
{
|
||||
Achievement * achievement = getAchievement(achieved_ids[i]);
|
||||
if(achievement != NULL)
|
||||
achievement->setAchieved();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void AchievementsStatus::onRaceEnd()
|
||||
{
|
||||
//reset all values that need to be reset
|
||||
std::map<uint32_t, Achievement *>::iterator iter;
|
||||
for ( iter = m_achievements.begin(); iter != m_achievements.end(); ++iter ) {
|
||||
iter->second->onRaceEnd();
|
||||
}
|
||||
}
|
@ -26,18 +26,17 @@
|
||||
|
||||
#include <irrString.h>
|
||||
#include <string>
|
||||
#include "io/xml_node.hpp"
|
||||
|
||||
class UTFWriter;
|
||||
class XMLNode;
|
||||
|
||||
class AchievementsSlot
|
||||
class AchievementsStatus
|
||||
{
|
||||
private:
|
||||
std::map<uint32_t, Achievement *> m_achievements;
|
||||
bool m_online;
|
||||
bool m_valid;
|
||||
unsigned int m_id;
|
||||
|
||||
void createFreshSlot();
|
||||
void deleteAchievements();
|
||||
|
||||
class SyncAchievementsRequest : public Online::XMLRequest {
|
||||
@ -47,18 +46,25 @@ private:
|
||||
};
|
||||
|
||||
public :
|
||||
AchievementsSlot(const XMLNode * input);
|
||||
AchievementsSlot(unsigned int id, bool online);
|
||||
~AchievementsSlot();
|
||||
bool isValid() const { return m_valid;}
|
||||
void save(std::ofstream & out);
|
||||
bool isOnline() const {return m_online;}
|
||||
AchievementsStatus();
|
||||
~AchievementsStatus();
|
||||
Achievement * getAchievement(uint32_t id);
|
||||
void load(const XMLNode * input);
|
||||
void save(UTFWriter &out);
|
||||
void add(Achievement *achievement);
|
||||
void sync(const std::vector<uint32_t> & achieved_ids);
|
||||
void onRaceEnd();
|
||||
unsigned int getID() const {return m_id;}
|
||||
const std::map<uint32_t, Achievement *> & getAllAchievements() {return m_achievements;}
|
||||
Achievement * getAchievement(uint32_t id);
|
||||
};
|
||||
// ------------------------------------------------------------------------
|
||||
const std::map<uint32_t, Achievement *>& getAllAchievements()
|
||||
{
|
||||
return m_achievements;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
bool isOnline() const { return m_online; }
|
||||
// ------------------------------------------------------------------------
|
||||
bool isValid() const { return m_valid; }
|
||||
// ------------------------------------------------------------------------
|
||||
}; // class AchievementsStatus
|
||||
|
||||
#endif
|
||||
|
@ -43,35 +43,29 @@ void ChallengeStatus::load(const XMLNode* challenges_node)
|
||||
m_data->getId().c_str());
|
||||
return;
|
||||
}
|
||||
const XMLNode* easy = node->getNode("easy");
|
||||
const XMLNode* medium = node->getNode("medium");
|
||||
const XMLNode* hard = node->getNode("hard");
|
||||
|
||||
m_state[0] = CH_INACTIVE;
|
||||
m_state[1] = CH_INACTIVE;
|
||||
m_state[2] = CH_INACTIVE;
|
||||
|
||||
if (easy != NULL)
|
||||
std::string solved;
|
||||
if (node->get("solved", &solved))
|
||||
{
|
||||
bool finished = false;
|
||||
easy->get("solved", &finished);
|
||||
if (solved == "easy")
|
||||
m_state[0] = CH_SOLVED;
|
||||
else if (solved == "medium")
|
||||
{
|
||||
m_state[0] = CH_SOLVED;
|
||||
m_state[1] = CH_SOLVED;
|
||||
}
|
||||
else if (solved == "hard")
|
||||
{
|
||||
m_state[0] = CH_SOLVED;
|
||||
m_state[1] = CH_SOLVED;
|
||||
m_state[2] = CH_SOLVED;
|
||||
}
|
||||
} // if has 'solved' attribute
|
||||
|
||||
if (finished) m_state[0] = CH_SOLVED;
|
||||
}
|
||||
if (medium != NULL)
|
||||
{
|
||||
bool finished = false;
|
||||
medium->get("solved", &finished);
|
||||
|
||||
if (finished) m_state[1] = CH_SOLVED;
|
||||
}
|
||||
if (hard != NULL)
|
||||
{
|
||||
bool finished = false;
|
||||
hard->get("solved", &finished);
|
||||
|
||||
if (finished) m_state[2] = CH_SOLVED;
|
||||
}
|
||||
} // load
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -90,15 +84,13 @@ void ChallengeStatus::setSolved(RaceManager::Difficulty d)
|
||||
|
||||
void ChallengeStatus::save(UTFWriter& writer)
|
||||
{
|
||||
writer << L" <"<< m_data->getId() << L">\n"
|
||||
<< L" <easy solved=\""
|
||||
<< isSolved(RaceManager::DIFFICULTY_EASY)
|
||||
<< L"\"/>\n"
|
||||
<< L" <medium solved=\""
|
||||
<< isSolved(RaceManager::DIFFICULTY_MEDIUM)
|
||||
<< L"\"/>\n"
|
||||
<< L" <hard solved=\""
|
||||
<< isSolved(RaceManager::DIFFICULTY_HARD)
|
||||
<< L"\"/>\n"
|
||||
<< L" </" << m_data->getId() << L">\n";
|
||||
writer << L" <" << m_data->getId();
|
||||
if (isSolved(RaceManager::DIFFICULTY_HARD))
|
||||
writer << L" solved=\"hard\"/>\n";
|
||||
else if (isSolved(RaceManager::DIFFICULTY_MEDIUM))
|
||||
writer << L" solved=\"medium\"/>\n";
|
||||
else if (isSolved(RaceManager::DIFFICULTY_EASY))
|
||||
writer << L" solved=\"easy\"/>\n";
|
||||
else
|
||||
writer << L" solved=\"none\"/>\n";
|
||||
} // save
|
||||
|
@ -271,7 +271,7 @@ void StoryModeStatus::grandPrixFinished()
|
||||
*/
|
||||
void StoryModeStatus::save(UTFWriter &out)
|
||||
{
|
||||
out << " <story-mode first-time=\"" << m_first_time << L"\">\n";
|
||||
out << L" <story-mode first-time=\"" << m_first_time << L"\">\n";
|
||||
std::map<std::string, ChallengeStatus*>::const_iterator i;
|
||||
for(i = m_challenges_state.begin();
|
||||
i != m_challenges_state.end(); i++)
|
||||
@ -279,5 +279,5 @@ void StoryModeStatus::save(UTFWriter &out)
|
||||
if (i->second != NULL)
|
||||
i->second->save(out);
|
||||
}
|
||||
out << " </story-mode>\n";
|
||||
out << L" </story-mode>\n";
|
||||
} // save
|
||||
|
@ -107,6 +107,7 @@ void PlayerManager::load()
|
||||
if(!m_current_player)
|
||||
Log::fatal("PlayerManager", "Can't find a default player.");
|
||||
|
||||
delete players;
|
||||
} // load
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -220,7 +221,6 @@ void PlayerManager::setCurrentPlayer(PlayerProfile *player)
|
||||
m_current_player = player;
|
||||
m_current_player->setDefault(true);
|
||||
m_current_player->computeActive();
|
||||
AchievementsManager::get()->updateCurrentPlayer();
|
||||
} // setCurrentPlayer
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -19,6 +19,7 @@
|
||||
#ifndef HEADER_PLAYER_MANAGER_HPP
|
||||
#define HEADER_PLAYER_MANAGER_HPP
|
||||
|
||||
#include "config/player_profile.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/ptr_vector.hpp"
|
||||
|
||||
@ -26,6 +27,7 @@
|
||||
|
||||
#include <cstddef> // NULL
|
||||
|
||||
class AchievementsStatus;
|
||||
class PlayerProfile;
|
||||
|
||||
/** A special class that manages all local player accounts.
|
||||
@ -88,6 +90,12 @@ public:
|
||||
/** Returns a player with a given unique id. */
|
||||
PlayerProfile *getPlayer(unsigned int n) { return &m_all_players[n];}
|
||||
// ------------------------------------------------------------------------
|
||||
/** A handy shortcut funtion. */
|
||||
static AchievementsStatus* getCurrentAchievementsStatus()
|
||||
{
|
||||
return get()->getCurrentPlayer()->getAchievementsStatus();
|
||||
} // getCurrentAchievementsStatus
|
||||
// ------------------------------------------------------------------------
|
||||
}; // PlayerManager
|
||||
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "config/player_profile.hpp"
|
||||
|
||||
#include "achievements/achievements_manager.hpp"
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "io/xml_node.hpp"
|
||||
@ -37,12 +38,13 @@ PlayerProfile::PlayerProfile(const core::stringw& name, bool is_guest)
|
||||
#ifdef DEBUG
|
||||
m_magic_number = 0xABCD1234;
|
||||
#endif
|
||||
m_name = name;
|
||||
m_is_guest_account = is_guest;
|
||||
m_use_frequency = is_guest ? -1 : 0;
|
||||
m_unique_id = PlayerManager::get()->getUniqueId();
|
||||
m_story_mode_status = unlock_manager->createStoryModeStatus();
|
||||
|
||||
m_name = name;
|
||||
m_is_guest_account = is_guest;
|
||||
m_use_frequency = is_guest ? -1 : 0;
|
||||
m_unique_id = PlayerManager::get()->getUniqueId();
|
||||
m_story_mode_status = unlock_manager->createStoryModeStatus();
|
||||
m_achievements_status =
|
||||
AchievementsManager::get()->createAchievementsStatus();
|
||||
} // PlayerProfile
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@ -59,8 +61,11 @@ PlayerProfile::PlayerProfile(const XMLNode* node)
|
||||
#ifdef DEBUG
|
||||
m_magic_number = 0xABCD1234;
|
||||
#endif
|
||||
const XMLNode *xml_game_slot = node->getNode("story-mode");
|
||||
m_story_mode_status = unlock_manager->createStoryModeStatus(xml_game_slot);
|
||||
const XMLNode *xml_story_mode = node->getNode("story-mode");
|
||||
m_story_mode_status = unlock_manager->createStoryModeStatus(xml_story_mode);
|
||||
const XMLNode *xml_achievements = node->getNode("achievements");
|
||||
m_achievements_status = AchievementsManager::get()
|
||||
->createAchievementsStatus(xml_achievements);
|
||||
|
||||
} // PlayerProfile
|
||||
|
||||
@ -74,9 +79,14 @@ void PlayerProfile::save(UTFWriter &out)
|
||||
<< L"\" guest=\"" << m_is_guest_account
|
||||
<< L"\" use-frequency=\"" << m_use_frequency
|
||||
<< L"\" is-default=\"" << m_is_default
|
||||
<< L"\" unique-id=\"" << m_unique_id << L"\">\n";
|
||||
assert(m_story_mode_status);
|
||||
m_story_mode_status->save(out);
|
||||
<< L"\" unique-id=\"" << m_unique_id << L"\">\n";
|
||||
{
|
||||
assert(m_story_mode_status);
|
||||
m_story_mode_status->save(out);
|
||||
|
||||
assert(m_achievements_status);
|
||||
m_achievements_status->save(out);
|
||||
}
|
||||
out << L" </player>\n";
|
||||
} // save
|
||||
|
||||
|
@ -30,6 +30,7 @@ using namespace irr;
|
||||
#include <string>
|
||||
|
||||
class UTFWriter;
|
||||
class AchievementsStatus;
|
||||
|
||||
/**
|
||||
* \brief Class for managing player profiles (name, control configuration, etc.)
|
||||
@ -64,6 +65,8 @@ private:
|
||||
/** The complete challenge state. */
|
||||
StoryModeStatus *m_story_mode_status;
|
||||
|
||||
AchievementsStatus *m_achievements_status;
|
||||
|
||||
public:
|
||||
|
||||
PlayerProfile(const core::stringw& name, bool is_guest = false);
|
||||
@ -186,6 +189,11 @@ public:
|
||||
{
|
||||
return m_story_mode_status->getNumHardTrophies();
|
||||
} // getNumHardTropies
|
||||
// ------------------------------------------------------------------------
|
||||
AchievementsStatus* getAchievementsStatus()
|
||||
{
|
||||
return m_achievements_status;
|
||||
} // getAchievementsStatus
|
||||
|
||||
}; // class PlayerProfile
|
||||
|
||||
|
@ -229,12 +229,22 @@ public:
|
||||
m_maxheight[who] = height;
|
||||
}
|
||||
|
||||
float getMaxHeight(u32 who) const
|
||||
{
|
||||
return m_maxheight[who];
|
||||
}
|
||||
|
||||
void setBoostTime(u32 who, float time)
|
||||
{
|
||||
assert(who < MAX_PLAYER_COUNT);
|
||||
m_boost_time[who] = time;
|
||||
}
|
||||
|
||||
float getBoostTime(u32 who) const
|
||||
{
|
||||
return m_boost_time[who];
|
||||
}
|
||||
|
||||
void setCenter(u32 who, float X, float Y)
|
||||
{
|
||||
assert(who < MAX_PLAYER_COUNT);
|
||||
@ -242,6 +252,11 @@ public:
|
||||
m_center[who].Y = Y;
|
||||
}
|
||||
|
||||
core::vector2df getCenter(u32 who) const
|
||||
{
|
||||
return core::vector2df(m_center[who].X, m_center[who].Y);
|
||||
}
|
||||
|
||||
void setDirection(u32 who, float X, float Y)
|
||||
{
|
||||
assert(who < MAX_PLAYER_COUNT);
|
||||
@ -249,6 +264,11 @@ public:
|
||||
m_direction[who].Y = Y;
|
||||
}
|
||||
|
||||
core::vector2df getDirection(u32 who) const
|
||||
{
|
||||
return core::vector2df(m_direction[who].X, m_direction[who].Y);
|
||||
}
|
||||
|
||||
void setCurrentCamera(u32 who)
|
||||
{
|
||||
m_current_camera = who;
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "graphics/shadow_importance.hpp"
|
||||
#include "graphics/stkanimatedmesh.hpp"
|
||||
#include "graphics/stkbillboard.hpp"
|
||||
#include "graphics/stkmesh.hpp"
|
||||
#include "graphics/stkmeshscenenode.hpp"
|
||||
#include "graphics/sun.hpp"
|
||||
#include "graphics/rtts.hpp"
|
||||
#include "graphics/water.hpp"
|
||||
@ -937,7 +937,7 @@ scene::IMeshSceneNode *IrrDriver::addMesh(scene::IMesh *mesh,
|
||||
if (!parent)
|
||||
parent = m_scene_manager->getRootSceneNode();
|
||||
|
||||
scene::IMeshSceneNode* node = new STKMesh(mesh, parent, m_scene_manager, -1);
|
||||
scene::IMeshSceneNode* node = new STKMeshSceneNode(mesh, parent, m_scene_manager, -1);
|
||||
node->drop();
|
||||
|
||||
return node;
|
||||
|
@ -578,6 +578,41 @@ void PostProcessing::renderFog(const core::matrix4 &ipvmat)
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void PostProcessing::renderMotionBlur(unsigned cam, ITexture *in, ITexture *out)
|
||||
{
|
||||
|
||||
MotionBlurProvider * const cb = (MotionBlurProvider *)irr_driver->
|
||||
getCallback(ES_MOTIONBLUR);
|
||||
|
||||
scene::ICameraSceneNode * const camnode =
|
||||
Camera::getCamera(cam)->getCameraSceneNode();
|
||||
// Calculate the kart's Y position on screen
|
||||
const core::vector3df pos =
|
||||
Camera::getCamera(cam)->getKart()->getNode()->getPosition();
|
||||
float ndc[4];
|
||||
core::matrix4 trans = camnode->getProjectionMatrix();
|
||||
trans *= camnode->getViewMatrix();
|
||||
|
||||
trans.transformVect(ndc, pos);
|
||||
const float karty = (ndc[1] / ndc[3]) * 0.5f + 0.5f;
|
||||
setMotionBlurCenterY(cam, karty);
|
||||
|
||||
irr_driver->getVideoDriver()->setRenderTarget(out, true, false);
|
||||
|
||||
glUseProgram(FullScreenShader::MotionBlurShader::Program);
|
||||
glBindVertexArray(FullScreenShader::MotionBlurShader::vao);
|
||||
|
||||
setTexture(0, getTextureGLuint(in), GL_NEAREST, GL_NEAREST);
|
||||
FullScreenShader::MotionBlurShader::setUniforms(cb->getBoostTime(cam), cb->getCenter(cam), cb->getDirection(cam), 0.15, cb->getMaxHeight(cam) * 0.7, 0);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Render the post-processed scene */
|
||||
void PostProcessing::render()
|
||||
@ -751,24 +786,7 @@ void PostProcessing::render()
|
||||
if (UserConfigParams::m_motionblur && m_any_boost) // motion blur
|
||||
{
|
||||
PROFILER_PUSH_CPU_MARKER("- Motion blur", 0xFF, 0x00, 0x00);
|
||||
// Calculate the kart's Y position on screen
|
||||
const core::vector3df pos =
|
||||
Camera::getCamera(cam)->getKart()->getNode()->getPosition();
|
||||
float ndc[4];
|
||||
core::matrix4 trans = camnode->getProjectionMatrix();
|
||||
trans *= camnode->getViewMatrix();
|
||||
|
||||
trans.transformVect(ndc, pos);
|
||||
const float karty = (ndc[1] / ndc[3]) * 0.5f + 0.5f;
|
||||
setMotionBlurCenterY(cam, karty);
|
||||
|
||||
|
||||
m_material.MaterialType = irr_driver->getShader(ES_MOTIONBLUR);
|
||||
m_material.setTexture(0, in);
|
||||
drv->setRenderTarget(out, true, false);
|
||||
|
||||
drawQuad(cam, m_material);
|
||||
|
||||
renderMotionBlur(cam, in, out);
|
||||
ITexture *tmp = in;
|
||||
in = out;
|
||||
out = tmp;
|
||||
|
@ -88,6 +88,7 @@ public:
|
||||
void renderPassThrough(video::ITexture *tex);
|
||||
void renderPassThrough(unsigned tex);
|
||||
|
||||
void renderMotionBlur(unsigned cam, video::ITexture *in, video::ITexture *out);
|
||||
void renderGlow(video::ITexture *tex);
|
||||
|
||||
/** Render the post-processed scene */
|
||||
|
@ -238,6 +238,7 @@ void Shaders::loadShaders()
|
||||
FullScreenShader::SSAOShader::init();
|
||||
FullScreenShader::SunLightShader::init();
|
||||
FullScreenShader::ShadowedSunLightShader::init();
|
||||
FullScreenShader::MotionBlurShader::init();
|
||||
MeshShader::ColorizeShader::init();
|
||||
MeshShader::NormalMapShader::init();
|
||||
MeshShader::ObjectPass1Shader::init();
|
||||
@ -1692,6 +1693,37 @@ namespace FullScreenShader
|
||||
glUniformMatrix4fv(uniform_ipvmat, 1, GL_FALSE, ipvmat.pointer());
|
||||
glUniform1i(uniform_tex, TU_ntex);
|
||||
}
|
||||
|
||||
GLuint MotionBlurShader::Program;
|
||||
GLuint MotionBlurShader::uniform_boost_amount;
|
||||
GLuint MotionBlurShader::uniform_center;
|
||||
GLuint MotionBlurShader::uniform_color_buffer;
|
||||
GLuint MotionBlurShader::uniform_direction;
|
||||
GLuint MotionBlurShader::uniform_mask_radius;
|
||||
GLuint MotionBlurShader::uniform_max_tex_height;
|
||||
GLuint MotionBlurShader::vao;
|
||||
|
||||
void MotionBlurShader::init()
|
||||
{
|
||||
Program = LoadProgram(file_manager->getAsset("shaders/screenquad.vert").c_str(), file_manager->getAsset("shaders/motion_blur.frag").c_str());
|
||||
uniform_boost_amount = glGetUniformLocation(Program, "boost_amount");
|
||||
uniform_center = glGetUniformLocation(Program, "center");
|
||||
uniform_color_buffer = glGetUniformLocation(Program, "color_buffer");
|
||||
uniform_direction = glGetUniformLocation(Program, "direction");
|
||||
uniform_mask_radius = glGetUniformLocation(Program, "mask_radius");
|
||||
uniform_max_tex_height = glGetUniformLocation(Program, "max_tex_height");
|
||||
vao = createVAO(Program);
|
||||
}
|
||||
|
||||
void MotionBlurShader::setUniforms(float boost_amount, const core::vector2df ¢er, const core::vector2df &direction, float mask_radius, float max_tex_height, unsigned TU_cb)
|
||||
{
|
||||
glUniform1f(uniform_boost_amount, boost_amount);
|
||||
glUniform2f(uniform_center, center.X, center.Y);
|
||||
glUniform2f(uniform_direction, direction.X, direction.Y);
|
||||
glUniform1f(uniform_mask_radius, mask_radius);
|
||||
glUniform1f(uniform_max_tex_height, max_tex_height);
|
||||
glUniform1i(uniform_color_buffer, TU_cb);
|
||||
}
|
||||
}
|
||||
|
||||
namespace UIShader
|
||||
|
@ -523,6 +523,17 @@ public:
|
||||
static void setUniforms(const core::matrix4 &ipvmat, float fogmax, float startH, float endH, float start, float end, const core::vector3df &col, unsigned TU_ntex);
|
||||
};
|
||||
|
||||
class MotionBlurShader
|
||||
{
|
||||
public:
|
||||
static GLuint Program;
|
||||
static GLuint uniform_boost_amount, uniform_color_buffer, uniform_center, uniform_direction, uniform_mask_radius, uniform_max_tex_height;
|
||||
static GLuint vao;
|
||||
|
||||
static void init();
|
||||
static void setUniforms(float boost_amount, const core::vector2df ¢er, const core::vector2df &direction, float mask_radius, float max_tex_height, unsigned TU_cb);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace UIShader
|
||||
|
@ -76,24 +76,6 @@ void STKAnimatedMesh::drawSolid(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
isObjectPass(video::E_MATERIAL_TYPE type)
|
||||
{
|
||||
if (type == irr_driver->getShader(ES_OBJECTPASS))
|
||||
return true;
|
||||
if (type == irr_driver->getShader(ES_OBJECTPASS_REF))
|
||||
return true;
|
||||
if (type == irr_driver->getShader(ES_OBJECTPASS_RIMLIT))
|
||||
return true;
|
||||
if (type == irr_driver->getShader(ES_OBJECT_UNLIT))
|
||||
return true;
|
||||
if (type == video::EMT_ONETEXTURE_BLEND)
|
||||
return true;
|
||||
if (type == video::EMT_TRANSPARENT_ADD_COLOR)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void STKAnimatedMesh::drawShadow(const GLMesh &mesh)
|
||||
{
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
@ -156,7 +138,7 @@ void STKAnimatedMesh::render()
|
||||
driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
|
||||
else if (Mesh->getMeshType() == scene::EAMT_SKINNED)
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation * ((scene::SSkinMeshBuffer*)mb)->Transformation);
|
||||
if (isObjectPass(material.MaterialType))
|
||||
if (isObject(material.MaterialType))
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
initvaostate(GLmeshes[i], material.MaterialType, false);
|
||||
|
@ -144,56 +144,6 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb)
|
||||
return result;
|
||||
}
|
||||
|
||||
STKMesh::STKMesh(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
|
||||
const irr::core::vector3df& position,
|
||||
const irr::core::vector3df& rotation,
|
||||
const irr::core::vector3df& scale) :
|
||||
CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
|
||||
{
|
||||
createGLMeshes();
|
||||
}
|
||||
|
||||
void STKMesh::createGLMeshes()
|
||||
{
|
||||
for (u32 i = 0; i<Mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
GLmeshes.push_back(allocateMeshBuffer(mb));
|
||||
}
|
||||
}
|
||||
|
||||
void STKMesh::cleanGLMeshes()
|
||||
{
|
||||
for (u32 i = 0; i < GLmeshes.size(); ++i)
|
||||
{
|
||||
GLMesh mesh = GLmeshes[i];
|
||||
if (!mesh.vertex_buffer)
|
||||
continue;
|
||||
if (mesh.vao_first_pass)
|
||||
glDeleteVertexArrays(1, &(mesh.vao_first_pass));
|
||||
if (mesh.vao_second_pass)
|
||||
glDeleteVertexArrays(1, &(mesh.vao_second_pass));
|
||||
if (mesh.vao_glow_pass)
|
||||
glDeleteVertexArrays(1, &(mesh.vao_glow_pass));
|
||||
if (mesh.vao_displace_pass)
|
||||
glDeleteVertexArrays(1, &(mesh.vao_displace_pass));
|
||||
glDeleteBuffers(1, &(mesh.vertex_buffer));
|
||||
glDeleteBuffers(1, &(mesh.index_buffer));
|
||||
}
|
||||
GLmeshes.clear();
|
||||
}
|
||||
|
||||
void STKMesh::setMesh(irr::scene::IMesh* mesh)
|
||||
{
|
||||
CMeshSceneNode::setMesh(mesh);
|
||||
cleanGLMeshes();
|
||||
createGLMeshes();
|
||||
}
|
||||
|
||||
STKMesh::~STKMesh()
|
||||
{
|
||||
cleanGLMeshes();
|
||||
}
|
||||
|
||||
void computeMVP(core::matrix4 &ModelViewProjectionMatrix)
|
||||
{
|
||||
@ -241,22 +191,6 @@ void drawObjectRefPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProje
|
||||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
static
|
||||
core::vector3df getWind()
|
||||
{
|
||||
const core::vector3df pos = irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD).getTranslation();
|
||||
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
|
||||
GrassShaderProvider *gsp = (GrassShaderProvider *)irr_driver->getCallback(ES_GRASS);
|
||||
float m_speed = gsp->getSpeed(), m_amplitude = gsp->getAmplitude();
|
||||
|
||||
float strength = (pos.X + pos.Y + pos.Z) * 1.2f + time * m_speed;
|
||||
strength = noise2d(strength / 10.0f) * m_amplitude * 5;
|
||||
// * 5 is to work with the existing amplitude values.
|
||||
|
||||
// Pre-multiply on the cpu
|
||||
return irr_driver->getWind() * strength;
|
||||
}
|
||||
|
||||
void drawGrassPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, core::vector3df windDir)
|
||||
{
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
@ -707,142 +641,7 @@ void drawBubble(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatr
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void STKMesh::drawGlow(const GLMesh &mesh)
|
||||
{
|
||||
ColorizeProvider * const cb = (ColorizeProvider *)irr_driver->getCallback(ES_COLORIZE);
|
||||
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
computeMVP(ModelViewProjectionMatrix);
|
||||
glUseProgram(MeshShader::ColorizeShader::Program);
|
||||
MeshShader::ColorizeShader::setUniforms(ModelViewProjectionMatrix, cb->getRed(), cb->getGreen(), cb->getBlue());
|
||||
|
||||
glBindVertexArray(mesh.vao_glow_pass);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void STKMesh::drawDisplace(const GLMesh &mesh)
|
||||
{
|
||||
DisplaceProvider * const cb = (DisplaceProvider *)irr_driver->getCallback(ES_DISPLACE);
|
||||
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
computeMVP(ModelViewProjectionMatrix);
|
||||
core::matrix4 ModelViewMatrix = irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
|
||||
ModelViewMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
|
||||
setTexture(0, getTextureGLuint(irr_driver->getTexture(FileManager::TEXTURE, "displace.png")), GL_LINEAR, GL_LINEAR, true);
|
||||
glUseProgram(MeshShader::DisplaceShader::Program);
|
||||
MeshShader::DisplaceShader::setUniforms(ModelViewProjectionMatrix, ModelViewMatrix, cb->getDirX(), cb->getDirY(), cb->getDir2X(), cb->getDir2Y(), 0);
|
||||
|
||||
glBindVertexArray(mesh.vao_displace_pass);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void STKMesh::drawTransparent(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
|
||||
{
|
||||
assert(irr_driver->getPhase() == TRANSPARENT_PASS);
|
||||
|
||||
computeMVP(ModelViewProjectionMatrix);
|
||||
|
||||
if (type == irr_driver->getShader(ES_BUBBLES))
|
||||
drawBubble(mesh, ModelViewProjectionMatrix);
|
||||
else if (World::getWorld()->getTrack()->isFogEnabled())
|
||||
drawTransparentFogObject(mesh, ModelViewProjectionMatrix, TextureMatrix);
|
||||
else
|
||||
drawTransparentObject(mesh, ModelViewProjectionMatrix, TextureMatrix);
|
||||
return;
|
||||
}
|
||||
|
||||
void STKMesh::drawShadow(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
|
||||
{
|
||||
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
|
||||
std::vector<core::matrix4> ShadowMVP(irr_driver->getShadowViewProj());
|
||||
for (unsigned i = 0; i < ShadowMVP.size(); i++)
|
||||
ShadowMVP[i] *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
|
||||
|
||||
if (type == irr_driver->getShader(ES_OBJECTPASS_REF))
|
||||
{
|
||||
setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
glUseProgram(MeshShader::RefShadowShader::Program);
|
||||
MeshShader::RefShadowShader::setUniforms(ShadowMVP, 0);
|
||||
}
|
||||
/* else if (type == irr_driver->getShader(ES_GRASS) || type == irr_driver->getShader(ES_GRASS_REF))
|
||||
{
|
||||
setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
glUseProgram(MeshShader::GrassShadowShader::Program);
|
||||
MeshShader::GrassShadowShader::setUniforms(ShadowMVP, windDir, 0);
|
||||
}*/
|
||||
else
|
||||
{
|
||||
glUseProgram(MeshShader::ShadowShader::Program);
|
||||
MeshShader::ShadowShader::setUniforms(ShadowMVP);
|
||||
}
|
||||
glBindVertexArray(mesh.vao_shadow_pass);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void STKMesh::drawSolid(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
|
||||
{
|
||||
switch (irr_driver->getPhase())
|
||||
{
|
||||
case SOLID_NORMAL_AND_DEPTH_PASS:
|
||||
{
|
||||
windDir = getWind();
|
||||
|
||||
computeMVP(ModelViewProjectionMatrix);
|
||||
computeTIMV(TransposeInverseModelView);
|
||||
|
||||
if (type == irr_driver->getShader(ES_NORMAL_MAP))
|
||||
drawNormalPass(mesh, ModelViewProjectionMatrix, TransposeInverseModelView);
|
||||
else if (type == irr_driver->getShader(ES_OBJECTPASS_REF))
|
||||
drawObjectRefPass1(mesh, ModelViewProjectionMatrix, TransposeInverseModelView);
|
||||
else if (type == irr_driver->getShader(ES_GRASS) || type == irr_driver->getShader(ES_GRASS_REF))
|
||||
drawGrassPass1(mesh, ModelViewProjectionMatrix, TransposeInverseModelView, windDir);
|
||||
else
|
||||
drawObjectPass1(mesh, ModelViewProjectionMatrix, TransposeInverseModelView);
|
||||
break;
|
||||
}
|
||||
case SOLID_LIT_PASS:
|
||||
{
|
||||
if (type == irr_driver->getShader(ES_SPHERE_MAP))
|
||||
drawSphereMap(mesh, ModelViewProjectionMatrix, TransposeInverseModelView);
|
||||
else if (type == irr_driver->getShader(ES_SPLATTING))
|
||||
drawSplatting(mesh, ModelViewProjectionMatrix);
|
||||
else if (type == irr_driver->getShader(ES_OBJECTPASS_REF))
|
||||
drawObjectRefPass2(mesh, ModelViewProjectionMatrix);
|
||||
else if (type == irr_driver->getShader(ES_GRASS) || type == irr_driver->getShader(ES_GRASS_REF))
|
||||
drawGrassPass2(mesh, ModelViewProjectionMatrix, windDir);
|
||||
else if (type == irr_driver->getShader(ES_OBJECTPASS_RIMLIT))
|
||||
drawObjectRimLimit(mesh, ModelViewProjectionMatrix, TransposeInverseModelView);
|
||||
else if (type == irr_driver->getShader(ES_OBJECT_UNLIT))
|
||||
drawObjectUnlit(mesh, ModelViewProjectionMatrix);
|
||||
else if (mesh.textures[1] && type != irr_driver->getShader(ES_NORMAL_MAP))
|
||||
drawDetailledObjectPass2(mesh, ModelViewProjectionMatrix);
|
||||
else if (!mesh.textures[0])
|
||||
drawUntexturedObject(mesh, ModelViewProjectionMatrix);
|
||||
else if (!TextureMatrix.isIdentity())
|
||||
drawMovingTexture(mesh, ModelViewProjectionMatrix, TextureMatrix);
|
||||
else
|
||||
drawObjectPass2(mesh, ModelViewProjectionMatrix);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
assert(0 && "wrong pass");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool isObject(video::E_MATERIAL_TYPE type)
|
||||
bool isObject(video::E_MATERIAL_TYPE type)
|
||||
{
|
||||
if (type == irr_driver->getShader(ES_OBJECTPASS))
|
||||
return true;
|
||||
@ -1003,69 +802,3 @@ void initvaostate(GLMesh &mesh, video::E_MATERIAL_TYPE type, bool MovingTexture)
|
||||
}
|
||||
}
|
||||
|
||||
void STKMesh::render()
|
||||
{
|
||||
irr::video::IVideoDriver* driver = irr_driver->getVideoDriver();
|
||||
|
||||
if (!Mesh || !driver)
|
||||
return;
|
||||
|
||||
bool isTransparentPass =
|
||||
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
|
||||
|
||||
++PassCount;
|
||||
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
Box = Mesh->getBoundingBox();
|
||||
|
||||
for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
if (mb)
|
||||
{
|
||||
TextureMatrix = getMaterial(i).getTextureMatrix(0);
|
||||
const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
|
||||
|
||||
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(material.MaterialType);
|
||||
bool transparent = (rnd && rnd->isTransparent());
|
||||
|
||||
if (isTransparentPass != transparent)
|
||||
continue;
|
||||
if (irr_driver->getPhase() == DISPLACEMENT_PASS)
|
||||
{
|
||||
initvaostate(GLmeshes[i], material.MaterialType, false);
|
||||
drawDisplace(GLmeshes[i]);
|
||||
continue;
|
||||
}
|
||||
if (!isObject(material.MaterialType))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::warn("material", "Unhandled (static) material type : %d", material.MaterialType);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// only render transparent buffer if this is the transparent render pass
|
||||
// and solid only in solid pass
|
||||
if (irr_driver->getPhase() == GLOW_PASS)
|
||||
{
|
||||
initvaostate(GLmeshes[i], material.MaterialType, TextureMatrix.isIdentity());
|
||||
drawGlow(GLmeshes[i]);
|
||||
}
|
||||
else if (irr_driver->getPhase() == SHADOW_PASS)
|
||||
{
|
||||
initvaostate(GLmeshes[i], material.MaterialType, TextureMatrix.isIdentity());
|
||||
drawShadow(GLmeshes[i], material.MaterialType);
|
||||
}
|
||||
else
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
initvaostate(GLmeshes[i], material.MaterialType, TextureMatrix.isIdentity());
|
||||
if (transparent)
|
||||
drawTransparent(GLmeshes[i], material.MaterialType);
|
||||
else
|
||||
drawSolid(GLmeshes[i], material.MaterialType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb);
|
||||
void initvaostate(GLMesh &mesh, video::E_MATERIAL_TYPE type, bool moving_texture);
|
||||
void computeMVP(core::matrix4 &ModelViewProjectionMatrix);
|
||||
void computeTIMV(core::matrix4 &TransposeInverseModelView);
|
||||
bool isObject(video::E_MATERIAL_TYPE type);
|
||||
|
||||
// Pass 1 shader (ie shaders that outputs normals and depth)
|
||||
void drawObjectPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView);
|
||||
@ -52,30 +53,4 @@ void drawTransparentObject(const GLMesh &mesh, const core::matrix4 &ModelViewPro
|
||||
void drawTransparentFogObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix);
|
||||
void drawBubble(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix);
|
||||
|
||||
class STKMesh : public irr::scene::CMeshSceneNode
|
||||
{
|
||||
protected:
|
||||
std::vector<GLMesh> GLmeshes;
|
||||
core::matrix4 ModelViewProjectionMatrix, TransposeInverseModelView, TextureMatrix;
|
||||
core::vector3df windDir;
|
||||
void drawSolid(const GLMesh &mesh, video::E_MATERIAL_TYPE type);
|
||||
void drawTransparent(const GLMesh &mesh, video::E_MATERIAL_TYPE type);
|
||||
|
||||
// Misc passes shaders (glow, displace...)
|
||||
void drawGlow(const GLMesh &mesh);
|
||||
void drawDisplace(const GLMesh &mesh);
|
||||
void drawShadow(const GLMesh &mesh, video::E_MATERIAL_TYPE type);
|
||||
void createGLMeshes();
|
||||
void cleanGLMeshes();
|
||||
public:
|
||||
STKMesh(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
|
||||
const irr::core::vector3df& position = irr::core::vector3df(0,0,0),
|
||||
const irr::core::vector3df& rotation = irr::core::vector3df(0,0,0),
|
||||
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
virtual void render();
|
||||
virtual void setMesh(irr::scene::IMesh* mesh);
|
||||
void MovingTexture(unsigned, unsigned);
|
||||
~STKMesh();
|
||||
};
|
||||
|
||||
#endif // STKMESH_H
|
||||
#endif // STKMESH_H
|
280
src/graphics/stkmeshscenenode.cpp
Normal file
280
src/graphics/stkmeshscenenode.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
#include "stkmeshscenenode.hpp"
|
||||
#include "stkmesh.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
#include <ISceneManager.h>
|
||||
#include <IMaterialRenderer.h>
|
||||
#include "config/user_config.hpp"
|
||||
#include "graphics/callbacks.hpp"
|
||||
#include "utils/helpers.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "modes/world.hpp"
|
||||
|
||||
static
|
||||
core::vector3df getWind()
|
||||
{
|
||||
const core::vector3df pos = irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD).getTranslation();
|
||||
const float time = irr_driver->getDevice()->getTimer()->getTime() / 1000.0f;
|
||||
GrassShaderProvider *gsp = (GrassShaderProvider *)irr_driver->getCallback(ES_GRASS);
|
||||
float m_speed = gsp->getSpeed(), m_amplitude = gsp->getAmplitude();
|
||||
|
||||
float strength = (pos.X + pos.Y + pos.Z) * 1.2f + time * m_speed;
|
||||
strength = noise2d(strength / 10.0f) * m_amplitude * 5;
|
||||
// * 5 is to work with the existing amplitude values.
|
||||
|
||||
// Pre-multiply on the cpu
|
||||
return irr_driver->getWind() * strength;
|
||||
}
|
||||
|
||||
STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
|
||||
const irr::core::vector3df& position,
|
||||
const irr::core::vector3df& rotation,
|
||||
const irr::core::vector3df& scale) :
|
||||
CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale)
|
||||
{
|
||||
createGLMeshes();
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::createGLMeshes()
|
||||
{
|
||||
for (u32 i = 0; i<Mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
GLmeshes.push_back(allocateMeshBuffer(mb));
|
||||
}
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::cleanGLMeshes()
|
||||
{
|
||||
for (u32 i = 0; i < GLmeshes.size(); ++i)
|
||||
{
|
||||
GLMesh mesh = GLmeshes[i];
|
||||
if (!mesh.vertex_buffer)
|
||||
continue;
|
||||
if (mesh.vao_first_pass)
|
||||
glDeleteVertexArrays(1, &(mesh.vao_first_pass));
|
||||
if (mesh.vao_second_pass)
|
||||
glDeleteVertexArrays(1, &(mesh.vao_second_pass));
|
||||
if (mesh.vao_glow_pass)
|
||||
glDeleteVertexArrays(1, &(mesh.vao_glow_pass));
|
||||
if (mesh.vao_displace_pass)
|
||||
glDeleteVertexArrays(1, &(mesh.vao_displace_pass));
|
||||
glDeleteBuffers(1, &(mesh.vertex_buffer));
|
||||
glDeleteBuffers(1, &(mesh.index_buffer));
|
||||
}
|
||||
GLmeshes.clear();
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::setMesh(irr::scene::IMesh* mesh)
|
||||
{
|
||||
CMeshSceneNode::setMesh(mesh);
|
||||
cleanGLMeshes();
|
||||
createGLMeshes();
|
||||
}
|
||||
|
||||
STKMeshSceneNode::~STKMeshSceneNode()
|
||||
{
|
||||
cleanGLMeshes();
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::drawGlow(const GLMesh &mesh)
|
||||
{
|
||||
ColorizeProvider * const cb = (ColorizeProvider *)irr_driver->getCallback(ES_COLORIZE);
|
||||
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
computeMVP(ModelViewProjectionMatrix);
|
||||
glUseProgram(MeshShader::ColorizeShader::Program);
|
||||
MeshShader::ColorizeShader::setUniforms(ModelViewProjectionMatrix, cb->getRed(), cb->getGreen(), cb->getBlue());
|
||||
|
||||
glBindVertexArray(mesh.vao_glow_pass);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::drawDisplace(const GLMesh &mesh)
|
||||
{
|
||||
DisplaceProvider * const cb = (DisplaceProvider *)irr_driver->getCallback(ES_DISPLACE);
|
||||
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
computeMVP(ModelViewProjectionMatrix);
|
||||
core::matrix4 ModelViewMatrix = irr_driver->getVideoDriver()->getTransform(video::ETS_VIEW);
|
||||
ModelViewMatrix *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
|
||||
setTexture(0, getTextureGLuint(irr_driver->getTexture(FileManager::TEXTURE, "displace.png")), GL_LINEAR, GL_LINEAR, true);
|
||||
glUseProgram(MeshShader::DisplaceShader::Program);
|
||||
MeshShader::DisplaceShader::setUniforms(ModelViewProjectionMatrix, ModelViewMatrix, cb->getDirX(), cb->getDirY(), cb->getDir2X(), cb->getDir2Y(), 0);
|
||||
|
||||
glBindVertexArray(mesh.vao_displace_pass);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::drawTransparent(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
|
||||
{
|
||||
assert(irr_driver->getPhase() == TRANSPARENT_PASS);
|
||||
|
||||
computeMVP(ModelViewProjectionMatrix);
|
||||
|
||||
if (type == irr_driver->getShader(ES_BUBBLES))
|
||||
drawBubble(mesh, ModelViewProjectionMatrix);
|
||||
else if (World::getWorld()->getTrack()->isFogEnabled())
|
||||
drawTransparentFogObject(mesh, ModelViewProjectionMatrix, TextureMatrix);
|
||||
else
|
||||
drawTransparentObject(mesh, ModelViewProjectionMatrix, TextureMatrix);
|
||||
return;
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::drawShadow(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
|
||||
{
|
||||
|
||||
GLenum ptype = mesh.PrimitiveType;
|
||||
GLenum itype = mesh.IndexType;
|
||||
size_t count = mesh.IndexCount;
|
||||
|
||||
|
||||
std::vector<core::matrix4> ShadowMVP(irr_driver->getShadowViewProj());
|
||||
for (unsigned i = 0; i < ShadowMVP.size(); i++)
|
||||
ShadowMVP[i] *= irr_driver->getVideoDriver()->getTransform(video::ETS_WORLD);
|
||||
|
||||
if (type == irr_driver->getShader(ES_OBJECTPASS_REF))
|
||||
{
|
||||
setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
glUseProgram(MeshShader::RefShadowShader::Program);
|
||||
MeshShader::RefShadowShader::setUniforms(ShadowMVP, 0);
|
||||
}
|
||||
/* else if (type == irr_driver->getShader(ES_GRASS) || type == irr_driver->getShader(ES_GRASS_REF))
|
||||
{
|
||||
setTexture(0, mesh.textures[0], GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true);
|
||||
glUseProgram(MeshShader::GrassShadowShader::Program);
|
||||
MeshShader::GrassShadowShader::setUniforms(ShadowMVP, windDir, 0);
|
||||
}*/
|
||||
else
|
||||
{
|
||||
glUseProgram(MeshShader::ShadowShader::Program);
|
||||
MeshShader::ShadowShader::setUniforms(ShadowMVP);
|
||||
}
|
||||
glBindVertexArray(mesh.vao_shadow_pass);
|
||||
glDrawElements(ptype, count, itype, 0);
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::drawSolid(const GLMesh &mesh, video::E_MATERIAL_TYPE type)
|
||||
{
|
||||
switch (irr_driver->getPhase())
|
||||
{
|
||||
case SOLID_NORMAL_AND_DEPTH_PASS:
|
||||
{
|
||||
windDir = getWind();
|
||||
|
||||
computeMVP(ModelViewProjectionMatrix);
|
||||
computeTIMV(TransposeInverseModelView);
|
||||
|
||||
if (type == irr_driver->getShader(ES_NORMAL_MAP))
|
||||
drawNormalPass(mesh, ModelViewProjectionMatrix, TransposeInverseModelView);
|
||||
else if (type == irr_driver->getShader(ES_OBJECTPASS_REF))
|
||||
drawObjectRefPass1(mesh, ModelViewProjectionMatrix, TransposeInverseModelView);
|
||||
else if (type == irr_driver->getShader(ES_GRASS) || type == irr_driver->getShader(ES_GRASS_REF))
|
||||
drawGrassPass1(mesh, ModelViewProjectionMatrix, TransposeInverseModelView, windDir);
|
||||
else
|
||||
drawObjectPass1(mesh, ModelViewProjectionMatrix, TransposeInverseModelView);
|
||||
break;
|
||||
}
|
||||
case SOLID_LIT_PASS:
|
||||
{
|
||||
if (type == irr_driver->getShader(ES_SPHERE_MAP))
|
||||
drawSphereMap(mesh, ModelViewProjectionMatrix, TransposeInverseModelView);
|
||||
else if (type == irr_driver->getShader(ES_SPLATTING))
|
||||
drawSplatting(mesh, ModelViewProjectionMatrix);
|
||||
else if (type == irr_driver->getShader(ES_OBJECTPASS_REF))
|
||||
drawObjectRefPass2(mesh, ModelViewProjectionMatrix);
|
||||
else if (type == irr_driver->getShader(ES_GRASS) || type == irr_driver->getShader(ES_GRASS_REF))
|
||||
drawGrassPass2(mesh, ModelViewProjectionMatrix, windDir);
|
||||
else if (type == irr_driver->getShader(ES_OBJECTPASS_RIMLIT))
|
||||
drawObjectRimLimit(mesh, ModelViewProjectionMatrix, TransposeInverseModelView);
|
||||
else if (type == irr_driver->getShader(ES_OBJECT_UNLIT))
|
||||
drawObjectUnlit(mesh, ModelViewProjectionMatrix);
|
||||
else if (mesh.textures[1] && type != irr_driver->getShader(ES_NORMAL_MAP))
|
||||
drawDetailledObjectPass2(mesh, ModelViewProjectionMatrix);
|
||||
else if (!mesh.textures[0])
|
||||
drawUntexturedObject(mesh, ModelViewProjectionMatrix);
|
||||
else if (!TextureMatrix.isIdentity())
|
||||
drawMovingTexture(mesh, ModelViewProjectionMatrix, TextureMatrix);
|
||||
else
|
||||
drawObjectPass2(mesh, ModelViewProjectionMatrix);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
assert(0 && "wrong pass");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void STKMeshSceneNode::render()
|
||||
{
|
||||
irr::video::IVideoDriver* driver = irr_driver->getVideoDriver();
|
||||
|
||||
if (!Mesh || !driver)
|
||||
return;
|
||||
|
||||
bool isTransparentPass =
|
||||
SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT;
|
||||
|
||||
++PassCount;
|
||||
|
||||
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
|
||||
Box = Mesh->getBoundingBox();
|
||||
|
||||
for (u32 i = 0; i<Mesh->getMeshBufferCount(); ++i)
|
||||
{
|
||||
scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i);
|
||||
if (mb)
|
||||
{
|
||||
TextureMatrix = getMaterial(i).getTextureMatrix(0);
|
||||
const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i];
|
||||
|
||||
video::IMaterialRenderer* rnd = driver->getMaterialRenderer(material.MaterialType);
|
||||
bool transparent = (rnd && rnd->isTransparent());
|
||||
|
||||
if (isTransparentPass != transparent)
|
||||
continue;
|
||||
if (irr_driver->getPhase() == DISPLACEMENT_PASS)
|
||||
{
|
||||
initvaostate(GLmeshes[i], material.MaterialType, false);
|
||||
drawDisplace(GLmeshes[i]);
|
||||
continue;
|
||||
}
|
||||
if (!isObject(material.MaterialType))
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Log::warn("material", "Unhandled (static) material type : %d", material.MaterialType);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// only render transparent buffer if this is the transparent render pass
|
||||
// and solid only in solid pass
|
||||
if (irr_driver->getPhase() == GLOW_PASS)
|
||||
{
|
||||
initvaostate(GLmeshes[i], material.MaterialType, TextureMatrix.isIdentity());
|
||||
drawGlow(GLmeshes[i]);
|
||||
}
|
||||
else if (irr_driver->getPhase() == SHADOW_PASS)
|
||||
{
|
||||
initvaostate(GLmeshes[i], material.MaterialType, TextureMatrix.isIdentity());
|
||||
drawShadow(GLmeshes[i], material.MaterialType);
|
||||
}
|
||||
else
|
||||
{
|
||||
irr_driver->IncreaseObjectCount();
|
||||
initvaostate(GLmeshes[i], material.MaterialType, TextureMatrix.isIdentity());
|
||||
if (transparent)
|
||||
drawTransparent(GLmeshes[i], material.MaterialType);
|
||||
else
|
||||
drawSolid(GLmeshes[i], material.MaterialType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
32
src/graphics/stkmeshscenenode.hpp
Normal file
32
src/graphics/stkmeshscenenode.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
#ifndef STKMESHSCENENODE_H
|
||||
#define STKMESHSCENENODE_H
|
||||
|
||||
#include "stkmesh.hpp"
|
||||
|
||||
class STKMeshSceneNode : public irr::scene::CMeshSceneNode
|
||||
{
|
||||
protected:
|
||||
std::vector<GLMesh> GLmeshes;
|
||||
core::matrix4 ModelViewProjectionMatrix, TransposeInverseModelView, TextureMatrix;
|
||||
core::vector3df windDir;
|
||||
void drawSolid(const GLMesh &mesh, video::E_MATERIAL_TYPE type);
|
||||
void drawTransparent(const GLMesh &mesh, video::E_MATERIAL_TYPE type);
|
||||
|
||||
// Misc passes shaders (glow, displace...)
|
||||
void drawGlow(const GLMesh &mesh);
|
||||
void drawDisplace(const GLMesh &mesh);
|
||||
void drawShadow(const GLMesh &mesh, video::E_MATERIAL_TYPE type);
|
||||
void createGLMeshes();
|
||||
void cleanGLMeshes();
|
||||
public:
|
||||
STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id,
|
||||
const irr::core::vector3df& position = irr::core::vector3df(0, 0, 0),
|
||||
const irr::core::vector3df& rotation = irr::core::vector3df(0, 0, 0),
|
||||
const irr::core::vector3df& scale = irr::core::vector3df(1.0f, 1.0f, 1.0f));
|
||||
virtual void render();
|
||||
virtual void setMesh(irr::scene::IMesh* mesh);
|
||||
void MovingTexture(unsigned, unsigned);
|
||||
~STKMeshSceneNode();
|
||||
};
|
||||
|
||||
#endif
|
11
src/main.cpp
11
src/main.cpp
@ -1126,11 +1126,11 @@ int main(int argc, char *argv[] )
|
||||
// Needs the kart and track directories to load potential challenges
|
||||
// in those dirs.
|
||||
unlock_manager = new UnlockManager();
|
||||
// Needs the unlock manager to initialise the game slots of all players
|
||||
PlayerManager::create();
|
||||
AchievementsManager::create();
|
||||
|
||||
// Needs the player manager
|
||||
AchievementsManager::get()->init();
|
||||
// Needs the unlock manager to initialise the game slots of all players
|
||||
// and the AchievementsManager to initialise the AchievementsStatus.
|
||||
PlayerManager::create();
|
||||
|
||||
GUIEngine::addLoadingIcon( irr_driver->getTexture(FileManager::GUI,
|
||||
"gui_lock.png" ) );
|
||||
@ -1394,11 +1394,12 @@ static void cleanSuperTuxKart()
|
||||
Online::RequestManager::deallocate();
|
||||
Online::ServersManager::deallocate();
|
||||
Online::ProfileManager::deallocate();
|
||||
AchievementsManager::deallocate();
|
||||
Online::CurrentUser::deallocate();
|
||||
GUIEngine::DialogQueue::deallocate();
|
||||
|
||||
AchievementsManager::destroy();
|
||||
Referee::cleanup();
|
||||
|
||||
if(ReplayPlay::get()) ReplayPlay::destroy();
|
||||
if(race_manager) delete race_manager;
|
||||
NewsManager::deallocate();
|
||||
|
@ -447,7 +447,8 @@ void World::terminateRace()
|
||||
}
|
||||
|
||||
PlayerManager::get()->getCurrentPlayer()->raceFinished();
|
||||
((MapAchievement *) AchievementsManager::get()->getActive()->getAchievement(1))->increase(getTrack()->getIdent(), 1);
|
||||
AchievementsStatus* status = PlayerManager::getCurrentAchievementsStatus();
|
||||
dynamic_cast<MapAchievement*>(status->getAchievement(1))->increase(getTrack()->getIdent(), 1);
|
||||
AchievementsManager::get()->onRaceEnd();
|
||||
|
||||
if (m_race_gui) m_race_gui->clearAllMessages();
|
||||
|
@ -20,20 +20,21 @@
|
||||
#include "online/current_user.hpp"
|
||||
|
||||
#include "achievements/achievements_manager.hpp"
|
||||
#include "addons/addons_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "online/servers_manager.hpp"
|
||||
#include "online/profile_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
#include "addons/addon.hpp"
|
||||
#include "addons/addons_manager.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "guiengine/dialog_queue.hpp"
|
||||
#include "guiengine/screen.hpp"
|
||||
#include "online/servers_manager.hpp"
|
||||
#include "online/profile_manager.hpp"
|
||||
#include "states_screens/login_screen.hpp"
|
||||
#include "states_screens/dialogs/change_password_dialog.hpp"
|
||||
#include "states_screens/dialogs/user_info_dialog.hpp"
|
||||
#include "states_screens/dialogs/notification_dialog.hpp"
|
||||
#include "states_screens/online_profile_friends.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <stdlib.h>
|
||||
@ -197,13 +198,12 @@ namespace Online
|
||||
UserConfigParams::m_saved_session = true;
|
||||
}
|
||||
ProfileManager::get()->addPersistent(m_profile);
|
||||
AchievementsManager::get()->updateCurrentPlayer();
|
||||
std::string achieved_string("");
|
||||
if(input->get("achieved", &achieved_string) == 1)
|
||||
{
|
||||
std::vector<uint32_t> achieved_ids =
|
||||
StringUtils::splitToUInt(achieved_string, ' ');
|
||||
AchievementsManager::get()->getActive()->sync(achieved_ids);
|
||||
PlayerManager::getCurrentAchievementsStatus()->sync(achieved_ids);
|
||||
}
|
||||
m_profile->fetchFriends();
|
||||
} // if success
|
||||
@ -248,7 +248,6 @@ namespace Online
|
||||
UserConfigParams::m_saved_user = 0;
|
||||
UserConfigParams::m_saved_token = "";
|
||||
UserConfigParams::m_saved_session = false;
|
||||
AchievementsManager::get()->updateCurrentPlayer();
|
||||
} // signOut
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include "achievements/achievements_manager.hpp"
|
||||
#include "animations/three_d_animation.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/player_profile.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/stars.hpp"
|
||||
@ -257,8 +259,12 @@ void Physics::update(float dt)
|
||||
if(type != PowerupManager::POWERUP_BOWLING || !target_kart->isInvulnerable())
|
||||
{
|
||||
p->getUserPointer(0)->getPointerFlyable()->hit(target_kart);
|
||||
if ( type ==PowerupManager::POWERUP_BOWLING )
|
||||
((SingleAchievement *) AchievementsManager::get()->getActive()->getAchievement(2))->increase(1);
|
||||
if (type == PowerupManager::POWERUP_BOWLING)
|
||||
{
|
||||
AchievementsStatus* status =
|
||||
PlayerManager::getCurrentAchievementsStatus();
|
||||
((SingleAchievement *) status->getAchievement(2))->increase(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,7 +17,9 @@
|
||||
|
||||
#include "states_screens/online_profile_achievements.hpp"
|
||||
|
||||
#include "achievements/achievement_info.hpp"
|
||||
#include "achievements/achievements_manager.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "guiengine/engine.hpp"
|
||||
#include "guiengine/scalable_font.hpp"
|
||||
#include "guiengine/screen.hpp"
|
||||
@ -81,7 +83,9 @@ void OnlineProfileAchievements::init()
|
||||
{
|
||||
m_waiting_for_achievements = false;
|
||||
m_achievements_list_widget->clear();
|
||||
const std::map<uint32_t, Achievement *> & all_achievements = AchievementsManager::get()->getActive()->getAllAchievements();
|
||||
const std::map<uint32_t, Achievement *> & all_achievements =
|
||||
PlayerManager::get()->getCurrentPlayer()->getAchievementsStatus()
|
||||
->getAllAchievements();
|
||||
std::map<uint32_t, Achievement *>::const_iterator it;
|
||||
for (it = all_achievements.begin(); it != all_achievements.end(); ++it )
|
||||
{
|
||||
@ -108,7 +112,9 @@ void OnlineProfileAchievements::eventCallback(Widget* widget, const std::string&
|
||||
{
|
||||
m_selected_achievement_index = m_achievements_list_widget->getSelectionID();
|
||||
|
||||
new MessageDialog(AchievementsManager::get()->getAchievementInfo(atoi(m_achievements_list_widget->getSelectionInternalName().c_str()))->getDescription());
|
||||
int id;
|
||||
StringUtils::fromString(m_achievements_list_widget->getSelectionInternalName(), id);
|
||||
new MessageDialog(AchievementsManager::get()->getAchievementInfo(id)->getDescription());
|
||||
}
|
||||
} // eventCallback
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user