This commit is contained in:
hiker 2016-04-26 12:50:51 +10:00
commit 031ae27919
37 changed files with 27280 additions and 255 deletions

View File

@ -1,4 +1,16 @@
## SupertTuxKart 0.9.1 ## SuperTuxKart 0.9.2
* Ghost replay races by Benau
* Battle mode AI by Benau
* Soccer mode AI by Benau
* New subsea track by samuncle
* TTF font rendering by Benau
* Kart properties refactor by Flakebi
* Scripting work under the hood
* Work on the track editor by mhp
* Tweak to challenges
* Bugfixes
## SuperTuxKart 0.9.1
* Many bug fixes * Many bug fixes
* Started to use scripting in tracks * Started to use scripting in tracks
* Significant audio performance improvements * Significant audio performance improvements

View File

@ -16,6 +16,7 @@ First, make sure that you have the following packages installed:
* OpenAL (recommended: openal-soft-devel) * OpenAL (recommended: openal-soft-devel)
* Ogg (libogg-dev) * Ogg (libogg-dev)
* Vorbis (libvorbis-dev) * Vorbis (libvorbis-dev)
* Freetype (libfreetype6-dev)
* libcurl (libcurl-devel) * libcurl (libcurl-devel)
* libbluetooth (bluez-devel) * libbluetooth (bluez-devel)
* libpng (libpng-devel) * libpng (libpng-devel)
@ -26,7 +27,7 @@ Ubuntu command:
``` ```
sudo apt-get install autoconf automake build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev \ sudo apt-get install autoconf automake build-essential cmake libogg-dev libvorbis-dev libopenal-dev libxxf86vm-dev \
libgl1-mesa-dev libglu1-mesa-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev libxrandr-dev libgl1-mesa-dev libglu1-mesa-dev libcurl4-openssl-dev libfribidi-dev libbluetooth-dev libxrandr-dev libfreetype6-dev
``` ```
Unpack the files from the tarball like this: Unpack the files from the tarball like this:

Binary file not shown.

View File

@ -1,19 +1,19 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<challenge version="2"> <challenge version="2">
<track id="subsea" laps="2"/> <track id="abyss" laps="3"/>
<mode major="single" minor="quickrace"/> <mode major="single" minor="quickrace"/>
<requirements trophies="0"/> <requirements trophies="0"/>
<hard> <hard>
<karts number="5"/> <karts number="5"/>
<requirements position="1" time="205"/> <requirements position="1" time="160"/>
</hard> </hard>
<medium> <medium>
<karts number="4"/> <karts number="4"/>
<requirements time="258"/> <requirements time="185"/>
</medium> </medium>
<easy> <easy>
<karts number="4"/> <karts number="4"/>
<requirements time="330"/> <requirements time="270"/>
</easy> </easy>
</challenge> </challenge>

View File

@ -4,7 +4,7 @@
<track id="sandtrack" laps="3" reverse="false" /> <track id="sandtrack" laps="3" reverse="false" />
<track id="farm" laps="3" reverse="false" /> <track id="farm" laps="3" reverse="false" />
<track id="olivermath" laps="4" reverse="false" /> <track id="olivermath" laps="4" reverse="false" />
<track id="subsea" laps="2" reverse="false" /> <track id="abyss" laps="3" reverse="false" />
<track id="scotland" laps="3" reverse="false" /> <track id="scotland" laps="3" reverse="false" />
</supertuxkart_grand_prix> </supertuxkart_grand_prix>

View File

@ -12,7 +12,15 @@
<list id="replay_list" x="0" y="0" width="100%" height="100%"/> <list id="replay_list" x="0" y="0" width="100%" height="100%"/>
</box> </box>
<spacer width="100%" height="2%" /> <div width="99%" align="center" layout="vertical-row" height="fit">
<button x="1%" id="record-ghost" I18N="In the ghost replay selection screen" text="Record ghost replay" /> <div width="100%" height="fit" layout="horizontal-row" >
<checkbox width="fit" id="replay_difficulty_toggle" text_align="left"/>
<spacer width="10"/>
<label proportion="1" height="100%" text_align="left" I18N="In the ghost replay selection screen" text="Only show replays matching the current difficulty"/>
</div>
</div>
<spacer width="100%" height="1%" />
<button x="1%" id="record-ghost" I18N="In the ghost replay selection screen" text="Record ghost replay"/>
</div> </div>
</stkgui> </stkgui>

View File

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<stkgui> <stkgui>
<div x="2%" y="2%" width="96%" height="96%" layout="horizontal-row"> <div x="2%" y="2%" width="96%" height="96%" layout="vertical-row">
<button id="continue" width="250" align="bottom" text="Continue"/> <spacer proportion="1"/>
<spacer width="20"/> <button id="save" width="450" align="center" text="Save Grand Prix"/>
<button id="save" width="250" align="bottom" text="Save Grand Prix"/> <spacer height="20"/>
<button id="continue" width="450" align="center" text="Continue"/>
</div> </div>
</stkgui> </stkgui>

View File

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<stkgui> <stkgui>
<div x="2%" y="2%" width="96%" height="96%" layout="horizontal-row"> <div x="2%" y="2%" width="96%" height="96%" layout="vertical-row">
<button id="continue" width="250" align="bottom" text="Continue"/> <spacer proportion="1"/>
<spacer width="20"/> <button id="save" width="450" align="center" text="Save Grand Prix"/>
<button id="save" width="250" align="bottom" text="Save Grand Prix"/> <spacer height="20"/>
<button id="continue" width="450" align="center" text="Continue"/>
</div> </div>
</stkgui> </stkgui>

View File

@ -13,7 +13,7 @@
square_items="true" child_width="128" child_height="128" /> square_items="true" child_width="128" child_height="128" />
<spacer height="15" width="10"/> <spacer height="15" width="10"/>
<div width="90%" align="center" layout="vertical-row" height="fit"> <div width="90%" align="center" layout="vertical-row" proportion="1">
<div width="100%" height="fit" layout="horizontal-row" > <div width="100%" height="fit" layout="horizontal-row" >
<checkbox width="fit" id="online" I18N="In the user screen" text_align="left"/> <checkbox width="fit" id="online" I18N="In the user screen" text_align="left"/>
<spacer width="10"/> <spacer width="10"/>
@ -44,15 +44,16 @@
I18N="In the user screen" text="Password"/> I18N="In the user screen" text="Password"/>
<textbox id="password" proportion="2" height="fit" I18N="In the user screen"/> <textbox id="password" proportion="2" height="fit" I18N="In the user screen"/>
</div> </div>
</div>
<div width="80%" align="center" layout="vertical-row" height="fit"> <spacer height="20" width="20"/>
<label id="message" width="80%" align="center" text_align="left"/>
<label id="message" width="100%" text_align="center"/>
</div> </div>
<spacer width="20" proportion="1"/> <spacer width="20" proportion="1"/>
<div width="90%" align="center" layout="vertical-row" height="13%" height="fit" align="bottom"> <div width="90%" align="center" layout="vertical-row" height="fit">
<buttonbar id="options" width="100%" height="100%" align="center"> <buttonbar id="options" width="100%" height="80" align="center">
<icon-button id="ok" width="64" height="64" icon="gui/green_check.png" <icon-button id="ok" width="64" height="64" icon="gui/green_check.png"
I18N="In the user screen" text="OK" label_location="bottom"/> I18N="In the user screen" text="OK" label_location="bottom"/>
<icon-button id="new_user" width="64" height="64" icon="gui/blue_plus.png" <icon-button id="new_user" width="64" height="64" icon="gui/blue_plus.png"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -966,6 +966,21 @@ void Material::setMaterialProperties(video::SMaterial *m, scene::IMeshBuffer* m
} }
#endif #endif
if (race_manager->getReverseTrack() &&
m_mirror_axis_when_reverse != ' ')
{
irr::video::S3DVertex* mbVertices = (video::S3DVertex*)mb->getVertices();
for (unsigned int i = 0; i < mb->getVertexCount(); i++)
{
core::vector2df &tc = mb->getTCoords(i);
if (m_mirror_axis_when_reverse == 'V')
tc.Y = 1 - tc.Y;
else
tc.X = 1 - tc.X;
}
} // reverse track and texture needs mirroring
} // setMaterialProperties } // setMaterialProperties
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -123,6 +123,7 @@ FileManager::FileManager()
m_subdir_name[LIBRARY ] = "library"; m_subdir_name[LIBRARY ] = "library";
m_subdir_name[MODEL ] = "models"; m_subdir_name[MODEL ] = "models";
m_subdir_name[MUSIC ] = "music"; m_subdir_name[MUSIC ] = "music";
m_subdir_name[REPLAY ] = "replay";
m_subdir_name[SCRIPT ] = "tracks"; m_subdir_name[SCRIPT ] = "tracks";
m_subdir_name[SFX ] = "sfx"; m_subdir_name[SFX ] = "sfx";
m_subdir_name[SKIN ] = "skins"; m_subdir_name[SKIN ] = "skins";

View File

@ -48,7 +48,7 @@ public:
* The last entry ASSET_COUNT specifies the number of entries. */ * The last entry ASSET_COUNT specifies the number of entries. */
enum AssetType {ASSET_MIN, enum AssetType {ASSET_MIN,
CHALLENGE=ASSET_MIN, CHALLENGE=ASSET_MIN,
GFX, GRANDPRIX, GUI, LIBRARY, MODEL, MUSIC, GFX, GRANDPRIX, GUI, LIBRARY, MODEL, MUSIC, REPLAY,
SCRIPT, SFX, SHADER, SKIN, TEXTURE, TTF, SCRIPT, SFX, SHADER, SKIN, TEXTURE, TTF,
TRANSLATION, ASSET_MAX = TRANSLATION, TRANSLATION, ASSET_MAX = TRANSLATION,
ASSET_COUNT}; ASSET_COUNT};
@ -138,7 +138,13 @@ public:
bool abort_on_error=false) const; bool abort_on_error=false) const;
std::string getAsset(AssetType type, const std::string &name) const; std::string getAsset(AssetType type, const std::string &name) const;
std::string getAsset(const std::string &name) const; std::string getAsset(const std::string &name) const;
// ------------------------------------------------------------------------
/** Returns the directory of an asset. */
std::string getAssetDirectory(AssetType type) const
{
return m_subdir_name[type];
}
// ------------------------------------------------------------------------
std::string searchMusic(const std::string& file_name) const; std::string searchMusic(const std::string& file_name) const;
std::string searchTexture(const std::string& fname) const; std::string searchTexture(const std::string& fname) const;
std::string getUserConfigFile(const std::string& fname) const; std::string getUserConfigFile(const std::string& fname) const;

View File

@ -112,6 +112,7 @@ void GhostKart::update(float dt)
center_shift = getTrans().getBasis() * center_shift; center_shift = getTrans().getBasis() * center_shift;
Moveable::updateGraphics(dt, center_shift, btQuaternion(0, 0, 0, 1)); Moveable::updateGraphics(dt, center_shift, btQuaternion(0, 0, 0, 1));
Moveable::updatePosition();
getKartModel()->update(dt, dt*(m_all_physic_info[idx].m_speed), getKartModel()->update(dt, dt*(m_all_physic_info[idx].m_speed),
m_all_physic_info[idx].m_steer, m_all_physic_info[idx].m_speed, idx); m_all_physic_info[idx].m_steer, m_all_physic_info[idx].m_speed, idx);

View File

@ -128,7 +128,18 @@ void Moveable::update(float dt)
{ {
if(m_body->getInvMass()!=0) if(m_body->getInvMass()!=0)
m_motion_state->getWorldTransform(m_transform); m_motion_state->getWorldTransform(m_transform);
m_velocityLC = getVelocity()*m_transform.getBasis(); m_velocityLC = getVelocity()*m_transform.getBasis();
updatePosition();
updateGraphics(dt, Vec3(0,0,0), btQuaternion(0, 0, 0, 1));
} // update
//-----------------------------------------------------------------------------
/** Updates the current position and rotation. This function is also called
* by ghost karts for getHeading() to work.
*/
void Moveable::updatePosition()
{
Vec3 forw_vec = m_transform.getBasis().getColumn(0); Vec3 forw_vec = m_transform.getBasis().getColumn(0);
m_heading = -atan2f(forw_vec.getZ(), forw_vec.getX()); m_heading = -atan2f(forw_vec.getZ(), forw_vec.getX());
@ -138,9 +149,7 @@ void Moveable::update(float dt)
Vec3 up = getTrans().getBasis().getColumn(1); Vec3 up = getTrans().getBasis().getColumn(1);
m_pitch = atan2(up.getZ(), fabsf(up.getY())); m_pitch = atan2(up.getZ(), fabsf(up.getY()));
m_roll = atan2(up.getX(), up.getY()); m_roll = atan2(up.getX(), up.getY());
} // updatePosition
updateGraphics(dt, Vec3(0,0,0), btQuaternion(0, 0, 0, 1));
} // update
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Creates the bullet rigid body for this moveable. /** Creates the bullet rigid body for this moveable.

View File

@ -110,6 +110,7 @@ public:
const btTransform const btTransform
&getTrans() const {return m_transform;} &getTrans() const {return m_transform;}
void setTrans(const btTransform& t); void setTrans(const btTransform& t);
void updatePosition();
} }
; // class Moveable ; // class Moveable

View File

@ -40,7 +40,6 @@ ReplayPlay *ReplayPlay::m_replay_play = NULL;
ReplayPlay::ReplayPlay() ReplayPlay::ReplayPlay()
{ {
m_current_replay_file = 0; m_current_replay_file = 0;
m_custom_replay_file = false;
} // ReplayPlay } // ReplayPlay
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -64,6 +63,22 @@ void ReplayPlay::reset()
void ReplayPlay::loadAllReplayFile() void ReplayPlay::loadAllReplayFile()
{ {
m_replay_file_list.clear(); m_replay_file_list.clear();
// Load stock replay first
std::set<std::string> pre_record;
file_manager->listFiles(pre_record, file_manager
->getAssetDirectory(FileManager::REPLAY), /*is_full_path*/ true);
for (std::set<std::string>::iterator i = pre_record.begin();
i != pre_record.end(); ++i)
{
if (!addReplayFile(*i, /*custom_replay*/ true))
{
// Skip invalid replay file
continue;
}
}
// Now user recorded replay
std::set<std::string> files; std::set<std::string> files;
file_manager->listFiles(files, file_manager->getReplayDir(), file_manager->listFiles(files, file_manager->getReplayDir(),
/*is_full_path*/ false); /*is_full_path*/ false);
@ -77,13 +92,12 @@ void ReplayPlay::loadAllReplayFile()
continue; continue;
} }
} }
} // loadAllReplayFile } // loadAllReplayFile
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool ReplayPlay::addReplayFile(const std::string& fn, bool custom_replay) bool ReplayPlay::addReplayFile(const std::string& fn, bool custom_replay)
{ {
// custom_replay is true when full path of filename is given
m_custom_replay_file = custom_replay;
char s[1024], s1[1024]; char s[1024], s1[1024];
if (StringUtils::getExtension(fn) != "replay") return false; if (StringUtils::getExtension(fn) != "replay") return false;
@ -92,6 +106,8 @@ bool ReplayPlay::addReplayFile(const std::string& fn, bool custom_replay)
if (fd == NULL) return false; if (fd == NULL) return false;
ReplayData rd; ReplayData rd;
// custom_replay is true when full path of filename is given
rd.m_custom_replay_file = custom_replay;
rd.m_filename = fn; rd.m_filename = fn;
fgets(s, 1023, fd); fgets(s, 1023, fd);
@ -196,7 +212,8 @@ void ReplayPlay::load()
m_ghost_karts.clearAndDeleteAll(); m_ghost_karts.clearAndDeleteAll();
char s[1024]; char s[1024];
FILE *fd = openReplayFile(/*writeable*/false, m_custom_replay_file); FILE *fd = openReplayFile(/*writeable*/false,
m_replay_file_list.at(m_current_replay_file).m_custom_replay_file);
if(!fd) if(!fd)
{ {
Log::error("Replay", "Can't read '%s', ghost replay disabled.", Log::error("Replay", "Can't read '%s', ghost replay disabled.",

View File

@ -55,6 +55,7 @@ public:
std::string m_track_name; std::string m_track_name;
std::vector<std::string> m_kart_list; std::vector<std::string> m_kart_list;
bool m_reverse; bool m_reverse;
bool m_custom_replay_file;
unsigned int m_difficulty; unsigned int m_difficulty;
unsigned int m_laps; unsigned int m_laps;
float m_min_time; float m_min_time;
@ -93,8 +94,6 @@ private:
unsigned int m_current_replay_file; unsigned int m_current_replay_file;
bool m_custom_replay_file;
std::vector<ReplayData> m_replay_file_list; std::vector<ReplayData> m_replay_file_list;
/** All ghost karts. */ /** All ghost karts. */

View File

@ -93,7 +93,7 @@ namespace Scripting
FILE *f = fopen(script_path.c_str(), "rb"); FILE *f = fopen(script_path.c_str(), "rb");
if (f == NULL) if (f == NULL)
{ {
Log::debug("Scripting", "File does not exist : {0}", script_path.c_str()); Log::debug("Scripting", "File does not exist : %s", script_path.c_str());
return ""; return "";
} }

View File

@ -112,14 +112,14 @@ namespace Scripting
scene::ISceneManager* sm = irr_driver->getSceneManager(); scene::ISceneManager* sm = irr_driver->getSceneManager();
scene::ISceneNode* sn = scene::ISceneNode* sn =
sm->addBillboardTextSceneNode(GUIEngine::getHighresDigitFont(), sm->addBillboardTextSceneNode(GUIEngine::getHighresDigitFont(),
wtext.c_str(), wtext.c_str(),
NULL, NULL,
core::dimension2df(textsize.Width / 35.0f, core::dimension2df(textsize.Width / 35.0f,
textsize.Height / 35.0f), textsize.Height / 35.0f),
xyz, xyz,
-1, // id -1, // id
GUIEngine::getSkin()->getColor("font::bottom"), GUIEngine::getSkin()->getColor("font::bottom"),
GUIEngine::getSkin()->getColor("font::top")); GUIEngine::getSkin()->getColor("font::top"));
World::getWorld()->getTrack()->addNode(sn); World::getWorld()->getTrack()->addNode(sn);
} }
} }
@ -145,6 +145,11 @@ namespace Scripting
return race_manager->getNumLocalPlayers(); return race_manager->getNumLocalPlayers();
} }
bool isTrackReverse()
{
return race_manager->getReverseTrack();
}
void setFog(float maxDensity, float start, float end, int r, int g, int b, float duration) void setFog(float maxDensity, float start, float end, int r, int g, int b, float duration)
{ {
PropertyAnimator* animator = PropertyAnimator::get(); PropertyAnimator* animator = PropertyAnimator::get();
@ -377,6 +382,7 @@ namespace Scripting
r = engine->RegisterGlobalFunction("void setFog(float maxDensity, float start, float end, int r, int g, int b, float duration)", asFUNCTION(setFog), asCALL_CDECL); assert(r >= 0); r = engine->RegisterGlobalFunction("void setFog(float maxDensity, float start, float end, int r, int g, int b, float duration)", asFUNCTION(setFog), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("int getNumberOfKarts()", asFUNCTION(getNumberOfKarts), asCALL_CDECL); assert(r >= 0); r = engine->RegisterGlobalFunction("int getNumberOfKarts()", asFUNCTION(getNumberOfKarts), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("int getNumLocalPlayers()", asFUNCTION(getNumLocalPlayers), asCALL_CDECL); assert(r >= 0); r = engine->RegisterGlobalFunction("int getNumLocalPlayers()", asFUNCTION(getNumLocalPlayers), asCALL_CDECL); assert(r >= 0);
r = engine->RegisterGlobalFunction("bool isReverse()", asFUNCTION(isTrackReverse), asCALL_CDECL); assert(r >= 0);
// TrackObject // TrackObject
r = engine->RegisterObjectMethod("TrackObject", "void setEnabled(bool status)", asMETHOD(::TrackObject, setEnabled), asCALL_THISCALL); assert(r >= 0); r = engine->RegisterObjectMethod("TrackObject", "void setEnabled(bool status)", asMETHOD(::TrackObject, setEnabled), asCALL_THISCALL); assert(r >= 0);

View File

@ -39,10 +39,15 @@ GhostReplayInfoDialog::GhostReplayInfoDialog(unsigned int replay_id)
LabelWidget *name = getWidget<LabelWidget>("name"); LabelWidget *name = getWidget<LabelWidget>("name");
assert(name); assert(name);
name->setText(stringw((m_rd.m_filename).c_str()), false); name->setText(stringw((m_rd.m_custom_replay_file ? StringUtils::getBasename
(m_rd.m_filename) : m_rd.m_filename).c_str()), false);
m_back_widget = getWidget<IconButtonWidget>("back"); m_back_widget = getWidget<IconButtonWidget>("back");
m_back_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER); m_back_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
// Non-deletable for custom (standard) replay file
getWidget<IconButtonWidget>("remove")->setActive(!m_rd.m_custom_replay_file);
m_action_widget = getWidget<RibbonWidget>("actions"); m_action_widget = getWidget<RibbonWidget>("actions");
m_record_widget = getWidget<CheckBoxWidget>("record-race"); m_record_widget = getWidget<CheckBoxWidget>("record-race");
m_watch_widget = getWidget<CheckBoxWidget>("watch-only"); m_watch_widget = getWidget<CheckBoxWidget>("watch-only");
@ -76,8 +81,8 @@ GUIEngine::EventPropagation
if(selection == "start") if(selection == "start")
{ {
bool reverse = m_rd.m_reverse; bool reverse = m_rd.m_reverse;
std::string track_name = m_rd.m_track_name; std::string track_name = m_rd.m_track_name;
int laps = m_rd.m_laps; int laps = m_rd.m_laps;
int replay_id = m_replay_id; int replay_id = m_replay_id;

View File

@ -62,6 +62,10 @@ void GhostReplaySelection::loadedFromFile()
m_replay_list_widget = getWidget<GUIEngine::ListWidget>("replay_list"); m_replay_list_widget = getWidget<GUIEngine::ListWidget>("replay_list");
assert(m_replay_list_widget != NULL); assert(m_replay_list_widget != NULL);
m_replay_list_widget->setColumnListener(this); m_replay_list_widget->setColumnListener(this);
m_replay_difficulty_toggle_widget =
getWidget<GUIEngine::CheckBoxWidget>("replay_difficulty_toggle");
m_replay_difficulty_toggle_widget->setState(true);
m_same_difficulty = m_replay_difficulty_toggle_widget->getState();
} // loadedFromFile } // loadedFromFile
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -82,6 +86,7 @@ void GhostReplaySelection::beforeAddingWidget()
void GhostReplaySelection::init() void GhostReplaySelection::init()
{ {
Screen::init(); Screen::init();
m_cur_difficulty = race_manager->getDifficulty();
refresh(/*forced_update*/false); refresh(/*forced_update*/false);
} // init } // init
@ -97,6 +102,10 @@ void GhostReplaySelection::loadList()
{ {
const ReplayPlay::ReplayData& rd = ReplayPlay::get()->getReplayData(i); const ReplayPlay::ReplayData& rd = ReplayPlay::get()->getReplayData(i);
if (m_same_difficulty && m_cur_difficulty !=
(RaceManager::Difficulty)rd.m_difficulty)
continue;
std::vector<GUIEngine::ListWidget::ListCell> row; std::vector<GUIEngine::ListWidget::ListCell> row;
Track* t = track_manager->getTrack(rd.m_track_name); Track* t = track_manager->getTrack(rd.m_track_name);
row.push_back(GUIEngine::ListWidget::ListCell row.push_back(GUIEngine::ListWidget::ListCell
@ -113,7 +122,7 @@ void GhostReplaySelection::loadList()
(StringUtils::toWString(rd.m_laps), -1, 1, true)); (StringUtils::toWString(rd.m_laps), -1, 1, true));
row.push_back(GUIEngine::ListWidget::ListCell row.push_back(GUIEngine::ListWidget::ListCell
(StringUtils::toWString(rd.m_min_time) + L"s", -1, 1, true)); (StringUtils::toWString(rd.m_min_time) + L"s", -1, 1, true));
m_replay_list_widget->addItem("replay", row); m_replay_list_widget->addItem(StringUtils::toString(i), row);
} }
} // loadList } // loadList
@ -132,11 +141,13 @@ void GhostReplaySelection::eventCallback(GUIEngine::Widget* widget,
} }
else if (name == m_replay_list_widget->m_properties[GUIEngine::PROP_ID]) else if (name == m_replay_list_widget->m_properties[GUIEngine::PROP_ID])
{ {
int selected_index = m_replay_list_widget->getSelectionID(); int selected_index = -1;
const bool success = StringUtils::fromString(m_replay_list_widget
->getSelectionInternalName(), selected_index);
// This can happen e.g. when the list is empty and the user // This can happen e.g. when the list is empty and the user
// clicks somewhere. // clicks somewhere.
if (selected_index >= (signed)ReplayPlay::get()->getNumReplayFile() || if (selected_index >= (signed)ReplayPlay::get()->getNumReplayFile() ||
selected_index < 0) selected_index < 0 || !success)
{ {
return; return;
} }
@ -148,6 +159,11 @@ void GhostReplaySelection::eventCallback(GUIEngine::Widget* widget,
TracksScreen::getInstance()->setOfficalTrack(false); TracksScreen::getInstance()->setOfficalTrack(false);
TracksScreen::getInstance()->push(); TracksScreen::getInstance()->push();
} }
else if (name == "replay_difficulty_toggle")
{
m_same_difficulty = m_replay_difficulty_toggle_widget->getState();
refresh(/*forced_update*/false);
}
} // eventCallback } // eventCallback

View File

@ -21,6 +21,7 @@
#include "guiengine/screen.hpp" #include "guiengine/screen.hpp"
#include "guiengine/widgets.hpp" #include "guiengine/widgets.hpp"
#include "race/race_manager.hpp"
#include "states_screens/dialogs/message_dialog.hpp" #include "states_screens/dialogs/message_dialog.hpp"
namespace GUIEngine { class Widget; } namespace GUIEngine { class Widget; }
@ -41,9 +42,12 @@ private:
GhostReplaySelection(); GhostReplaySelection();
~GhostReplaySelection(); ~GhostReplaySelection();
GUIEngine::ListWidget* m_replay_list_widget; GUIEngine::ListWidget* m_replay_list_widget;
std::string m_file_to_be_deleted; GUIEngine::CheckBoxWidget* m_replay_difficulty_toggle_widget;
bool m_sort_desc; RaceManager::Difficulty m_cur_difficulty;
std::string m_file_to_be_deleted;
bool m_same_difficulty;
bool m_sort_desc;
public: public:

View File

@ -52,6 +52,7 @@
using namespace irr::core; using namespace irr::core;
using namespace irr::gui; using namespace irr::gui;
using namespace irr::video; using namespace irr::video;
using namespace GUIEngine;
const float DURATION = 15.0f; const float DURATION = 15.0f;
@ -112,6 +113,8 @@ void GrandPrixLose::init()
m_phase = 1; m_phase = 1;
m_global_time = 0.0f; m_global_time = 0.0f;
getWidget<ButtonWidget>("continue")->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
} // init } // init
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------

View File

@ -55,6 +55,7 @@
using namespace irr::core; using namespace irr::core;
using namespace irr::gui; using namespace irr::gui;
using namespace irr::video; using namespace irr::video;
using namespace GUIEngine;
const float KARTS_X = -0.95f; const float KARTS_X = -0.95f;
const float KARTS_DELTA_X = 1.9f; const float KARTS_DELTA_X = 1.9f;
@ -172,6 +173,7 @@ void GrandPrixWin::init()
m_phase = 1; m_phase = 1;
SFXManager::get()->quickSound("gp_end"); SFXManager::get()->quickSound("gp_end");
getWidget<ButtonWidget>("continue")->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
} // init } // init
// ------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------

View File

@ -192,7 +192,7 @@ void TracksScreen::buildTrackList()
if (!(curr_group_name == DEFAULT_GROUP_NAME || if (!(curr_group_name == DEFAULT_GROUP_NAME ||
curr_group_name == ALL_TRACK_GROUPS_ID) && m_offical_track) curr_group_name == ALL_TRACK_GROUPS_ID) && m_offical_track)
{ {
tracks_widget->setText(_("Only Offical track is supported.")); tracks_widget->setText(_("Only official tracks are supported."));
tracks_widget->updateItemDisplay(); tracks_widget->updateItemDisplay();
return; return;
} }

View File

@ -930,18 +930,6 @@ void Track::convertTrackToBullet(scene::ISceneNode *node)
if (mb->getVertexType() == video::EVT_STANDARD) if (mb->getVertexType() == video::EVT_STANDARD)
{ {
irr::video::S3DVertex* mbVertices=(video::S3DVertex*)mb->getVertices(); irr::video::S3DVertex* mbVertices=(video::S3DVertex*)mb->getVertices();
if (race_manager->getReverseTrack() &&
material->getMirrorAxisInReverse() != ' ')
{
for (unsigned int i = 0; i < mb->getVertexCount(); i++)
{
core::vector2df &tc = mb->getTCoords(i);
if (material->getMirrorAxisInReverse() == 'V')
tc.Y = 1 - tc.Y;
else
tc.X = 1 - tc.X;
}
} // reverse track and texture needs mirroring
for (unsigned int matrix_index = 0; matrix_index < matrices.size(); matrix_index++) for (unsigned int matrix_index = 0; matrix_index < matrices.size(); matrix_index++)
{ {
for (unsigned int j = 0; j < mb->getIndexCount(); j += 3) for (unsigned int j = 0; j < mb->getIndexCount(); j += 3)