Merge branch 'master' of github.com:supertuxkart/stk-code

This commit is contained in:
hiker
2018-01-01 00:36:24 +11:00
63 changed files with 1163 additions and 328 deletions

1
.gitignore vendored
View File

@@ -60,6 +60,7 @@ android/bin
android/build
android/libs
android/obj
android/res
android/.gradle
android-*
*.apk

View File

@@ -143,38 +143,3 @@ you have to run:
and then:
zipalign -v 4 SuperTuxKart-release-unsigned.apk SuperTuxKart-release.apk
--------------------------------------------------------------------------------
KNOWN ISSUES
--------------------------------------------------------------------------------
1. It's not possible to compile STK for Android < 4.4 due to missing GLES 3.0
functions. It is technically possible to do - check GLES context version,
load OpenGL functions dynamically using EGL, and if they are not loaded
properly, then fallback to GLES 2.0.
2. It never ocurred for me, but it's possible that EGL context is lost in some
cases. SuperTuxKart is not designed to re-create all textures at any moment,
so this is a "Wontfix", at least for now.
3. We use "exit(0)" at the end of main function. We shouldn't do it and we
should just return from the main function. But STK uses some global
variables and their values are remembered when the game is restarted. We
should properly clear them or re-initialize on startup. Using the "exit(0)"
is not-that-bad workaround, but it may cause a crash on exit sometimes.
It seems to affect only Android 5.0. More information about the crash:
https://code.google.com/p/android/issues/detail?id=160824
4. STK crashes on startup on some devices when aarch64 build is made using
Android r13 NDK. The r13 version has rather big modifications (it uses clang
instead of gcc by default). This is probably a bug in NDK/compiler/OS, but
for this reason using NDK r12 for 64-bit arm compilation is preferred.
5. Angelscript doesn't have full support for aarch64 builds, so that scripting
won't work on this platform.
6. Turning left/right using accelerometer is available, but at this stage the
default screen orientation is not automatically detected and user must
manually choose if he needs "phone" or "tablet" accelerometer.

BIN
android/icon-dbg.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -36,6 +36,13 @@ export HOST_AARCH64=aarch64-linux-android
export NDK_PLATFORM_AARCH64=android-21
export SDK_VERSION_AARCH64=21
export APP_NAME_RELEASE="SuperTuxKart"
export APP_NAME_DEBUG="SuperTuxKart Debug"
export PACKAGE_NAME_RELEASE="org.supertuxkart.stk"
export PACKAGE_NAME_DEBUG="org.supertuxkart.stk_dev"
export APP_ICON_RELEASE="$DIRNAME/icon.png"
export APP_ICON_DEBUG="$DIRNAME/icon-dbg.png"
# A helper function that checks if error ocurred
check_error()
@@ -52,6 +59,7 @@ if [ ! -z "$1" ] && [ "$1" = "clean" ]; then
rm -rf build
rm -rf libs
rm -rf obj
rm -rf res
rm -rf .gradle
exit
fi
@@ -108,10 +116,16 @@ if [ "$BUILD_TYPE" = "debug" ] || [ "$BUILD_TYPE" = "Debug" ]; then
export ANT_BUILD_TYPE="debug"
export GRADLE_BUILD_TYPE="assembleDebug"
export IS_DEBUG_BUILD=1
export APP_NAME="$APP_NAME_DEBUG"
export PACKAGE_NAME="$PACKAGE_NAME_DEBUG"
export APP_ICON="$APP_ICON_DEBUG"
elif [ "$BUILD_TYPE" = "release" ] || [ "$BUILD_TYPE" = "Release" ]; then
export ANT_BUILD_TYPE="release"
export GRADLE_BUILD_TYPE="assembleRelease"
export IS_DEBUG_BUILD=0
export APP_NAME="$APP_NAME_RELEASE"
export PACKAGE_NAME="$PACKAGE_NAME_RELEASE"
export APP_ICON="$APP_ICON_RELEASE"
else
echo "Unsupported BUILD_TYPE: $BUILD_TYPE. Possible values are: " \
"debug, release"
@@ -342,8 +356,31 @@ check_error
# Build apk
echo "Building APK"
mkdir -p "$DIRNAME/res/drawable/"
mkdir -p "$DIRNAME/res/drawable-hdpi/"
mkdir -p "$DIRNAME/res/drawable-mdpi/"
mkdir -p "$DIRNAME/res/drawable-xhdpi/"
mkdir -p "$DIRNAME/res/drawable-xxhdpi/"
mkdir -p "$DIRNAME/res/values/"
STRINGS_FILE="$DIRNAME/res/values/strings.xml"
echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>" > "$STRINGS_FILE"
echo "<resources>" >> "$STRINGS_FILE"
echo " <string name=\"app_name\">$APP_NAME</string>" >> "$STRINGS_FILE"
echo "</resources>" >> "$STRINGS_FILE"
sed -i "s/minSdkVersion=\".*\"/minSdkVersion=\"$SDK_VERSION\"/g" \
"$DIRNAME/AndroidManifest.xml"
sed -i "s/package=\".*\"/package=\"$PACKAGE_NAME\"/g" \
"$DIRNAME/AndroidManifest.xml"
cp "$APP_ICON" "$DIRNAME/res/drawable/icon.png"
convert -scale 72x72 "$APP_ICON" "$DIRNAME/res/drawable-hdpi/icon.png"
convert -scale 48x48 "$APP_ICON" "$DIRNAME/res/drawable-mdpi/icon.png"
convert -scale 96x96 "$APP_ICON" "$DIRNAME/res/drawable-xhdpi/icon.png"
convert -scale 144x144 "$APP_ICON" "$DIRNAME/res/drawable-xxhdpi/icon.png"
if [ "$BUILD_TOOL" = "gradle" ]; then

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">SuperTuxKart</string>
</resources>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
<div x="1%" y="1%" width="98%" height="98%" layout="vertical-row" >
<header id="title" text_align="center" width="80%" align="center" text="Local Networking"/>
<spacer height="5%" width="10"/>
<icon id="logo" align="center" proportion="1" width="100%" icon="gui/logo.png"/>
<spacer height="5%" width="10"/>
<buttonbar id="lan" proportion="1" width="90%" align="center">
<icon-button id="find_lan_server" width="128" height="128"
icon="gui/online/menu_find_server.png" focus_icon="gui/online/menu_find_server_hover.png"
I18N="In the online multiplayer screen" text="Find Server"/>
<icon-button id="create_lan_server" width="128" height="128"
icon="gui/online/menu_create_server.png" focus_icon="gui/online/menu_create_server_hover.png"
I18N="In the online multiplayer screen" text="Create Server"/>
<!--
<icon-button id="manage_user" width="128" height="128"
icon="gui/options_players.png"
I18N="In the online multiplayer screen" text="Users"/>
-->
</buttonbar>
<spacer height="10%" width="10"/>
</div>
</stkgui>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<div x="0" y="0" width="100%" height="100%" layout="vertical-row" >
<header text_align="center" width="80%" align="center" text="Online"/>
<spacer height="15" width="10"/>
<button id="user-id" width="20%" height="fit" align="center"/>
<spacer height="15" width="10"/>
<icon id="logo" align="center" proportion="4" width="100%" icon="gui/logo.png"/>
<spacer height="15" width="10"/>
<buttonbar id="menu_toprow" proportion="3" width="90%" align="center">
<icon-button id="lan" width="128" height="128"
icon="gui/menu_multi.png" focus_icon="gui/menu_multi_focus.png"
I18N="Networking menu button" text="Local Networking"/>
<icon-button id="wan" width="128" height="128"
icon="gui/menu_multi.png" focus_icon="gui/menu_multi_focus.png"
I18N="Networking menu button" text="Global Networking"/>
<icon-button id="online" width="128" height="128"
icon="gui/menu_online.png" focus_icon="gui/menu_online_focus.png"
I18N="Networking menu button" text="Your profile"/>
</buttonbar>
<spacer height="10%" width="10"/>
</div>
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
</stkgui>

View File

@@ -9,7 +9,6 @@
<spacer height="25" width="10"/>
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"
I18N="Section in the profile screen" text="Achievements"/>
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png"/>

View File

@@ -9,7 +9,6 @@
<spacer height="25" width="10"/>
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"/>
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png"
I18N="Section in the profile screen" text="Friends"/>

View File

@@ -3,59 +3,25 @@
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
<div x="1%" y="1%" width="98%" height="98%" layout="vertical-row" >
<header id="title" text_align="center" width="80%" align="center" text="..."/>
<header id="title" text_align="center" width="80%" align="center" text="Global Networking"/>
<spacer height="25" width="10"/>
<spacer height="5%" width="10"/>
<icon id="logo" align="center" proportion="1" width="100%" icon="gui/logo.png"/>
<spacer height="5%" width="10"/>
<buttonbar id="wan" proportion="1" width="90%" align="center">
<icon-button id="find_wan_server" width="128" height="128"
icon="gui/online/menu_find_server.png" focus_icon="gui/online/menu_find_server_hover.png"
I18N="In the online multiplayer screen" text="Find Server"/>
<icon-button id="create_wan_server" width="128" height="128"
icon="gui/online/menu_create_server.png" focus_icon="gui/online/menu_create_server_hover.png"
I18N="In the online multiplayer screen" text="Create Server"/>
<icon-button id="quick_wan_play" width="128" height="128"
icon="gui/online/menu_quick_play.png" focus_icon="gui/online/menu_quick_play_hover.png"
I18N="In the online multiplayer screen" text="Quick Play"/>
</buttonbar>
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png" I18N="Section in the profile screen" text="Servers"/>
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"/>
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png" />
<icon-button id="tab_settings" width="128" height="128" icon="gui/main_options.png" />
</tabs>
<box proportion="1" width="100%" layout="vertical-row">
<div x="1%" y="2%" width="98%" height="96%" layout="vertical-row" >
<spacer height="5%" width="25"/>
<box width="100%" proportion="1" padding="10" layout="vertical-row">
<bright width="100%" text="Local Networking" align="center" text_align="left" />
<buttonbar id="lan" proportion="2" width="90%" align="center">
<icon-button id="find_lan_server" width="128" height="128"
icon="gui/online/menu_find_server.png" focus_icon="gui/online/menu_find_server_hover.png"
I18N="In the online multiplayer screen" text="Find Server"/>
<icon-button id="create_lan_server" width="128" height="128"
icon="gui/online/menu_create_server.png" focus_icon="gui/online/menu_create_server_hover.png"
I18N="In the online multiplayer screen" text="Create Server"/>
<!--
<icon-button id="manage_user" width="128" height="128"
icon="gui/options_players.png"
I18N="In the online multiplayer screen" text="Users"/>
-->
</buttonbar>
</box>
<spacer height="5%" width="25"/>
<box width="100%" proportion="1" padding="10" layout="vertical-row">
<bright width="100%" text="Global Networking" align="center" text_align="left" />
<buttonbar id="wan" proportion="2" width="90%" align="center">
<icon-button id="find_wan_server" width="128" height="128"
icon="gui/online/menu_find_server.png" focus_icon="gui/online/menu_find_server_hover.png"
I18N="In the online multiplayer screen" text="Find Server"/>
<icon-button id="create_wan_server" width="128" height="128"
icon="gui/online/menu_create_server.png" focus_icon="gui/online/menu_create_server_hover.png"
I18N="In the online multiplayer screen" text="Create Server"/>
<icon-button id="quick_wan_play" width="128" height="128"
icon="gui/online/menu_quick_play.png" focus_icon="gui/online/menu_quick_play_hover.png"
I18N="In the online multiplayer screen" text="Quick Play"/>
</buttonbar>
</box>
</div>
</box>
<spacer height="10%" width="10"/>
</div>
</stkgui>

View File

@@ -8,7 +8,6 @@
<spacer height="25" width="10"/>
<tabs id="profile_tabs" height="10%" max_height="110" x="2%" width="98%" align="center">
<icon-button id="tab_servers" width="128" height="128" icon="gui/main_network.png"/>
<icon-button id="tab_achievements" width="128" height="128" icon="gui/gp_copy.png"/>
<icon-button id="tab_friends" width="128" height="128" icon="gui/options_players.png" />
<icon-button id="tab_settings" width="128" height="128" icon="gui/main_options.png"

View File

@@ -182,6 +182,7 @@ namespace scene
virtual s32 getAnimationSet() const = 0;
virtual void addAnimationSet(u32 start, u32 end) = 0;
virtual void useAnimationSet(u32 set_num) = 0;
virtual void removeAllAnimationSet() = 0;
};
} // end namespace scene

View File

@@ -167,6 +167,7 @@ namespace scene
m_animation_set.push_back(start);
m_animation_set.push_back(end);
}
virtual void removeAllAnimationSet() { m_animation_set.clear(); }
virtual void useAnimationSet(u32 set_num);
virtual void setFrameLoopOnce(s32 begin, s32 end);
protected:

View File

@@ -694,6 +694,12 @@ bool CIrrDeviceLinux::createWindow()
visualAttrBuffer[17] = 0;
visualAttrBuffer[19] = 0;
}
if (CreationParams.HandleSRGB == false)
{
visualAttrBuffer[21] = GLX_DONT_CARE;
}
// first round with unchanged values
{
configList=glxChooseFBConfig(display, screennr, visualAttrBuffer,&nitems);

View File

@@ -68,7 +68,7 @@ namespace scene
//! constructor
CSkinnedMesh::CSkinnedMesh()
: SkinningBuffers(0), AnimationFrames(0.f), FramesPerSecond(25.f),
: AnimationFrames(0.f), SkinningBuffers(0), FramesPerSecond(25.f),
LastAnimatedFrame(-1), SkinnedLastFrame(false),
InterpolationMode(EIM_LINEAR),
HasAnimation(false), PreparedForSkinning(false),

View File

@@ -175,6 +175,8 @@ namespace scene
u32 getTotalJoints() const { return m_total_joints; }
f32 AnimationFrames;
private:
void toStaticPose();
@@ -215,7 +217,6 @@ private:
core::aabbox3d<f32> BoundingBox;
f32 AnimationFrames;
f32 FramesPerSecond;
f32 LastAnimatedFrame;

View File

@@ -1,5 +1,5 @@
# Modify this file to change the last-modified date when you add/remove a file.
# This will then trigger a new cmake run automatically.
# This will then trigger a new cmake run automatically.
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")

View File

@@ -47,7 +47,7 @@ ChallengeData::ChallengeData(const std::string& filename)
for (int d=0; d<RaceManager::DIFFICULTY_COUNT; d++)
{
m_num_karts[d] = -1;
m_default_num_karts[d] = -1;
m_position[d] = -1;
m_time[d] = -1.0f;
m_energy[d] = -1;
@@ -176,7 +176,7 @@ ChallengeData::ChallengeData(const std::string& filename)
int num_karts = -1;
if (!karts_node->get("number", &num_karts)) error("karts");
m_num_karts[d] = num_karts;
m_default_num_karts[d] = num_karts;
std::string replay_file;
if (karts_node->get("replay_file", &replay_file))
@@ -385,7 +385,7 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const
race_manager->setMinorMode(m_minor);
race_manager->setTrack(m_track_id);
race_manager->setNumLaps(m_num_laps);
race_manager->setNumKarts(m_num_karts[d]);
race_manager->setNumKarts(m_default_num_karts[d]);
race_manager->setNumPlayers(1);
race_manager->setCoinTarget(m_energy[d]);
race_manager->setDifficulty(d);
@@ -404,7 +404,7 @@ void ChallengeData::setRace(RaceManager::Difficulty d) const
race_manager->setMinorMode(m_minor);
race_manager->setGrandPrix(*grand_prix_manager->getGrandPrix(m_gp_id));
race_manager->setDifficulty(d);
race_manager->setNumKarts(m_num_karts[d]);
race_manager->setNumKarts(m_default_num_karts[d]);
race_manager->setNumPlayers(1);
}
@@ -448,7 +448,7 @@ bool ChallengeData::isChallengeFulfilled() const
if (kart->isEliminated() ) return false;
if (track_name != m_track_id ) return false;
if ((int)world->getNumKarts() < m_num_karts[d] ) return false;
if ((int)world->getNumKarts() < m_default_num_karts[d] ) return false;
if (m_energy[d] > 0 && kart->getEnergy() < m_energy[d] ) return false;
if (m_position[d] > 0 && kart->getPosition() > m_position[d]) return false;
@@ -495,7 +495,7 @@ bool ChallengeData::isGPFulfilled() const
if (race_manager->getMajorMode() != RaceManager::MAJOR_MODE_GRAND_PRIX ||
race_manager->getMinorMode() != m_minor ||
race_manager->getGrandPrix().getId() != m_gp_id ||
race_manager->getNumberOfKarts() < (unsigned int)m_num_karts[d] ||
race_manager->getNumberOfKarts() < (unsigned int)m_default_num_karts[d] ||
race_manager->getNumPlayers() > 1) return false;
// check if the player came first.

View File

@@ -84,7 +84,7 @@ private:
int m_num_laps;
int m_position[RaceManager::DIFFICULTY_COUNT];
int m_num_karts[RaceManager::DIFFICULTY_COUNT];
int m_default_num_karts[RaceManager::DIFFICULTY_COUNT];
std::string m_ai_kart_ident[RaceManager::DIFFICULTY_COUNT];
std::string m_replay_files[RaceManager::DIFFICULTY_COUNT];
float m_time[RaceManager::DIFFICULTY_COUNT];
@@ -208,7 +208,7 @@ public:
*/
int getNumKarts(RaceManager::Difficulty difficulty) const
{
return m_num_karts[difficulty];
return m_default_num_karts[difficulty];
} // getNumKarts
// ------------------------------------------------------------------------
/** Returns the maximum time in which the kart must finish.

View File

@@ -321,9 +321,129 @@ core::stringc ListUserConfigParam<T, U>::toString() const
return "";
} // toString
// ----------------------------------------------------------------------------
template<typename T, typename U>
MapUserConfigParam<T, U>::MapUserConfigParam(const char* param_name,
const char* comment)
{
m_param_name = param_name;
all_params.push_back(this);
if (comment != NULL) m_comment = comment;
} // MapUserConfigParam
// ----------------------------------------------------------------------------
template<typename T, typename U>
MapUserConfigParam<T, U>::MapUserConfigParam(const char* param_name,
const char* comment,
int nb_elements,
...)
{
m_param_name = param_name;
all_params.push_back(this);
if (comment != NULL) m_comment = comment;
// ============================================================================
// add the default list
va_list arguments;
va_start(arguments, nb_elements);
struct pair_type { T key; U value; };
for (int i = 0; i < nb_elements; i++)
{
pair_type key_value_pair = va_arg(arguments, pair_type);
m_elements.insert(std::pair<T, U>(key_value_pair.key, key_value_pair.value));
}
va_end(arguments); // Cleans up the list
} // MapUserConfigParam
// ----------------------------------------------------------------------------
template<typename T, typename U>
MapUserConfigParam<T, U>::MapUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment)
{
m_param_name = param_name;
group->addChild(this);
if (comment != NULL) m_comment = comment;
} // MapUserConfigParam
// ----------------------------------------------------------------------------
template<typename T, typename U>
MapUserConfigParam<T, U>::MapUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment,
int nb_elements,
...)
{
m_param_name = param_name;
group->addChild(this);
if (comment != NULL) m_comment = comment;
// add the default list
va_list arguments;
va_start(arguments, nb_elements);
struct pair_type { T key; U value; };
for (int i = 0; i < nb_elements; i++)
{
pair_type key_value_pair = va_arg(arguments, pair_type);
m_elements.insert(std::pair<T, U>(key_value_pair.key, key_value_pair.value));
}
va_end(arguments); // Cleans up the list
} // MapUserConfigParam
// ----------------------------------------------------------------------------
template<typename T, typename U>
void MapUserConfigParam<T, U>::write(std::ofstream& stream) const
{
// comment
if (m_comment.size() > 0) stream << " <!-- " << m_comment.c_str();
stream << " -->\n <" << m_param_name.c_str() << "\n";
for (const auto& kv : m_elements)
{
stream << " " << kv.first << "=\"" << kv.second << "\"\n";
}
stream << " >\n";
stream << " </" << m_param_name.c_str() << ">\n\n";
} // write
// ----------------------------------------------------------------------------
template<typename T, typename U>
void MapUserConfigParam<T, U>::findYourDataInAChildOf(const XMLNode* node)
{
const XMLNode* child = node->getNode(m_param_name);
if (child == NULL)
{
//Log::error("User Config", "Couldn't find parameter group %s", m_param_name.c_str());
return;
}
child->get(&m_elements);
} // findYourDataInAChildOf
// ----------------------------------------------------------------------------
template<typename T, typename U>
void MapUserConfigParam<T, U>::findYourDataInAnAttributeOf(const XMLNode* node)
{
} // findYourDataInAnAttributeOf
// ----------------------------------------------------------------------------
template<typename T, typename U>
void MapUserConfigParam<T, U>::addElement(T element, U value)
{
m_elements[element] = value;
} // findYourDataInAnAttributeOf
// ----------------------------------------------------------------------------
template<typename T, typename U>
core::stringc MapUserConfigParam<T, U>::toString() const
{
return "";
} // toString
// ----------------------------------------------------------------------------
IntUserConfigParam::IntUserConfigParam(int default_value,
const char* param_name,
const char* comment)

View File

@@ -136,6 +136,55 @@ public:
}; // ListUserConfigParam
typedef ListUserConfigParam<std::string, const char*> StringListUserConfigParam;
template<typename T, typename U>
class MapUserConfigParam : public UserConfigParam
{
std::map<T, U> m_elements;
public:
MapUserConfigParam(const char* param_name,
const char* comment = NULL);
MapUserConfigParam(const char* param_name,
const char* comment,
int nb_elts,
...);
MapUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment = NULL);
MapUserConfigParam(const char* param_name,
GroupUserConfigParam* group,
const char* comment,
int nb_elts,
...);
void write(std::ofstream& stream) const;
void findYourDataInAChildOf(const XMLNode* node);
void findYourDataInAnAttributeOf(const XMLNode* node);
void addElement(T element, U value);
irr::core::stringc toString() const;
operator std::map<T,U>() const
{
return m_elements;
}
std::map<T, U>& operator=(const std::map<T,U>& v)
{
m_elements = std::map<T, U>(v);
return m_elements;
}
std::map<T, U>& operator=(const MapUserConfigParam& v)
{
m_elements = std::map<T,U>(v);
return m_elements;
}
U& operator[] (const T key)
{
return m_elements[key];
}
}; // ListUserConfigParam
typedef MapUserConfigParam<int, int> IntToIntUserConfigParam;
// ============================================================================
class IntUserConfigParam : public UserConfigParam
{
@@ -335,7 +384,7 @@ namespace UserConfigParams
PARAM_DEFAULT( GroupUserConfigParam("RaceSetup",
"Race Setup Settings") );
PARAM_PREFIX IntUserConfigParam m_num_karts
PARAM_PREFIX IntUserConfigParam m_default_num_karts
PARAM_DEFAULT( IntUserConfigParam(4, "numkarts",
&m_race_setup_group,
"Default number of karts. -1 means use all") );
@@ -369,7 +418,7 @@ namespace UserConfigParams
PARAM_PREFIX StringUserConfigParam m_last_used_kart_group
PARAM_DEFAULT( StringUserConfigParam("all", "last_kart_group",
"Last selected kart group") );
// ---- Wiimote data
PARAM_PREFIX GroupUserConfigParam m_wiimote_group
PARAM_DEFAULT( GroupUserConfigParam("WiiMote",
@@ -706,6 +755,14 @@ namespace UserConfigParams
"stun.voxgratia.org",
"stun.xten.com") );
// ---- Gamemode setup
PARAM_PREFIX IntToIntUserConfigParam m_num_karts_per_gamemode
PARAM_DEFAULT(IntToIntUserConfigParam("num_karts_per_gamemode",
"The Number of karts per gamemode.",
1,
std::make_pair(1100, 4)
));
PARAM_PREFIX BoolUserConfigParam m_log_packets
PARAM_DEFAULT( BoolUserConfigParam(false, "log-network-packets",
"If all network packets should be logged") );

View File

@@ -166,7 +166,6 @@ void SolidCommandBuffer::fill(MeshMap *mesh_map)
fillInstanceData<InstanceDataFourTex, MeshMap>
(mesh_map, four_tex_material_list, InstanceTypeFourTex);
if (!CVS->supportsAsyncInstanceUpload())
glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER);
} //SolidCommandBuffer::fill

View File

@@ -218,7 +218,6 @@ protected:
mesh_map,
instance_buffer);
}
if (!CVS->supportsAsyncInstanceUpload())
{
glUnmapBuffer(GL_ARRAY_BUFFER);

View File

@@ -20,6 +20,7 @@
#include "utils/constants.hpp"
#include "utils/mini_glm.hpp"
#include "../../lib/irrlicht/source/Irrlicht/CSkinnedMesh.h"
const uint8_t VERSION_NOW = 1;
#include <algorithm>
@@ -47,7 +48,7 @@ scene::IAnimatedMesh* SPMeshLoader::createMesh(io::IReadFile* f)
}
m_bind_frame = 0;
m_joint_count = 0;
//m_frame_count = 0;
m_frame_count = 0;
m_mesh = NULL;
m_mesh = m_scene_manager->createSkinnedMesh();
io::IFileSystem* fs = m_scene_manager->getFileSystem();
@@ -196,6 +197,9 @@ scene::IAnimatedMesh* SPMeshLoader::createMesh(io::IReadFile* f)
f->read(&pre_computed_size, 2);
}
m_mesh->finalize();
// Because the last frame in spm is usable
static_cast<scene::CSkinnedMesh*>(m_mesh)->AnimationFrames =
(float)m_frame_count + 1.0f;
m_all_armatures.clear();
m_to_bind_pose_matrices.clear();
m_joints.clear();
@@ -366,8 +370,8 @@ void SPMeshLoader::createAnimationData(irr::io::IReadFile* spm)
}
for (unsigned i = 0; i < armature_size; i++)
{
//m_frame_count = std::max(m_frame_count,
// (unsigned)m_all_armatures[i].m_frame_pose_matrices.back().first);
m_frame_count = std::max(m_frame_count,
(unsigned)m_all_armatures[i].m_frame_pose_matrices.back().first);
m_joint_count += m_all_armatures[i].m_joint_used;
}

View File

@@ -79,7 +79,7 @@ private:
unsigned id);
};
// ------------------------------------------------------------------------
unsigned m_bind_frame, m_joint_count;//, m_frame_count;
unsigned m_bind_frame, m_joint_count, m_frame_count;
// ------------------------------------------------------------------------
std::vector<Armature> m_all_armatures;
// ------------------------------------------------------------------------

View File

@@ -18,7 +18,6 @@
#include "io/file_manager.hpp"
#include "io/xml_node.hpp"
#include "utils/string_utils.hpp"
#include "utils/interpolation_array.hpp"
#include "utils/vec3.hpp"

View File

@@ -33,9 +33,11 @@ using namespace irr;
#include "utils/leak_check.hpp"
#include "utils/no_copy.hpp"
#include "utils/string_utils.hpp"
#include "utils/time.hpp"
#include "utils/types.hpp"
class InterpolationArray;
class Vec3;
@@ -95,6 +97,27 @@ public:
int getHPR(core::vector3df *value) const;
int getHPR(Vec3 *value) const;
template<typename T, typename U>
int get(std::map<T, U>* out_map) const
{
using namespace StringUtils;
for (auto& p : m_attributes)
{
T val_1;
if (!fromString(p.first, val_1))
{
return 0;
}
U val_2;
if (!fromString(wideToUtf8(p.second), val_2))
{
return 0;
}
(*out_map)[val_1] = val_2;
}
return (int)m_attributes.size();
}
bool hasChildNamed(const char* name) const;
/** Handy functions to test the bit pattern returned by get(vector3df*).*/

View File

@@ -497,6 +497,28 @@ void Attachment::update(float dt)
bool is_shield = (m_type == ATTACH_BUBBLEGUM_SHIELD|| m_type == ATTACH_NOLOK_BUBBLEGUM_SHIELD);
float m_wanted_node_scale = is_shield ? std::max(1.0f, m_kart->getHighestPoint()*1.1f) : 1.0f;
int slow_flashes = 3;
if (is_shield & m_time_left < slow_flashes)
{
int flashes_per_second = 4;
int divisor = 2;
float fast_flashes = 0.5F;
if (m_time_left < fast_flashes)
{
flashes_per_second = 12;
}
float mod = (int)(m_time_left * flashes_per_second * 2) % divisor;
if (mod < divisor / 2)
{
m_node->setVisible(false);
}
else
{
m_node->setVisible(true);
}
}
if (m_node_scale < m_wanted_node_scale)
{

View File

@@ -2181,7 +2181,7 @@ void Kart::playCrashSFX(const Material* m, AbstractKart *k)
{
const float speed_for_max_volume = 15; //The speed at which the sound plays at maximum volume
const float max_volume = 1; //The maximum volume a sound is played at
const float min_volume = 0.2; //The minimum volume a sound is played at
const float min_volume = 0.2f; //The minimum volume a sound is played at
float volume; //The volume the crash sound will be played at

View File

@@ -594,6 +594,7 @@ void cmdLineHelp()
" -h, --help Show this help.\n"
" --log=N Set the verbosity to a value between\n"
" 0 (Debug) and 5 (Only Fatal messages)\n"
" --logbuffer=N Buffers up to N lines log lines before writing.\n"
" --root=DIR Path to add to the list of STK root directories.\n"
" You can specify more than one by separating them\n"
" with colons (:).\n"
@@ -664,6 +665,8 @@ int handleCmdLineOutputModifier()
int n;
if(CommandLine::has("--log", &n))
Log::setLogLevel(n);
if (CommandLine::has("--logbuffer", &n))
Log::setBufferSize(n);
if(CommandLine::has("--log=nocolor"))
{
@@ -1189,16 +1192,16 @@ int handleCmdLine()
if(CommandLine::has("--numkarts", &n) ||CommandLine::has("-k", &n))
{
UserConfigParams::m_num_karts = n;
if(UserConfigParams::m_num_karts > stk_config->m_max_karts)
UserConfigParams::m_default_num_karts = n;
if(UserConfigParams::m_default_num_karts > stk_config->m_max_karts)
{
Log::warn("main", "Number of karts reset to maximum number %d.",
stk_config->m_max_karts);
UserConfigParams::m_num_karts = stk_config->m_max_karts;
UserConfigParams::m_default_num_karts = stk_config->m_max_karts;
}
race_manager->setNumKarts( UserConfigParams::m_num_karts );
race_manager->setNumKarts( UserConfigParams::m_default_num_karts );
Log::verbose("main", "%d karts will be used.",
(int)UserConfigParams::m_num_karts);
(int)UserConfigParams::m_default_num_karts);
} // --numkarts
if(CommandLine::has( "--no-start-screen") ||
@@ -1807,8 +1810,10 @@ int main(int argc, char *argv[] )
} // try
catch (std::exception &e)
{
Log::flushBuffers();
Log::error("main", "Exception caught : %s.",e.what());
Log::error("main", "Aborting SuperTuxKart.");
Log::flushBuffers();
}
/* Program closing...*/
@@ -1832,6 +1837,8 @@ int main(int argc, char *argv[] )
MemoryLeaks::checkForLeaks();
#endif
Log::flushBuffers();
#ifndef WIN32
if (user_config) //close logfiles
{

View File

@@ -29,7 +29,7 @@
#include "tracks/track_manager.hpp"
std::vector<std::string> DemoWorld::m_demo_tracks;
int DemoWorld::m_num_karts = 2;
int DemoWorld::m_default_num_karts = 2;
float DemoWorld::m_max_idle_time = 99999.0f;
float DemoWorld::m_current_idle_time = 0;
bool DemoWorld::m_do_demo = false;
@@ -49,7 +49,7 @@ DemoWorld::DemoWorld()
race_manager->setReverseTrack(false);
race_manager->setMinorMode (RaceManager::MINOR_MODE_NORMAL_RACE);
race_manager->setDifficulty(RaceManager::DIFFICULTY_HARD);
race_manager->setNumKarts(m_num_karts);
race_manager->setNumKarts(m_default_num_karts);
race_manager->setNumPlayers(1);
race_manager->setPlayerKart(0, UserConfigParams::m_default_kart);
@@ -149,7 +149,7 @@ bool DemoWorld::updateIdleTimeAndStartDemo(float dt)
input_manager->getDeviceManager()->setAssignMode(ASSIGN);
m_do_demo = true;
race_manager->setNumKarts(m_num_karts);
race_manager->setNumKarts(m_default_num_karts);
race_manager->setPlayerKart(0, "tux");
race_manager->setupPlayerKartInfo();
race_manager->startSingleRace(m_demo_tracks[0], m_num_laps, false);

View File

@@ -40,7 +40,7 @@ private:
static std::vector<std::string> m_demo_tracks;
/** Number of karts to use in demo mode. */
static int m_num_karts;
static int m_default_num_karts;
/** Idle time after which demo mode should be started. */
static float m_max_idle_time;
@@ -66,7 +66,7 @@ public:
static void setNumLaps(unsigned int num_laps) { m_num_laps = num_laps; }
// ------------------------------------------------------------------------
/** Sets the number of karts to use in demo mode. */
static void setNumKarts(unsigned int num_karts) { m_num_karts = num_karts;}
static void setNumKarts(unsigned int num_karts) { m_default_num_karts = num_karts;}
// ------------------------------------------------------------------------
static void setTracks(const std::vector<std::string> &tracks);
// ------------------------------------------------------------------------

View File

@@ -66,7 +66,7 @@ RaceManager::RaceManager()
{
// Several code depends on this, e.g. kart_properties
assert(DIFFICULTY_FIRST == 0);
m_num_karts = UserConfigParams::m_num_karts;
m_num_karts = UserConfigParams::m_default_num_karts;
m_difficulty = DIFFICULTY_HARD;
m_major_mode = MAJOR_MODE_SINGLE;
m_minor_mode = MINOR_MODE_NORMAL_RACE;

View File

@@ -295,6 +295,33 @@ namespace Scripting
return -1;
}
/** Remove all animation set for a skeletal animation */
void removeAllAnimationSet(/** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
{
if (memory)
{
((scene::IAnimatedMeshSceneNode*)(memory))->removeAllAnimationSet();
}
}
/** Add an animation set for a skeletal animation */
void addAnimationSet(int start/** \cond DOXYGEN_IGNORE */, int end/** \cond DOXYGEN_IGNORE */, /** \cond DOXYGEN_IGNORE */void *memory /** \endcond */)
{
if (memory)
{
((scene::IAnimatedMeshSceneNode*)(memory))->addAnimationSet(start, end);
}
}
/** use an current frame for a skeletal animation */
void useAnimationSet(int set_num /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */)
{
if (memory)
{
((scene::IAnimatedMeshSceneNode*)(memory))->useAnimationSet(set_num);
}
}
/** Sets the current frame for a skeletal animation */
void setCurrentFrame(int frame /** \cond DOXYGEN_IGNORE */, void *memory /** \endcond */)
{
@@ -465,6 +492,8 @@ namespace Scripting
r = engine->RegisterObjectMethod("TrackObject", "void moveTo(const Vec3 &in, bool)", asMETHOD(::TrackObject, moveTo), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "Vec3 getCenterPosition()", asFUNCTION(TrackObject::getCenterPosition), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "Vec3 getOrigin()", asFUNCTION(TrackObject::getOrigin), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "TrackObject@ getParentLibrary()", asMETHOD(::TrackObject, getParentLibrary), asCALL_THISCALL); assert(r >= 0);
r = engine->RegisterObjectMethod("TrackObject", "string getName()", asMETHOD(::TrackObject, getName), asCALL_THISCALL); assert(r >= 0);
// PhysicalObject
r = engine->RegisterObjectMethod("PhysicalObject", "bool isFlattenKartObject()", asMETHOD(PhysicalObject, isFlattenKartObject), asCALL_THISCALL); assert(r >= 0);
@@ -476,6 +505,9 @@ namespace Scripting
r = engine->RegisterObjectMethod("Mesh", "void setFrameLoopOnce(int start, int end)", asFUNCTION(Mesh::setFrameLoopOnce), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("Mesh", "int getFrameNr()", asFUNCTION(Mesh::getFrameNr), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("Mesh", "int getAnimationSet()", asFUNCTION(Mesh::getAnimationSet), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("Mesh", "void useAnimationSet(int set_num)", asFUNCTION(Mesh::useAnimationSet), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("Mesh", "void addAnimationSet(int start, int end)", asFUNCTION(Mesh::addAnimationSet), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("Mesh", "void removeAllAnimationSet()", asFUNCTION(Mesh::removeAllAnimationSet), asCALL_CDECL_OBJLAST); assert(r >= 0);
r = engine->RegisterObjectMethod("Mesh", "void setCurrentFrame(int frame)", asFUNCTION(Mesh::setCurrentFrame), asCALL_CDECL_OBJLAST); assert(r >= 0);
//r = engine->RegisterObjectMethod("Mesh", "void move(Vec3 &in)", asFUNCTION(movePresentation), asCALL_CDECL_OBJLAST); assert(r >= 0);

View File

@@ -581,20 +581,20 @@ bool FeatureUnlockedCutScene::onEscapePressed()
void FeatureUnlockedCutScene::continueButtonPressed()
{
//if (m_global_time < GIFT_EXIT_TO)
//{
// // If animation was not over yet, the button is used to skip the animation
// while (m_global_time < GIFT_EXIT_TO)
// {
// // simulate all the steps of the animation until we reach the end
// onUpdate(0.4f);
// World::getWorld()->updateWorld(0.4f);
// }
//}
//else
//{
if (m_global_time < GIFT_EXIT_TO)
{
// If animation was not over yet, the button is used to skip the animation
while (m_global_time < GIFT_EXIT_TO)
{
// simulate all the steps of the animation until we reach the end
onUpdate(0.4f);
World::getWorld()->updateWorld(0.4f);
}
}
else
{
((CutsceneWorld*)World::getWorld())->abortCutscene();
//}
}
} // continueButtonPressed

View File

@@ -128,7 +128,7 @@ void GhostReplaySelection::loadList()
row.push_back(GUIEngine::ListWidget::ListCell
(StringUtils::toWString(rd.m_min_time) + L"s", -1, 1, true));
row.push_back(GUIEngine::ListWidget::ListCell
(rd.m_user_name, -1, 1, true));
(rd.m_user_name.empty() ? " " : rd.m_user_name, -1, 1, true));
m_replay_list_widget->addItem(StringUtils::toString(i), row);
}
} // loadList

View File

@@ -234,8 +234,9 @@ void GPInfoScreen::init()
{
const int local_players = race_manager->getNumLocalPlayers();
int min_ai = 0;
int num_ai = UserConfigParams::m_num_karts - local_players;
int num_ai = UserConfigParams::m_num_karts_per_gamemode[RaceManager::MAJOR_MODE_GRAND_PRIX]
- local_players;
// A ftl reace needs at least three karts to make any sense
if (race_manager->getMinorMode()==RaceManager::MINOR_MODE_FOLLOW_LEADER)
{
@@ -243,9 +244,7 @@ void GPInfoScreen::init()
}
num_ai = std::max(min_ai, num_ai);
UserConfigParams::m_num_karts = num_ai + local_players;
race_manager->setNumKarts(num_ai + local_players);
m_ai_kart_spinner->setActive(true);
m_ai_kart_spinner->setValue(num_ai);
m_ai_kart_spinner->setMax(stk_config->m_max_karts - local_players);
@@ -315,11 +314,24 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name,
/*new tracks*/ true );
addTracks();
}
else if (button == "start" || button == "continue")
else if (button == "start")
{
// Normal GP: start/continue a saved GP
// Normal GP: start GP
const int local_players = race_manager->getNumLocalPlayers();
const bool has_AI = race_manager->hasAI();
const int num_ai = has_AI ? m_ai_kart_spinner->getValue() : 0;
race_manager->setNumKarts(local_players + num_ai);
UserConfigParams::m_num_karts_per_gamemode[RaceManager::MAJOR_MODE_GRAND_PRIX] = local_players + num_ai;
m_gp.changeReverse(getReverse());
race_manager->startGP(m_gp, false, (button == "continue"));
race_manager->startGP(m_gp, false, false);
}
else if (button == "continue")
{
// Normal GP: continue a saved GP
m_gp.changeReverse(getReverse());
race_manager->startGP(m_gp, false, true);
}
} // name=="buttons"
else if (name=="group-spinner")
@@ -347,7 +359,7 @@ void GPInfoScreen::eventCallback(Widget *, const std::string &name,
{
const int num_ai = m_ai_kart_spinner->getValue();
race_manager->setNumKarts( race_manager->getNumLocalPlayers() + num_ai );
UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers() + num_ai;
UserConfigParams::m_num_karts_per_gamemode[RaceManager::MAJOR_MODE_GRAND_PRIX] = race_manager->getNumLocalPlayers() + num_ai;
}
else if(name=="back")
{

View File

@@ -46,6 +46,7 @@
#include "states_screens/offline_kart_selection.hpp"
#include "states_screens/online_profile_achievements.hpp"
#include "states_screens/online_profile_servers.hpp"
#include "states_screens/online_screen.hpp"
#include "states_screens/options_screen_video.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/user_screen.hpp"
@@ -75,9 +76,6 @@ bool MainMenuScreen::m_enable_online = false;
MainMenuScreen::MainMenuScreen() : Screen("main_menu.stkgui")
{
m_online_string = _("Online");
//I18N: Used as a verb, appears on the main menu (login button)
m_login_string = _("Login");
} // MainMenuScreen
// ----------------------------------------------------------------------------
@@ -151,10 +149,7 @@ void MainMenuScreen::init()
w->setBadge(LOADING_BADGE);
}
m_online = getWidget<IconButtonWidget>("online");
if(!m_enable_online)
m_online->setActive(false);
IconButtonWidget* online = getWidget<IconButtonWidget>("online");
LabelWidget* w = getWidget<LabelWidget>("info_addons");
const core::stringw &news_text = NewsManager::get()->getNextNewsMessage();
@@ -179,32 +174,25 @@ void MainMenuScreen::init()
} // init
// ----------------------------------------------------------------------------
void MainMenuScreen::onUpdate(float delta)
void MainMenuScreen::onUpdate(float delta)
{
PlayerProfile *player = PlayerManager::getCurrentPlayer();
if(PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_GUEST ||
PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_IN)
{
m_user_id->setText(player->getLastOnlineName() + "@stk");
m_online->setActive(true);
m_online->setLabel(m_online_string);
}
else if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_OUT)
{
m_online->setActive(true);
m_online->setLabel(m_login_string);
m_user_id->setText(player->getName());
}
else
{
// now must be either logging in or logging out
m_online->setActive(false);
m_user_id->setText(player->getName());
}
m_online->setLabel(PlayerManager::getCurrentOnlineId() ? m_online_string
: m_login_string);
IconButtonWidget* addons_icon = getWidget<IconButtonWidget>("addons");
if (addons_icon != NULL)
{
@@ -472,6 +460,7 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
}
else if (selection == "story")
{
NetworkConfig::get()->unsetNetworking();
PlayerProfile *player = PlayerManager::getCurrentPlayer();
if (player->isFirstTime())
{
@@ -505,23 +494,30 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
}
else if (selection == "online")
{
if(UserConfigParams::m_internet_status!=RequestManager::IPERM_ALLOWED)
if (MainMenuScreen::m_enable_online)
{
new MessageDialog(_("You can not play online without internet access. "
"If you want to play online, go to options, select "
" tab 'User Interface', and edit "
"\"Connect to the Internet\"."));
return;
}
if (PlayerManager::getCurrentOnlineId())
{
ProfileManager::get()->setVisiting(PlayerManager::getCurrentOnlineId());
OnlineProfileServers::getInstance()->push();
OnlineScreen::getInstance()->push();
}
else
{
UserScreen::getInstance()->push();
if (UserConfigParams::m_internet_status != RequestManager::IPERM_ALLOWED)
{
new MessageDialog(_("You can not play online without internet access. "
"If you want to play online, go to options, select "
" tab 'User Interface', and edit "
"\"Connect to the Internet\"."));
return;
}
if (PlayerManager::getCurrentOnlineId())
{
ProfileManager::get()->setVisiting(PlayerManager::getCurrentOnlineId());
TabOnlineProfileAchievements::getInstance()->push();
}
else
{
UserScreen::getInstance()->push();
}
}
}
else if (selection == "addons")

View File

@@ -32,13 +32,6 @@ class MainMenuScreen : public GUIEngine::Screen, public GUIEngine::ScreenSinglet
private:
friend class GUIEngine::ScreenSingleton<MainMenuScreen>;
core::stringw m_online_string;
core::stringw m_login_string;
/** Keep the widget to avoid looking it up every frame. */
GUIEngine::IconButtonWidget* m_online;
/** Keep the widget to to the user name. */
GUIEngine::ButtonWidget *m_user_id;

View File

@@ -0,0 +1,112 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010-2015 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 "states_screens/online_profile_servers.hpp"
#include "audio/sfx_manager.hpp"
#include "config/player_manager.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/scalable_font.hpp"
#include "guiengine/screen.hpp"
#include "guiengine/widget.hpp"
#include "network/network_config.hpp"
#include "network/protocol_manager.hpp"
#include "network/protocols/connect_to_server.hpp"
#include "network/protocols/request_connection.hpp"
#include "network/servers_manager.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/create_server_screen.hpp"
#include "states_screens/networking_lobby.hpp"
#include "states_screens/online_lan.hpp"
#include "states_screens/server_selection.hpp"
#include "utils/translation.hpp"
#include <IGUIButton.h>
#include <iostream>
#include <sstream>
using namespace GUIEngine;
using namespace irr::core;
using namespace irr::gui;
using namespace Online;
DEFINE_SCREEN_SINGLETON( OnlineLanScreen );
// -----------------------------------------------------------------------------
OnlineLanScreen::OnlineLanScreen() : GUIEngine::Screen("online/lan.stkgui")
{
} // OnlineLanScreen
// -----------------------------------------------------------------------------
void OnlineLanScreen::loadedFromFile()
{
} // loadedFromFile
// -----------------------------------------------------------------------------
void OnlineLanScreen::init()
{
RibbonWidget* ribbon = getWidget<RibbonWidget>("lan");
assert(ribbon != NULL);
ribbon->select("find_lan_server", PLAYER_ID_GAME_MASTER);
ribbon->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
} // init
// -----------------------------------------------------------------------------
void OnlineLanScreen::eventCallback(Widget* widget, const std::string& name, const int playerID)
{
if (name == "back")
{
StateManager::get()->popMenu();
return;
}
if (name == "lan")
{
RibbonWidget* ribbon = dynamic_cast<RibbonWidget*>(widget);
std::string selection = ribbon->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == "create_lan_server")
{
NetworkConfig::get()->setIsLAN();
NetworkConfig::get()->setIsServer(true);
CreateServerScreen::getInstance()->push();
// TODO: create lan server
}
else if (selection == "find_lan_server")
{
NetworkConfig::get()->setIsLAN();
NetworkConfig::get()->setIsServer(false);
ServerSelection::getInstance()->push();
}
}
} // eventCallback
// ----------------------------------------------------------------------------
/** Also called when pressing the back button. It resets the flags to indicate
* a networked game.
*/
bool OnlineLanScreen::onEscapePressed()
{
NetworkConfig::get()->unsetNetworking();
//StateManager::get()->popMenu();
return true;
} // onEscapePressed

View File

@@ -0,0 +1,57 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013-2015 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.
#ifndef __HEADER_OLAN_HPP__
#define __HEADER_OLAN_HPP__
#include <string>
#include <irrString.h>
#include "guiengine/screen.hpp"
#include "guiengine/widgets.hpp"
#include "states_screens/online_profile_base.hpp"
namespace GUIEngine { class Widget; }
/**
* \brief Online profiel overview screen
* \ingroup states_screens
*/
class OnlineLanScreen : public GUIEngine::Screen, public GUIEngine::ScreenSingleton<OnlineLanScreen>
{
protected:
OnlineLanScreen();
public:
friend class GUIEngine::ScreenSingleton<OnlineLanScreen>;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void loadedFromFile() OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name,
const int playerID) OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void init() OVERRIDE;
virtual bool onEscapePressed() OVERRIDE;
}; // class OnlineProfileServers
#endif

View File

@@ -42,7 +42,6 @@ using namespace Online;
OnlineProfileBase::OnlineProfileBase(const std::string &filename)
: Screen(filename.c_str())
{
m_servers_tab = NULL;
m_friends_tab = NULL;
m_achievements_tab = NULL;
m_settings_tab = NULL;
@@ -63,9 +62,6 @@ void OnlineProfileBase::loadedFromFile()
m_friends_tab = (IconButtonWidget *)m_profile_tabs->findWidgetNamed("tab_friends");
assert(m_friends_tab != NULL);
m_servers_tab = (IconButtonWidget *)m_profile_tabs->findWidgetNamed("tab_servers");
assert(m_servers_tab != NULL);
m_achievements_tab = (IconButtonWidget*)m_profile_tabs->findWidgetNamed("tab_achievements");
assert(m_profile_tabs == NULL || m_achievements_tab != NULL);
@@ -107,7 +103,6 @@ void OnlineProfileBase::init()
if (m_profile_tabs)
{
m_servers_tab->setTooltip(_("Servers"));
m_friends_tab->setTooltip(_("Friends"));
m_achievements_tab->setTooltip(_("Achievements"));
m_settings_tab->setTooltip(_("Account Settings"));
@@ -159,8 +154,6 @@ void OnlineProfileBase::eventCallback(Widget* widget, const std::string& name,
sm->replaceTopMostScreen(TabOnlineProfileAchievements::getInstance());
else if (selection == m_settings_tab->m_properties[PROP_ID])
sm->replaceTopMostScreen(OnlineProfileSettings::getInstance());
else if (selection == m_servers_tab->m_properties[PROP_ID])
sm->replaceTopMostScreen(OnlineProfileServers::getInstance());
}
else if (name == "back")
{

View File

@@ -42,7 +42,6 @@ protected:
/** Pointer to the various widgets on the screen. */
GUIEngine::LabelWidget * m_header;
GUIEngine::RibbonWidget* m_profile_tabs;
GUIEngine::IconButtonWidget * m_servers_tab;
GUIEngine::IconButtonWidget * m_friends_tab;
GUIEngine::IconButtonWidget * m_achievements_tab;
GUIEngine::IconButtonWidget * m_settings_tab;

View File

@@ -48,7 +48,7 @@ DEFINE_SCREEN_SINGLETON( OnlineProfileServers );
// -----------------------------------------------------------------------------
OnlineProfileServers::OnlineProfileServers() : OnlineProfileBase("online/profile_servers.stkgui")
OnlineProfileServers::OnlineProfileServers() : GUIEngine::Screen("online/profile_servers.stkgui")
{
} // OnlineProfileServers
@@ -56,44 +56,28 @@ OnlineProfileServers::OnlineProfileServers() : OnlineProfileBase("online/profile
void OnlineProfileServers::loadedFromFile()
{
OnlineProfileBase::loadedFromFile();
} // loadedFromFile
// -----------------------------------------------------------------------------
void OnlineProfileServers::init()
{
OnlineProfileBase::init();
m_profile_tabs->select( m_servers_tab->m_properties[PROP_ID], PLAYER_ID_GAME_MASTER );
m_servers_tab->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
// OnlineScreen::getInstance()->push();
RibbonWidget* ribbon = getWidget<RibbonWidget>("wan");
assert(ribbon != NULL);
ribbon->select("find_wan_server", PLAYER_ID_GAME_MASTER);
ribbon->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
} // init
// -----------------------------------------------------------------------------
void OnlineProfileServers::eventCallback(Widget* widget, const std::string& name, const int playerID)
{
OnlineProfileBase::eventCallback( widget, name, playerID);
if (name == "lan")
if (name == "back")
{
RibbonWidget* ribbon = dynamic_cast<RibbonWidget*>(widget);
std::string selection = ribbon->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == "create_lan_server")
{
NetworkConfig::get()->setIsLAN();
NetworkConfig::get()->setIsServer(true);
CreateServerScreen::getInstance()->push();
// TODO: create lan server
}
else if (selection == "find_lan_server")
{
NetworkConfig::get()->setIsLAN();
NetworkConfig::get()->setIsServer(false);
ServerSelection::getInstance()->push();
}
StateManager::get()->popMenu();
return;
}
else if (name == "wan")
if (name == "wan")
{
RibbonWidget* ribbon = dynamic_cast<RibbonWidget*>(widget);
std::string selection = ribbon->getSelectionIDString(PLAYER_ID_GAME_MASTER);
@@ -176,6 +160,6 @@ void OnlineProfileServers::doQuickPlay()
bool OnlineProfileServers::onEscapePressed()
{
NetworkConfig::get()->unsetNetworking();
return OnlineProfileBase::onEscapePressed();
return true;
} // onEscapePressed

View File

@@ -33,7 +33,7 @@ namespace GUIEngine { class Widget; }
* \brief Online profiel overview screen
* \ingroup states_screens
*/
class OnlineProfileServers : public OnlineProfileBase, public GUIEngine::ScreenSingleton<OnlineProfileServers>
class OnlineProfileServers : public GUIEngine::Screen, public GUIEngine::ScreenSingleton<OnlineProfileServers>
{
protected:
OnlineProfileServers();

View File

@@ -0,0 +1,198 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009-2015 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "states_screens/main_menu_screen.hpp"
#include "config/player_manager.hpp"
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "guiengine/scalable_font.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "input/device_manager.hpp"
#include "input/input_manager.hpp"
#include "input/keyboard_device.hpp"
#include "io/file_manager.hpp"
#include "main_loop.hpp"
#include "network/network_config.hpp"
#include "online/request_manager.hpp"
#include "states_screens/online_lan.hpp"
#include "states_screens/online_profile_achievements.hpp"
#include "states_screens/online_profile_servers.hpp"
#include "states_screens/online_screen.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/user_screen.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
#include "tracks/track_manager.hpp"
#include "utils/string_utils.hpp"
#include <string>
using namespace GUIEngine;
using namespace Online;
DEFINE_SCREEN_SINGLETON( OnlineScreen );
// ----------------------------------------------------------------------------
OnlineScreen::OnlineScreen() : Screen("online/online.stkgui")
{
m_online_string = _("Your profile");
//I18N: Used as a verb, appears on the main networking menu (login button)
m_login_string = _("Login");
} // OnlineScreen
// ----------------------------------------------------------------------------
void OnlineScreen::loadedFromFile()
{
} // loadedFromFile
// ----------------------------------------------------------------------------
void OnlineScreen::beforeAddingWidget()
{
bool is_logged_in = false;
PlayerProfile *player = PlayerManager::getCurrentPlayer();
if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_GUEST ||
PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_IN)
{
is_logged_in = true;
}
IconButtonWidget* wan = getWidget<IconButtonWidget>("wan");
wan->setActive(is_logged_in);
wan->setVisible(is_logged_in);
} // beforeAddingWidget
// ----------------------------------------------------------------------------
//
void OnlineScreen::init()
{
Screen::init();
m_online = getWidget<IconButtonWidget>("online");
if (!MainMenuScreen::m_enable_online)
m_online->setActive(false);
m_user_id = getWidget<ButtonWidget>("user-id");
assert(m_user_id);
RibbonWidget* r = getWidget<RibbonWidget>("menu_toprow");
r->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
} // init
// ----------------------------------------------------------------------------
void OnlineScreen::onUpdate(float delta)
{
PlayerProfile *player = PlayerManager::getCurrentPlayer();
if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_GUEST ||
PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_IN)
{
m_online->setActive(true);
m_online->setLabel(m_online_string);
m_user_id->setText(player->getLastOnlineName() + "@stk");
}
else if (PlayerManager::getCurrentOnlineState() == PlayerProfile::OS_SIGNED_OUT)
{
m_online->setActive(true);
m_online->setLabel(m_login_string);
m_user_id->setText(player->getName());
}
else
{
// now must be either logging in or logging out
m_online->setActive(false);
m_user_id->setText(player->getName());
}
m_online->setLabel(PlayerManager::getCurrentOnlineId() ? m_online_string
: m_login_string);
} // onUpdate
// ----------------------------------------------------------------------------
void OnlineScreen::eventCallback(Widget* widget, const std::string& name,
const int playerID)
{
if (name == "user-id")
{
UserScreen::getInstance()->push();
return;
}
else if (name == "back")
{
StateManager::get()->popMenu();
return;
}
RibbonWidget* ribbon = dynamic_cast<RibbonWidget*>(widget);
if (ribbon == NULL) return; // what's that event??
// ---- A ribbon icon was clicked
std::string selection =
ribbon->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == "lan")
{
OnlineLanScreen::getInstance()->push();
}
else if (selection == "wan")
{
OnlineProfileServers::getInstance()->push();
}
else if (selection == "online")
{
if (UserConfigParams::m_internet_status != RequestManager::IPERM_ALLOWED)
{
new MessageDialog(_("You can not play online without internet access. "
"If you want to play online, go to options, select "
" tab 'User Interface', and edit "
"\"Connect to the Internet\"."));
return;
}
if (PlayerManager::getCurrentOnlineId())
{
ProfileManager::get()->setVisiting(PlayerManager::getCurrentOnlineId());
TabOnlineProfileAchievements::getInstance()->push();
}
else
{
UserScreen::getInstance()->push();
}
}
} // eventCallback
// ----------------------------------------------------------------------------
void OnlineScreen::tearDown()
{
} // tearDown
// ----------------------------------------------------------------------------
void OnlineScreen::onDisabledItemClicked(const std::string& item)
{
} // onDisabledItemClicked

View File

@@ -0,0 +1,71 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2009-2015 Marianne Gagnon
//
// 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.
#ifndef HEADER_ONLINE_SCREEN_HPP
#define HEADER_ONLINE_SCREEN_HPP
#include "guiengine/screen.hpp"
namespace GUIEngine { class Widget; class ListWidget;
class ButtonWidget; class IconButtonWidget; }
/**
* \brief Handles the networking main menu
* \ingroup states_screens
*/
class OnlineScreen : public GUIEngine::Screen, public GUIEngine::ScreenSingleton<OnlineScreen>
{
private:
friend class GUIEngine::ScreenSingleton<OnlineScreen>;
core::stringw m_online_string;
core::stringw m_login_string;
/** Keep the widget to to the user name. */
GUIEngine::ButtonWidget *m_user_id;
/** Keep the widget to avoid looking it up every frame. */
GUIEngine::IconButtonWidget* m_online;
OnlineScreen();
public:
virtual void onUpdate(float delta) OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void loadedFromFile() OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void beforeAddingWidget() OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name,
const int playerID) OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void init() OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void tearDown() OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void onDisabledItemClicked(const std::string& item) OVERRIDE;
};
#endif

View File

@@ -163,15 +163,19 @@ void TrackInfoScreen::init()
race_manager->hasAI());
m_ai_kart_spinner->setVisible(has_AI);
getWidget<LabelWidget>("ai-text")->setVisible(has_AI);
if (has_AI)
{
m_ai_kart_spinner->setActive(true);
int num_ai = UserConfigParams::m_num_karts_per_gamemode[race_manager->getMinorMode()] - local_players;
// Avoid negative numbers (which can happen if e.g. the number of karts
// in a previous race was lower than the number of players now.
int num_ai = UserConfigParams::m_num_karts - local_players;
if (num_ai < 0) num_ai = 0;
m_ai_kart_spinner->setValue(num_ai);
race_manager->setNumKarts(num_ai + local_players);
// Set the max karts supported based on the battle arena selected
if(race_manager->getMinorMode()==RaceManager::MINOR_MODE_3_STRIKES ||
@@ -240,7 +244,8 @@ void TrackInfoScreen::init()
m_ai_kart_spinner->setValue(0);
m_ai_kart_spinner->setActive(false);
race_manager->setNumKarts(race_manager->getNumLocalPlayers());
UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers();
UserConfigParams::m_num_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers();
}
else if (record_available)
{
@@ -367,10 +372,11 @@ void TrackInfoScreen::onEnterPressedInternal()
if (has_AI)
num_ai = m_ai_kart_spinner->getValue();
if (UserConfigParams::m_num_karts != (local_players + num_ai))
if (UserConfigParams::m_num_karts_per_gamemode[race_manager->getMinorMode()] != (local_players + num_ai))
{
race_manager->setNumKarts(local_players + num_ai);
UserConfigParams::m_num_karts = local_players + num_ai;
UserConfigParams::m_num_karts_per_gamemode[race_manager->getMinorMode()] = local_players + num_ai;
}
// Disable accidentally unlocking of a challenge
@@ -420,7 +426,7 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name,
{
m_ai_kart_spinner->setActive(false);
race_manager->setNumKarts(race_manager->getNumLocalPlayers());
UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers();
UserConfigParams::m_num_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers();
}
else
{
@@ -439,7 +445,7 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name,
{
const int num_ai = m_ai_kart_spinner->getValue();
race_manager->setNumKarts( race_manager->getNumLocalPlayers() + num_ai );
UserConfigParams::m_num_karts = race_manager->getNumLocalPlayers() + num_ai;
UserConfigParams::m_num_karts_per_gamemode[race_manager->getMinorMode()] = race_manager->getNumLocalPlayers() + num_ai;
updateHighScores();
}
} // eventCallback

View File

@@ -400,7 +400,7 @@ void BaseUserScreen::eventCallback(Widget* widget,
*/
void BaseUserScreen::closeScreen()
{
StateManager::get()->resetAndGoToScreen(MainMenuScreen::getInstance());
StateManager::get()->popMenu();
} // closeScreen
// ----------------------------------------------------------------------------

View File

@@ -466,6 +466,7 @@ void Track::cleanup()
}
#endif
m_meta_library.clear();
Scripting::ScriptEngine::getInstance()->cleanupCache();
m_current_track = NULL;
@@ -1570,6 +1571,39 @@ void Track::createWater(const XMLNode &node)
scene_node->getMaterial(0).setFlag(video::EMF_GOURAUD_SHADING, true);
} // createWater
// ----------------------------------------------------------------------------
static void recursiveUpdatePosition(scene::ISceneNode *node)
{
node->updateAbsolutePosition();
scene::ISceneNodeList::ConstIterator it = node->getChildren().begin();
for (; it != node->getChildren().end(); ++it)
{
recursiveUpdatePosition(*it);
}
} // recursiveUpdatePosition
// ----------------------------------------------------------------------------
static void recursiveUpdatePhysics(std::vector<TrackObject*>& tos)
{
for (TrackObject* to : tos)
{
if (to->getPhysicalObject())
{
TrackObjectPresentationSceneNode* sn = to
->getPresentation<TrackObjectPresentationSceneNode>();
if (sn)
{
to->getPhysicalObject()->move(
sn->getNode()->getAbsoluteTransformation().getTranslation(),
sn->getNode()->getAbsoluteTransformation()
.getRotationDegrees());
}
}
recursiveUpdatePhysics(to->getChildren());
}
} // recursiveUpdatePhysics
// ----------------------------------------------------------------------------
/** This function load the actual scene, i.e. all parts of the track,
* animations, items, ... It is called from world during initialisation.
@@ -1757,6 +1791,19 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
loadObjects(root, path, model_def_loader, true, NULL, NULL);
// Correct the parenting of meta library
for (auto& p : m_meta_library)
{
auto* ln = p.first->getPresentation<TrackObjectPresentationLibraryNode>();
assert(ln);
TrackObjectPresentationLibraryNode* meta_ln = p.second
->getPresentation<TrackObjectPresentationLibraryNode>();
assert(meta_ln);
meta_ln->getNode()->setParent(ln->getNode());
recursiveUpdatePosition(meta_ln->getNode());
recursiveUpdatePhysics(p.second->getChildren());
}
model_def_loader.cleanLibraryNodesAfterLoad();
Scripting::ScriptEngine::getInstance()->compileLoadedScripts();

View File

@@ -374,6 +374,8 @@ private:
/** List of all bezier curves in the track - for e.g. camera, ... */
std::vector<BezierCurve*> m_all_curves;
std::vector<std::pair<TrackObject*, TrackObject*> > m_meta_library;
/** The number of laps the track will be raced in a random GP.
* m_actual_number_of_laps is initialised with this value.*/
int m_default_number_of_laps;
@@ -672,6 +674,10 @@ public:
// ------------------------------------------------------------------------
/** Adds mesh to cleanup list */
void addCachedMesh(scene::IMesh* mesh) { m_all_cached_meshes.push_back(mesh); }
// ------------------------------------------------------------------------
/** Adds the parent of the meta library for correction later */
void addMetaLibrary(TrackObject* parent, TrackObject* meta_library)
{ m_meta_library.emplace_back(parent, meta_library); }
}; // class Track
#endif

View File

@@ -31,6 +31,7 @@
#include "physics/physical_object.hpp"
#include "race/race_manager.hpp"
#include "scriptengine/script_engine.hpp"
#include "tracks/track.hpp"
#include "tracks/model_definition_loader.hpp"
#include <IAnimatedMeshSceneNode.h>
@@ -160,6 +161,10 @@ void TrackObject::init(const XMLNode &xml_node, scene::ISceneNode* parent,
{
xml_node.get("name", &m_name);
m_presentation = new TrackObjectPresentationLibraryNode(this, xml_node, model_def_loader);
if (parent_library != NULL)
{
Track::getCurrentTrack()->addMetaLibrary(parent_library, this);
}
}
else if (type == "sfx-emitter")
{

View File

@@ -180,6 +180,7 @@ TrackObjectPresentationLibraryNode::TrackObjectPresentationLibraryNode(
{
m_parent = NULL;
m_start_executed = false;
m_reset_executed = false;
std::string name;
xml_node.get("name", &name);
@@ -289,6 +290,22 @@ void TrackObjectPresentationLibraryNode::update(float dt)
m_start_executed = true;
std::string fn_name = StringUtils::insertValues("void %s::onStart(const string)", m_name.c_str());
if (m_parent != NULL)
{
std::string lib_id = m_parent->getID();
std::string* lib_id_ptr = &lib_id;
Scripting::ScriptEngine::getInstance()->runFunction(false, fn_name,
[&](asIScriptContext* ctx) {
ctx->SetArgObject(0, lib_id_ptr);
});
}
}
if (!m_reset_executed)
{
m_reset_executed = true;
std::string fn_name = StringUtils::insertValues("void %s::onReset(const string)", m_name.c_str());
if (m_parent != NULL)
{
std::string lib_id = m_parent->getID();

View File

@@ -187,13 +187,18 @@ class TrackObjectPresentationLibraryNode : public TrackObjectPresentationSceneNo
TrackObject* m_parent;
using TrackObjectPresentationSceneNode::move;
std::string m_name;
bool m_start_executed;
bool m_start_executed, m_reset_executed;
public:
TrackObjectPresentationLibraryNode(TrackObject* parent,
const XMLNode& xml_node,
ModelDefinitionLoader& model_def_loader);
virtual ~TrackObjectPresentationLibraryNode();
virtual void update(float dt);
virtual void update(float dt) OVERRIDE;
virtual void reset() OVERRIDE
{
m_reset_executed = false;
TrackObjectPresentationSceneNode::reset();
}
void move(const core::vector3df& xyz, const core::vector3df& hpr,
const core::vector3df& scale, bool isAbsoluteCoord, bool moveChildrenPhysicalBodies);
}; // TrackObjectPresentationLibraryNode

View File

@@ -35,6 +35,9 @@
Log::LogLevel Log::m_min_log_level = Log::LL_VERBOSE;
bool Log::m_no_colors = false;
FILE* Log::m_file_stdout = NULL;
std::string Log::m_prefix = "";
size_t Log::m_buffer_size = 1;
Synchronised<std::vector<struct Log::LineInfo> > Log::m_line_buffer;
// ----------------------------------------------------------------------------
/** Selects background/foreground colors for the message depending on
@@ -106,25 +109,22 @@ void Log::setTerminalColor(LogLevel level)
*/
void Log::resetTerminalColor()
{
if(m_no_colors)
{
printf("\n");
return;
}
if(m_no_colors) return;
#ifdef WIN32
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
/*TERM_BLACK*/0 << 4 | /*TERM_LIGHTGRAY*/7);
printf("\n");
#else
printf("%c[0;;m\n", 0x1B);
printf("%c[0;;m", 0x1B);
#endif
} // resetTerminalColor
// ----------------------------------------------------------------------------
/** This actually prints the log message. If log messages are not redirected
* to a file, it tries to select a terminal colour.
/** This actually creates a log message. If the messages are to be buffered,
* it will be appended to the output buffer. If the buffer is full, it will
* be flushed. If the message is not to be buffered, it will be immediately
* written using writeLine().
* \param level Log level of the message to print.
* \param format A printf-like format string.
* \param va_list The values to be printed for the format.
@@ -132,105 +132,119 @@ void Log::resetTerminalColor()
void Log::printMessage(int level, const char *component, const char *format,
VALIST args)
{
assert(level>=0 && level <=LL_FATAL);
assert(level >= 0 && level <= LL_FATAL);
if(level<m_min_log_level) return;
if (level < m_min_log_level) return;
#ifdef ANDROID
android_LogPriority alp;
switch (level)
static const char *names[] = { "debug", "verbose ", "info ",
"warn ", "error ", "fatal " };
const int MAX_LENGTH = 2048;
char line[MAX_LENGTH + 1];
int index = 0;
if (!m_prefix.empty())
index += snprintf(line+index, MAX_LENGTH-index, "%s ", m_prefix.c_str());
index += snprintf (line + index, MAX_LENGTH - index, "[%s] %s: ", names[level], component);
index += vsnprintf(line + index, MAX_LENGTH - index, format, args);
va_end(args);
index = snprintf (line + index, MAX_LENGTH - index, "\n");
// If the data is not buffered, immediately print it:
if (m_buffer_size <= 1)
{
// STK is using the levels slightly different from android
// (debug lowest, verbose above it; while android reverses
// this order. So to get the same behaviour (e.g. filter
// out debug message, but still get verbose, we swap
// the order here.
case LL_VERBOSE: alp = ANDROID_LOG_DEBUG; break;
case LL_DEBUG: alp = ANDROID_LOG_VERBOSE; break;
case LL_INFO: alp = ANDROID_LOG_INFO; break;
case LL_WARN : alp = ANDROID_LOG_WARN; break;
case LL_ERROR: alp = ANDROID_LOG_ERROR; break;
case LL_FATAL: alp = ANDROID_LOG_FATAL; break;
default: alp = ANDROID_LOG_FATAL;
writeLine(line, level);
return;
}
#endif
static const char *names[] = {"debug", "verbose ", "info ",
"warn ", "error ", "fatal "};
// Using a va_list twice produces undefined results, ie crash.
// So make a copy if we're going to use it twice.
VALIST copy;
if (m_file_stdout)
// Now the data needs to be buffered. Add an entry to the buffer,
// and if necessary flush the buffers.
struct LineInfo li;
li.m_level = level;
li.m_line = std::string(line);
m_line_buffer.lock();
m_line_buffer.getData().push_back(li);
if (m_line_buffer.getData().size() < m_buffer_size)
{
va_copy(copy, args);
// Buffer not yet full, don't flush data.
m_line_buffer.unlock();
return;
}
#if defined(_MSC_FULL_VER) && defined(_DEBUG)
VALIST copy2;
va_copy(copy2, args);
#endif
m_line_buffer.unlock();
// Because of the unlock above it can happen that another thread adds
// another line and calls flushBuffers() first before this thread can
// call it, but that doesn't really matter, when this thread will finally
// call flushBuffer() it will then just print nothing if another thread
// had been actively flushing it in between.
flushBuffers();
} // printMessage
// ----------------------------------------------------------------------------
/** Writes the specified line to the various output devices, e.g. terminal,
* log file etc. If log messages are not redirected to a file, it tries to
* select a terminal colour.
* \param line The line to write.
* \param level Message level. Only used to select terminal colour.
*/
void Log::writeLine(const char *line, int level)
{
// If we don't have a console file, write to stdout and hope for the best
if(!m_file_stdout || level >= LL_WARN ||
if (!m_file_stdout || level >= LL_WARN ||
UserConfigParams::m_log_errors_to_console) // log to console & file
{
VALIST out;
va_copy(out, args);
setTerminalColor((LogLevel)level);
#ifdef ANDROID
__android_log_vprint(alp, "SuperTuxKart", format, out);
#else
printf("[%s] %s: ", names[level], component);
vprintf(format, out);
#endif
#ifdef ANDROID
android_LogPriority alp;
switch (level)
{
// STK is using the levels slightly different from android
// (debug lowest, verbose above it; while android reverses
// this order. So to get the same behaviour (e.g. filter
// out debug message, but still get verbose, we swap
// the order here.
case LL_VERBOSE: alp = ANDROID_LOG_DEBUG; break;
case LL_DEBUG: alp = ANDROID_LOG_VERBOSE; break;
case LL_INFO: alp = ANDROID_LOG_INFO; break;
case LL_WARN: alp = ANDROID_LOG_WARN; break;
case LL_ERROR: alp = ANDROID_LOG_ERROR; break;
case LL_FATAL: alp = ANDROID_LOG_FATAL; break;
default: alp = ANDROID_LOG_FATAL;
}
__android_log_print(alp, "SuperTuxKart", "%s", line);
#else
printf(line);
#endif
resetTerminalColor(); // this prints a \n
va_end(out);
}
#if defined(_MSC_FULL_VER) && defined(_DEBUG)
static char szBuff[2048];
vsnprintf(szBuff, sizeof(szBuff), format, copy2);
OutputDebugString("[");
OutputDebugString(names[level]);
OutputDebugString("] ");
OutputDebugString(component);
OutputDebugString(": ");
OutputDebugString(szBuff);
OutputDebugString("\r\n");
OutputDebugString(line);
#endif
if(m_file_stdout)
{
fprintf (m_file_stdout, "[%s] %s: ", names[level], component);
vfprintf(m_file_stdout, format, copy);
fprintf (m_file_stdout, "\n");
va_end(copy);
}
if (m_file_stdout) fprintf(m_file_stdout, "%s", line);
#ifdef WIN32
if (level >= LL_FATAL)
{
std::string message;
char tmp[2048];
sprintf(tmp, "[%s] %s: ", names[level], component);
message += tmp;
VALIST out;
va_copy(out, args);
vsprintf(tmp, format, out);
message += tmp;
va_end(out);
MessageBoxA(NULL, message.c_str(), "SuperTuxKart - Fatal error", MB_OK);
MessageBoxA(NULL, line, "SuperTuxKart - Fatal error", MB_OK);
}
#endif
} // printMessage
} // _fluhBuffers
// ----------------------------------------------------------------------------
/** Flushes all stored log messages to the various output devices (thread safe).
*/
void Log::flushBuffers()
{
m_line_buffer.lock();
for (unsigned int i = 0; i < m_line_buffer.getData().size(); i++)
{
const LineInfo &li = m_line_buffer.getData()[i];
writeLine(li.m_line.c_str(), li.m_level);
}
m_line_buffer.getData().clear();
m_line_buffer.unlock();
} // flushBuffers
// ----------------------------------------------------------------------------
/** This function opens the files that will contain the output.

View File

@@ -20,11 +20,15 @@
#ifndef HEADER_LOG_HPP
#define HEADER_LOG_HPP
#include "utils/synchronised.hpp"
#include <assert.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>
#ifdef __GNUC__
# define VALIST __gnuc_va_list
@@ -59,13 +63,30 @@ private:
/** The file where stdout output will be written */
static FILE* m_file_stdout;
/** An optional buffer for lines to be output. */
struct LineInfo
{
std::string m_line;
int m_level;
};
static Synchronised<std::vector<struct LineInfo> > m_line_buffer;
/** <0 if no buffered logging is to be used, otherwise this is
** the maximum number of lines the buffer should hold. */
static size_t m_buffer_size;
/** An optional prefix to be printed. */
static std::string m_prefix;
static void setTerminalColor(LogLevel level);
static void resetTerminalColor();
public:
static void writeLine(const char *line, int level);
static void printMessage(int level, const char *component,
const char *format, VALIST va_list);
public:
// ------------------------------------------------------------------------
/** A simple macro to define the various log functions.
* Note that an assert is added so that a debugger is triggered
@@ -95,7 +116,12 @@ public:
static void openOutputFiles(const std::string &logout);
static void closeOutputFiles();
static void flushBuffers();
// ------------------------------------------------------------------------
/** Sets the number of lines to buffer. Setting the buffer size to a
* a value <=1 means no buffering, lines will be immediately printed. */
static void setBufferSize(size_t n) { m_buffer_size = n; }
// ------------------------------------------------------------------------
/** Defines the minimum log level to be displayed. */
static void setLogLevel(int n)
@@ -120,5 +146,9 @@ public:
{
m_no_colors = true;
} // disableColor
// ------------------------------------------------------------------------
/** Sets a prefix to be printed before each line. To disable the prefix,
* set it to "". */
static void setPrefix(const std::string &prefix) { m_prefix = prefix; }
}; // Log
#endif

View File

@@ -43,7 +43,7 @@
!define DESCRIPTION "3D open-source arcade racer with a variety characters, tracks, and modes to play"
Name "${APPNAMEANDVERSION}"
OutFile "${APPNAMEANDVERSION} installer.exe"
OutFile "${APPNAMEANDVERSION} installer-64bit.exe"
# These will be displayed by the "Click here for support information" link in "Add/Remove Programs"
# It is possible to use "mailto:" links in here to open the email client
@@ -174,12 +174,12 @@ Section "Install" SecMain
; Try to find the binary directory in a list of 'typical' names:
; The first found directory is used
${!setIfUndefinedAndExists} EXEC_PATH ..\..\bld\bin\RelWithDebInfo\*.*
${!setIfUndefinedAndExists} EXEC_PATH ..\..\bld\bin\Release\*.*
${!setIfUndefinedAndExists} EXEC_PATH ..\..\build\bin\RelWithDebInfo\*.*
${!setIfUndefinedAndExists} EXEC_PATH ..\..\build\bin\Release\*.*
${!setIfUndefinedAndExists} EXEC_PATH ..\..\cmake_build\bin\RelWithDebInfo\*.*
${!setIfUndefinedAndExists} EXEC_PATH ..\..\cmake_build\bin\Release\*.*
${!setIfUndefinedAndExists} EXEC_PATH ..\..\bld-64\bin\RelWithDebInfo\*.*
${!setIfUndefinedAndExists} EXEC_PATH ..\..\bld-64\bin\Release\*.*
${!setIfUndefinedAndExists} EXEC_PATH ..\..\build-64\bin\RelWithDebInfo\*.*
${!setIfUndefinedAndExists} EXEC_PATH ..\..\build-64\bin\Release\*.*
${!setIfUndefinedAndExists} EXEC_PATH ..\..\cmake_build-64\bin\RelWithDebInfo\*.*
${!setIfUndefinedAndExists} EXEC_PATH ..\..\cmake_build-64\bin\Release\*.*
File /x *.ilk ${EXEC_PATH}
@@ -206,7 +206,7 @@ Section "Install" SecMain
File *.ico
; prereqs
SetOutPath "$INSTDIR\prerequisites"
File /r prerequisites\*.*
File /r prerequisites\vcredist_x64.exe
; data + assets
SetOutPath "$INSTDIR\data\"
@@ -281,7 +281,6 @@ Section "Uninstall" redist
DELETE /REBOOTOK "$INSTDIR\icon.ico"
DELETE /REBOOTOK "$INSTDIR\libcurl-4.dll"
DELETE /REBOOTOK "$INSTDIR\libeay32.dll"
DELETE /REBOOTOK "$INSTDIR\libidn-11.dll"
DELETE /REBOOTOK "$INSTDIR\License.txt"
DELETE /REBOOTOK "$INSTDIR\libfreetype.dll"
DELETE /REBOOTOK "$INSTDIR\libfribidi-0.dll"

View File

@@ -35,7 +35,7 @@
!define VERSION_MINOR 9
!define VERSION_REVISION 3
; Empty means stable, could be -git, -rc1
!define VERSION_BUILD "-rc1"
!define VERSION_BUILD "-git"
;Name and file
!define APPNAME "SuperTuxKart"
@@ -43,7 +43,7 @@
!define DESCRIPTION "3D open-source arcade racer with a variety characters, tracks, and modes to play"
Name "${APPNAMEANDVERSION}"
OutFile "${APPNAMEANDVERSION} installer.exe"
OutFile "${APPNAMEANDVERSION} installer-32bit.exe"
# These will be displayed by the "Click here for support information" link in "Add/Remove Programs"
# It is possible to use "mailto:" links in here to open the email client
@@ -206,7 +206,7 @@ Section "Install" SecMain
File *.ico
; prereqs
SetOutPath "$INSTDIR\prerequisites"
File /r prerequisites\*.*
File /r prerequisites\vcredist_x86.exe
; data + assets
SetOutPath "$INSTDIR\data\"