Merge remote-tracking branch 'upstream/master'

This commit is contained in:
KroArtem 2014-02-23 19:41:00 +04:00
commit 30977b7913
33 changed files with 1044 additions and 894 deletions

View File

@ -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;

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}
}

View 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();
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
// ----------------------------------------------------------------------------

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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 &center, 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

View File

@ -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 &center, const core::vector2df &direction, float mask_radius, float max_tex_height, unsigned TU_cb);
};
}
namespace UIShader

View File

@ -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);

View File

@ -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);
}
}
}
}

View File

@ -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

View 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);
}
}
}
}

View 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

View File

@ -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();

View File

@ -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();

View File

@ -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
// ------------------------------------------------------------------------

View File

@ -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);
}
}
}

View File

@ -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