Merged with master and solved conflicts

This commit is contained in:
Elderme 2015-09-18 11:05:27 +02:00
commit b7ab99e5e2
58 changed files with 5142 additions and 4597 deletions

View File

@ -19,6 +19,7 @@ option(USE_WIIUSE "Support for wiimote input devices" ON)
option(USE_FRIBIDI "Support for right-to-left languages" ON)
option(CHECK_ASSETS "Check if assets are installed in ../stk-assets" ON)
option(USE_SYSTEM_ANGELSCRIPT "Use system angelscript instead of built-in angelscript. If you enable this option, make sure to use a compatible version." OFF)
option(ENABLE_NETWORK_MULTIPLAYER "Enable network multiplayer. This will replace the online profile GUI in the main menu with the network multiplayer GUI" OFF)
if(MSVC AND (MSVC_VERSION LESS 1900))
# Normally hide the option to build wiiuse on VS, since it depends
@ -123,9 +124,15 @@ endif()
# Build the angelscript library if not in system
find_package(Angelscript)
if(USE_SYSTEM_ANGELSCRIPT AND ANGELSCRIPT_FOUND)
include_directories(${Angelscript_INCLUDE_DIRS})
if(USE_SYSTEM_ANGELSCRIPT)
find_package(Angelscript)
if(ANGELSCRIPT_FOUND)
include_directories(${Angelscript_INCLUDE_DIRS})
else()
message(FATAL_ERROR "Angelscript not found. "
"Either install angelscript or use built-in version using "
"-DUSE_SYSTEM_ANGELSCRIPT=0")
endif()
else()
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/angelscript/projects/cmake")
include_directories("${PROJECT_SOURCE_DIR}/lib/angelscript/include")
@ -205,6 +212,11 @@ if(MINGW AND CMAKE_BUILD_TYPE MATCHES Release)
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--subsystem,windows")
endif()
# Netwowk Multiplayer
if(ENABLE_NETWORK_MULTIPLAYER)
add_definitions(-DENABLE_NETWORK_MULTIPLAYER_SCREEN)
endif()
if(WIN32)
# By default windows.h has macros defined for min and max that screw up everything
add_definitions(-DNOMINMAX)
@ -213,7 +225,7 @@ if(WIN32)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
# Avoid timespec structure redeclaration on Visual Studio 2015
if (MSVC_VERSION EQUAL 1900)
if (NOT (MSVC_VERSION LESS 1900))
add_definitions(-DHAVE_STRUCT_TIMESPEC)
endif()
endif()
@ -408,24 +420,6 @@ endif()
add_subdirectory(tools/font_tool)
# ==== Make dist target ====
if(MSVC OR MINGW)
# Don't create a dist target for VS
else()
add_custom_target(dist
COMMAND rm -rf ${CMAKE_BINARY_DIR}/SuperTuxKart-${PROJECT_VERSION} && rm -f ${CMAKE_BINARY_DIR}/SuperTuxKart-${PROJECT_VERSION}.tar.bz2
&& echo "Exporting..."
&& svn export ${PROJECT_SOURCE_DIR} ${CMAKE_BINARY_DIR}/SuperTuxKart-${PROJECT_VERSION}
&& echo "Compressing..."
&& cd ${CMAKE_BINARY_DIR}
&& tar -cjf ${CMAKE_BINARY_DIR}/SuperTuxKart-${PROJECT_VERSION}.tar.bz2 ./SuperTuxKart-${PROJECT_VERSION}
&& echo "Done, cleaning up"
&& rm -rf ${CMAKE_BINARY_DIR}/SuperTuxKart-${PROJECT_VERSION}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
endif()
# ==== Checking if data folder exists ====
if(NOT IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/data)
message( FATAL_ERROR "${CMAKE_CURRENT_SOURCE_DIR}/data folder doesn't exist" )

View File

@ -10,11 +10,11 @@
</hard>
<medium>
<karts number="4"/>
<requirements position="2"/>
<requirements position="1"/>
</medium>
<easy>
<karts number="3"/>
<requirements position="3"/>
<requirements position="1"/>
</easy>
</challenge>

View File

@ -6,15 +6,15 @@
<hard>
<karts number="5"/>
<requirements position="1" time="50"/>
<requirements position="1" time="65"/>
</hard>
<medium>
<karts number="5"/>
<requirements position="1" time="65"/>
<requirements position="1" time="85"/>
</medium>
<easy>
<karts number="5"/>
<requirements position="1" time="80"/>
<requirements position="1" time="105"/>
</easy>
</challenge>

View File

@ -6,7 +6,7 @@
<hard>
<karts number="5"/>
<requirements position="1" time="200"/>
<requirements position="1" time="205"/>
</hard>
<medium>
<karts number="4"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

After

Width:  |  Height:  |  Size: 181 KiB

View File

@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
<div x="5%" y="2%" width="90%" height="96%" layout="vertical-row" >
<header I18N="Title for tutorials screen" text="Tutorial - Selection Room" text_align="center" width="100%" />
<spacer proportion="1" width="100%"/>
<list id="tutorials" proportion="5" width="75%" align="center"/>
<spacer proportion="1" width="100%"/>
<spacer width="100%" height="45"/>
</div>
<button id="play" x="-200" y="-40" height="35" align="right" text="Play all"/>
</stkgui>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,10 @@ cmake_minimum_required(VERSION 2.6)
set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE)
cmake_policy(SET CMP0003 NEW)
if(NOT (CMAKE_MAJOR_VERSION VERSION_LESS 3))
cmake_policy(SET CMP0048 OLD)
endif()
project(angelscript)
option(BUILD_SHARED_LIBS "Build shared library" OFF)

View File

@ -0,0 +1,112 @@
// Copyright (C) 2015 Ben Au
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
namespace irr
{
namespace gui
{
//Here a list of characters that don't start or end a line for chinese/japanese/korean
//Only commonly use and full width characters are included
//You should use full width characters when writing CJK, like using "。"instead of a "."
//You can add more characters if needed
//For full list please visit http://webapp.docx4java.org/OnlineDemo/ecma376/WordML/kinsoku.html
bool UtfNoStarting (wchar_t c)
{
switch (c)
{
case 8217: //
return true;
case 8221: //”
return true;
case 12293: //々
return true;
case 12297: //〉
return true;
case 12299: //》
return true;
case 12301: //」
return true;
case 65373: //
return true;
case 12309: //
return true;
case 65289: //
return true;
case 12303: //』
return true;
case 12305: //】
return true;
case 12311: //〗
return true;
case 65281: //
return true;
case 65285: //
return true;
case 65311: //
return true;
case 65344: //
return true;
case 65292: //
return true;
case 65306: //
return true;
case 65307: //
return true;
case 65294: //
return true;
case 12290: //。
return true;
case 12289: //、
return true;
default:
return false;
}
}
bool UtfNoEnding (wchar_t c)
{
switch (c)
{
case 8216: //
return true;
case 8220: //“
return true;
case 12296: //〈
return true;
case 12298: //《
return true;
case 12300: //「
return true;
case 65371: //
return true;
case 12308: //
return true;
case 65288: //
return true;
case 12302: //『
return true;
case 12304: //【
return true;
case 12310: //〖
return true;
default:
return false;
}
}
//Helper function
bool breakable (wchar_t c)
{
if ((c > 12287 && c < 40960) || //Common CJK words
(c > 44031 && c < 55204) || //Hangul
(c > 63743 && c < 64256) || //More Chinese
c == 173 || c == L' ' || c == 0) //Soft hyphen and white space
return true;
return false;
}
} // end namespace gui
} // end namespace irr

View File

@ -10,9 +10,7 @@
#include "IGUIFont.h"
#include "IVideoDriver.h"
#include "rect.h"
#define CJK_START 12287
#define CJK_END 40960
#include "utfwrapping.h"
namespace irr
{
@ -357,102 +355,77 @@ void CGUIStaticText::breakText()
lineBreak = true;
c = '\0';
}
word += c;
bool isWhitespace = (c == L' ' || c == 0);
if ( !isWhitespace )
if (word.size())
{
// part of a word
word += c;
const s32 wordlgth = font->getDimension(word.c_str()).Width;
//Check for CJK, show them first if out of range of displaying area
if (Text[i] > CJK_START && Text[i] < CJK_END)
{
const s32 cjklgth = font->getDimension(word.c_str()).Width;
if (cjklgth > (elWidth - 23))
{
BrokenText.push_back(line);
length = cjklgth;
line = word;
word = L"";
whitespace = L"";
}
}
}
if ( isWhitespace || i == (size-1))
{
if (word.size())
{
// here comes the next whitespace, look if
// we must break the last word to the next line.
const s32 whitelgth = font->getDimension(whitespace.c_str()).Width;
const s32 wordlgth = font->getDimension(word.c_str()).Width;
if (wordlgth > elWidth)
if (length && (length + wordlgth > elWidth))
{ // too long to fit inside
// break to next line
unsigned int where = 1;
while (where != line.size()) //Find the first breakable position
{
// This word is too long to fit in the available space, look for
// the Unicode Soft HYphen (SHY / 00AD) character for a place to
// break the word at
int where = word.findFirst( wchar_t(0x00AD) );
if (where != -1)
if (UtfNoEnding(Text[i - where]) || //Prevent unsuitable character from displaying
UtfNoStarting(Text[i - where]) || //at the position of starting or ending of a line
UtfNoStarting(Text[i + 1 - where])) //Handle case which more than one non-newline-starting characters are together
{
core::stringw first = word.subString(0, where);
core::stringw second = word.subString(where, word.size() - where);
BrokenText.push_back(line + first + L"-");
const s32 secondLength = font->getDimension(second.c_str()).Width;
length = secondLength;
line = second;
where++;
continue;
}
if (breakable(Text[i - where]))
break;
else
{
// No soft hyphen found, so there's nothing more we can do
// break to next line
if (length)
BrokenText.push_back(line);
length = wordlgth;
line = word;
}
where++;
}
else if (length && (length + wordlgth + whitelgth > elWidth))
if (where != line.size())
{
// break to next line
BrokenText.push_back(line);
length = wordlgth;
line = word;
core::stringw first = line.subString(0, line.size() + 1 - where);
core::stringw second = line.subString(line.size() + 1 - where , where - 1);
if (first.lastChar() == wchar_t(0x00AD))
BrokenText.push_back(first + L"-"); //Print the Unicode Soft HYphen (SHY / 00AD) character
else
BrokenText.push_back(first);
const s32 secondLength = font->getDimension(second.c_str()).Width;
length = secondLength + wordlgth;
line = second + word;
}
else if (breakable(c) || UtfNoEnding(c) || UtfNoStarting(c)) //Unusual case
{
BrokenText.push_back(line); //Force breaking to next line too if last word is breakable,
line = word; //it happens when someone writes too many non-newline-starting
length = wordlgth; //chars in the first line, so we ignore the rules.
}
// No suitable place to break words, so there's nothing more we can do
// break to next line
else
{
// add word to line
line += whitespace;
line += word;
length += whitelgth + wordlgth;
length += wordlgth;
}
word = L"";
whitespace = L"";
}
if ( isWhitespace )
else
{
whitespace += c;
}
// compute line break
if (lineBreak)
{
line += whitespace;
line += word;
BrokenText.push_back(line);
line = L"";
word = L"";
whitespace = L"";
length = 0;
length += wordlgth;
}
word = L"";
}
// compute line break
if (lineBreak)
{
line += word;
BrokenText.push_back(line);
line = L"";
word = L"";
length = 0;
}
}
line += whitespace;
line += word;
BrokenText.push_back(line);
}

View File

@ -243,12 +243,17 @@ ChallengeData::ChallengeData(const std::string& filename)
}
core::stringw description;
if (track_node != NULL)
if (track_node != NULL && m_minor!=RaceManager::MINOR_MODE_FOLLOW_LEADER)
{
//I18N: number of laps to race in a challenge
description += _("Laps : %i", m_num_laps);
description += core::stringw(L"\n");
}
else if (track_node)
{
// Follow the leader mode:
description = _("Follow the leader");
}
m_challenge_description = description;
} // ChallengeData

View File

@ -433,12 +433,6 @@ void Camera::smoothMoveCamera(float dt)
assert(!isnan(m_camera->getPosition().Y));
assert(!isnan(m_camera->getPosition().Z));
if (race_manager->getNumLocalPlayers() < 2)
{
SFXManager::get()->positionListener(current_position,
current_target - current_position,
Vec3(0,1,0));
}
} // smoothMoveCamera
//-----------------------------------------------------------------------------
@ -530,6 +524,14 @@ void Camera::getCameraSettings(float *above_kart, float *cam_angle,
*/
void Camera::update(float dt)
{
if (race_manager->getNumLocalPlayers() < 2)
{
Vec3 pos(m_camera->getPosition());
SFXManager::get()->positionListener(pos,
Vec3(m_camera->getTarget()) - pos,
Vec3(0, 1, 0));
}
if (m_kart == NULL) return; // cameras not attached to kart must be positioned manually
float above_kart, cam_angle, side_way, distance;

View File

@ -96,8 +96,8 @@ IrrDriver *irr_driver = NULL;
GPUTimer m_perf_query[Q_LAST];
const int MIN_SUPPORTED_HEIGHT = 600;
const int MIN_SUPPORTED_WIDTH = 800;
const int MIN_SUPPORTED_HEIGHT = 768;
const int MIN_SUPPORTED_WIDTH = 1024;
// ----------------------------------------------------------------------------
/** The constructor creates the irrlicht device. It first creates a NULL
@ -327,7 +327,8 @@ void IrrDriver::createListOfVideoModes()
{
const int w = modes->getVideoModeResolution(i).Width;
const int h = modes->getVideoModeResolution(i).Height;
if (h < MIN_SUPPORTED_HEIGHT || w < MIN_SUPPORTED_WIDTH)
if ( (h < MIN_SUPPORTED_HEIGHT || w < MIN_SUPPORTED_WIDTH) &&
( ! (h==600 && w==800 && UserConfigParams::m_artist_debug_mode) ) )
continue;
VideoMode mode(w, h);
@ -424,7 +425,8 @@ void IrrDriver::initDevice()
m_device = NULL;
SIrrlichtCreationParameters params;
params.ForceLegacyDevice = UserConfigParams::m_force_legacy_device;
params.ForceLegacyDevice = (UserConfigParams::m_force_legacy_device ||
UserConfigParams::m_gamepad_visualisation);
// Try 32 and, upon failure, 24 then 16 bit per pixels
for (int bits=32; bits>15; bits -=8)
@ -1096,16 +1098,29 @@ scene::IMeshSceneNode *IrrDriver::addOctTree(scene::IMesh *mesh)
scene::IMeshSceneNode *IrrDriver::addSphere(float radius,
const video::SColor &color)
{
scene::IMeshSceneNode *node = m_scene_manager->addSphereSceneNode(radius);
node->setMaterialType(video::EMT_SOLID);
scene::IMesh *mesh = node->getMesh();
scene::IMesh *mesh = m_scene_manager->getGeometryCreator()
->createSphereMesh(radius);
mesh->setMaterialFlag(video::EMF_COLOR_MATERIAL, true);
video::SMaterial m;
video::SMaterial &m = mesh->getMeshBuffer(0)->getMaterial();
m.AmbientColor = color;
m.DiffuseColor = color;
m.EmissiveColor = color;
m.BackfaceCulling = false;
mesh->getMeshBuffer(0)->getMaterial() = m;
m.MaterialType = video::EMT_SOLID;
m.setTexture(0, getUnicolorTexture(video::SColor(128, 255, 105, 180)));
m.setTexture(1, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
if (CVS->isGLSL())
{
STKMeshSceneNode *node =
new STKMeshSceneNode(mesh,
m_scene_manager->getRootSceneNode(),
NULL, -1, "sphere");
return node;
}
scene::IMeshSceneNode *node = m_scene_manager->addMeshSceneNode(mesh);
return node;
} // addSphere

View File

@ -474,6 +474,7 @@ unsigned ShaderBasedRenderer::updateLightsInfo(scene::ICameraSceneNode * const c
}
unsigned lightnum = 0;
bool multiplayer = (race_manager->getNumLocalPlayers() > 1);
for (unsigned i = 0; i < 15; i++)
{
@ -491,7 +492,12 @@ unsigned ShaderBasedRenderer::updateLightsInfo(scene::ICameraSceneNode * const c
float em = light_node->getEnergyMultiplier();
if (em < 1.0f)
{
light_node->setEnergyMultiplier(std::min(1.0f, em + dt));
// In single-player, fade-in lights.
// In multi-player, can't do that, the light objects are shared by all players
if (multiplayer)
light_node->setEnergyMultiplier(1.0f);
else
light_node->setEnergyMultiplier(std::min(1.0f, em + dt));
}
const core::vector3df &pos = light_node->getAbsolutePosition();

View File

@ -18,6 +18,7 @@
#include "graphics/show_curve.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/irr_driver.hpp"
#include "utils/vec3.hpp"
@ -64,6 +65,9 @@ void ShowCurve::addEmptyMesh()
m_mesh = irr_driver->createQuadMesh(&m,
/*create_one_quad*/ false);
m_buffer = m_mesh->getMeshBuffer(0);
m_buffer->getMaterial().setTexture(0, getUnicolorTexture(video::SColor(128, 255, 105, 180)));
m_buffer->getMaterial().setTexture(1, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
assert(m_buffer->getVertexType()==video::EVT_STANDARD);
} // addEmptyMesh

View File

@ -252,13 +252,16 @@ void fillLocalBuffer(GLMesh &mesh, scene::IMeshBuffer* mb)
glGenBuffers(1, &(mesh.index_buffer));
glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex_buffer);
const void* vertices = mb->getVertices();
const u32 vertexCount = mb->getVertexCount();
// This can happen for certain debug structures, e.g. ShowCurve
if (vertexCount == 0)
return;
const c8* vbuf = static_cast<const c8*>(vertices);
glBufferData(GL_ARRAY_BUFFER, vertexCount * mesh.Stride, vbuf,
GL_STREAM_DRAW);
assert(vertexCount);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index_buffer);
const void* indices = mb->getIndices();

View File

@ -417,10 +417,8 @@ void PlayerKartWidget::markAsReady()
// 'playerNameString' is already fribidize, so we need to use
// 'insertValues' and not _("...", a) so it's not flipped again
m_ready_text =
GUIEngine::getGUIEnv()->addStaticText(
StringUtils::insertValues(_("%s is ready"),
playerNameString).c_str(),
rect );
GUIEngine::getGUIEnv()->addStaticText(_("%s is ready", playerNameString),
rect);
m_ready_text->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER );
m_children.remove(m_player_ident_spinner);

View File

@ -111,84 +111,84 @@ irr::core::stringw Binding::getAsString() const
case 222: s="'"; break;
#endif
//I18N: input configuration screen: mouse button
case irr::KEY_LBUTTON : s = _("Left Mouse Button"); break;
case irr::KEY_LBUTTON : s = _C("input_key", "Left Mouse Button"); break;
//I18N: input configuration screen: mouse button
case irr::KEY_RBUTTON : s = _("Right Mouse Button"); break;
case irr::KEY_RBUTTON : s = _C("input_key", "Right Mouse Button"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_CANCEL : s = _("Cancel"); break;
case irr::KEY_CANCEL : s = _C("input_key", "Cancel"); break;
//I18N: input configuration screen: mouse button
case irr::KEY_MBUTTON : s = _("Middle Mouse Button"); break;
case irr::KEY_MBUTTON : s = _C("input_key", "Middle Mouse Button"); break;
//I18N: input configuration screen: mouse button
case irr::KEY_XBUTTON1 : s = _("X1 Mouse Button"); break;
case irr::KEY_XBUTTON1 : s = _C("input_key", "X1 Mouse Button"); break;
//I18N: input configuration screen: mouse button
case irr::KEY_XBUTTON2 : s = _("X2 Mouse Button"); break;
case irr::KEY_XBUTTON2 : s = _C("input_key", "X2 Mouse Button"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_BACK : s = _("Backspace"); break;
case irr::KEY_BACK : s = _C("input_key", "Backspace"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_TAB : s = _("Tab"); break;
case irr::KEY_TAB : s = _C("input_key", "Tab"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_CLEAR : s = _("Clear"); break;
case irr::KEY_CLEAR : s = _C("input_key", "Clear"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_RETURN : s = _("Return"); break;
case irr::KEY_RETURN : s = _C("input_key", "Return"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_SHIFT : s = _("Shift"); break;
case irr::KEY_SHIFT : s = _C("input_key", "Shift"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_CONTROL : s = _("Control"); break;
case irr::KEY_CONTROL : s = _C("input_key", "Control"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_MENU : s = _("Alt/Menu"); break;
case irr::KEY_MENU : s = _C("input_key", "Alt/Menu"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_PAUSE : s = _("Pause"); break;
case irr::KEY_PAUSE : s = _C("input_key", "Pause"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_CAPITAL : s = _("Caps Lock"); break;
case irr::KEY_CAPITAL : s = _C("input_key", "Caps Lock"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_KANA : s = _("Kana"); break;
case irr::KEY_KANA : s = _C("input_key", "Kana"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_JUNJA : s = _("Junja"); break;
case irr::KEY_JUNJA : s = _C("input_key", "Junja"); break;
//I18N: input configuration screen: keyboard key
//I18N: input configuration screen: keyboard key
case irr::KEY_FINAL : s = _("Final"); break;
case irr::KEY_FINAL : s = _C("input_key", "Final"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_ESCAPE : s = _("Escape"); break;
case irr::KEY_ESCAPE : s = _C("input_key", "Escape"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_CONVERT : s = _("Convert"); break;
case irr::KEY_CONVERT : s = _C("input_key", "Convert"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NONCONVERT : s = _("Nonconvert"); break;
case irr::KEY_NONCONVERT : s = _C("input_key", "Nonconvert"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_ACCEPT : s = _("Accept"); break;
case irr::KEY_ACCEPT : s = _C("input_key", "Accept"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_MODECHANGE : s = _("Modechange"); break;
case irr::KEY_MODECHANGE : s = _C("input_key", "Modechange"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_SPACE : s = _("Space"); break;
case irr::KEY_SPACE : s = _C("input_key", "Space"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_PRIOR : s = _("Page Up"); break;
case irr::KEY_PRIOR : s = _C("input_key", "Page Up"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NEXT : s = _("Page Down"); break;
case irr::KEY_NEXT : s = _C("input_key", "Page Down"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_END : s = _("End"); break;
case irr::KEY_END : s = _C("input_key", "End"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_HOME : s = _("Home"); break;
case irr::KEY_HOME : s = _C("input_key", "Home"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_LEFT : s = _("Left"); break;
case irr::KEY_LEFT : s = _C("input_key", "Left"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_UP : s = _("Up"); break;
case irr::KEY_UP : s = _C("input_key", "Up"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_RIGHT : s = _("Right"); break;
case irr::KEY_RIGHT : s = _C("input_key", "Right"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_DOWN : s = _("Down"); break;
case irr::KEY_DOWN : s = _C("input_key", "Down"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_SELECT : s = _("Select"); break;
case irr::KEY_SELECT : s = _C("input_key", "Select"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_PRINT : s = _("Print"); break;
case irr::KEY_PRINT : s = _C("input_key", "Print"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_EXECUT : s = _("Exec"); break;
case irr::KEY_EXECUT : s = _C("input_key", "Exec"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_SNAPSHOT : s = _("Print Screen"); break;
case irr::KEY_SNAPSHOT : s = _C("input_key", "Print Screen"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_INSERT : s = _("Insert"); break;
case irr::KEY_INSERT : s = _C("input_key", "Insert"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_DELETE : s = _("Delete"); break;
case irr::KEY_DELETE : s = _C("input_key", "Delete"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_HELP : s = _("Help"); break;
case irr::KEY_HELP : s = _C("input_key", "Help"); break;
case irr::KEY_KEY_0 : s = "0"; break;
case irr::KEY_KEY_1 : s = "1"; break;
case irr::KEY_KEY_2 : s = "2"; break;
@ -226,43 +226,43 @@ irr::core::stringw Binding::getAsString() const
case irr::KEY_KEY_Y : s = "Y"; break;
case irr::KEY_KEY_Z : s = "Z"; break;
//I18N: input configuration screen: keyboard key
case irr::KEY_LWIN : s = _("Left Logo"); break;
case irr::KEY_LWIN : s = _C("input_key", "Left Logo"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_RWIN : s = _("Right Logo"); break;
case irr::KEY_RWIN : s = _C("input_key", "Right Logo"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_APPS : s = _("Apps"); break;
case irr::KEY_APPS : s = _C("input_key", "Apps"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_SLEEP : s = _("Sleep"); break;
case irr::KEY_SLEEP : s = _C("input_key", "Sleep"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NUMPAD0 : s = _("Numpad 0"); break;
case irr::KEY_NUMPAD0 : s = _C("input_key", "Numpad 0"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NUMPAD1 : s = _("Numpad 1"); break;
case irr::KEY_NUMPAD1 : s = _C("input_key", "Numpad 1"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NUMPAD2 : s = _("Numpad 2"); break;
case irr::KEY_NUMPAD2 : s = _C("input_key", "Numpad 2"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NUMPAD3 : s = _("Numpad 3"); break;
case irr::KEY_NUMPAD3 : s = _C("input_key", "Numpad 3"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NUMPAD4 : s = _("Numpad 4"); break;
case irr::KEY_NUMPAD4 : s = _C("input_key", "Numpad 4"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NUMPAD5 : s = _("Numpad 5"); break;
case irr::KEY_NUMPAD5 : s = _C("input_key", "Numpad 5"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NUMPAD6 : s = _("Numpad 6"); break;
case irr::KEY_NUMPAD6 : s = _C("input_key", "Numpad 6"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NUMPAD7 : s = _("Numpad 7"); break;
case irr::KEY_NUMPAD7 : s = _C("input_key", "Numpad 7"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NUMPAD8 : s = _("Numpad 8"); break;
case irr::KEY_NUMPAD8 : s = _C("input_key", "Numpad 8"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NUMPAD9 : s = _("Numpad 9"); break;
case irr::KEY_NUMPAD9 : s = _C("input_key", "Numpad 9"); break;
case irr::KEY_MULTIPLY : s = "*"; break;
case irr::KEY_ADD : s = "+"; break;
//I18N: input configuration screen: keyboard key
case irr::KEY_SEPARATOR : s = _("Separator"); break;
case irr::KEY_SEPARATOR : s = _C("input_key", "Separator"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_SUBTRACT : s = _("- (Subtract)"); break;
case irr::KEY_SUBTRACT : s = _C("input_key", "- (Subtract)"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_DECIMAL : s = _("Decimal"); break;
case irr::KEY_DECIMAL : s = _C("input_key", "Decimal"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_DIVIDE : s = _("/ (Divide)"); break;
case irr::KEY_DIVIDE : s = _C("input_key", "/ (Divide)"); break;
case irr::KEY_F1 : s = "F1"; break;
case irr::KEY_F2 : s = "F2"; break;
case irr::KEY_F3 : s = "F3"; break;
@ -288,41 +288,41 @@ irr::core::stringw Binding::getAsString() const
case irr::KEY_F23 : s = "F23"; break;
case irr::KEY_F24 : s = "F24"; break;
//I18N: input configuration screen: keyboard key
case irr::KEY_NUMLOCK : s = _("Num Lock"); break;
case irr::KEY_NUMLOCK : s = _C("input_key", "Num Lock"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_SCROLL : s = _("Scroll Lock"); break;
case irr::KEY_SCROLL : s = _C("input_key", "Scroll Lock"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_LSHIFT : s = _("Left Shift"); break;
case irr::KEY_LSHIFT : s = _C("input_key", "Left Shift"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_RSHIFT : s = _("Right Shift"); break;
case irr::KEY_RSHIFT : s = _C("input_key", "Right Shift"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_LCONTROL : s = _("Left Control"); break;
case irr::KEY_LCONTROL : s = _C("input_key", "Left Control"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_RCONTROL : s = _("Right Control"); break;
case irr::KEY_RCONTROL : s = _C("input_key", "Right Control"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_LMENU : s = _("Left Menu"); break;
case irr::KEY_LMENU : s = _C("input_key", "Left Menu"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_RMENU : s = _("Right Menu"); break;
case irr::KEY_RMENU : s = _C("input_key", "Right Menu"); break;
case irr::KEY_PLUS : s = "+"; break;
case irr::KEY_COMMA : s = ","; break;
case irr::KEY_MINUS : s = "-"; break;
case irr::KEY_PERIOD : s = "."; break;
//I18N: input configuration screen: keyboard key
case irr::KEY_ATTN : s = _("Attn"); break;
case irr::KEY_ATTN : s = _C("input_key", "Attn"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_CRSEL : s = _("Crsel"); break;
case irr::KEY_CRSEL : s = _C("input_key", "Crsel"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_EXSEL : s = _("Exsel"); break;
case irr::KEY_EXSEL : s = _C("input_key", "Exsel"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_EREOF : s = _("Ereof"); break;
case irr::KEY_EREOF : s = _C("input_key", "Ereof"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_PLAY : s = _("Play"); break;
case irr::KEY_PLAY : s = _C("input_key", "Play"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_ZOOM : s = _("Zoom"); break;
case irr::KEY_ZOOM : s = _C("input_key", "Zoom"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_PA1 : s = _("Pa1"); break;
case irr::KEY_PA1 : s = _C("input_key", "Pa1"); break;
//I18N: input configuration screen: keyboard key
case irr::KEY_OEM_CLEAR : s = _("Oem Clear"); break;
case irr::KEY_OEM_CLEAR : s = _C("input_key", "Oem Clear"); break;
}
break;

View File

@ -139,6 +139,7 @@ void Attachment::set(AttachmentType type, float time,
break;
case ATTACH_BOMB:
m_node->setMesh(attachment_manager->getMesh(type));
m_node->setAnimationSpeed(0);
if (m_bomb_sound) m_bomb_sound->deleteSFX();
m_bomb_sound = SFXManager::get()->createSoundSource("clock");
m_bomb_sound->setLoop(true);

View File

@ -321,6 +321,24 @@ void PlayerController::update(float dt)
if (!history->replayHistory())
steer(dt, m_steer_val);
// look backward when the player requests or
// if automatic reverse camera is active
if (m_camera->getMode() != Camera::CM_FINAL)
{
if (m_controls->m_look_back || (UserConfigParams::m_reverse_look_threshold > 0 &&
m_kart->getSpeed() < -UserConfigParams::m_reverse_look_threshold))
{
m_camera->setMode(Camera::CM_REVERSE);
}
else
{
if (m_camera->getMode() == Camera::CM_REVERSE)
m_camera->setMode(Camera::CM_NORMAL);
}
}
if (World::getWorld()->isStartPhase())
{
if (m_controls->m_accel || m_controls->m_brake ||
@ -358,21 +376,7 @@ void PlayerController::update(float dt)
return;
}
// look backward when the player requests or
// if automatic reverse camera is active
if (m_camera->getMode() != Camera::CM_FINAL)
{
if (m_controls->m_look_back || (UserConfigParams::m_reverse_look_threshold>0 &&
m_kart->getSpeed()<-UserConfigParams::m_reverse_look_threshold))
{
m_camera->setMode(Camera::CM_REVERSE);
}
else
{
if (m_camera->getMode() == Camera::CM_REVERSE)
m_camera->setMode(Camera::CM_NORMAL);
}
}
// We can't restrict rescue to fulfil isOnGround() (which would be more like
// MK), since e.g. in the City track it is possible for the kart to end

View File

@ -19,24 +19,10 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//The AI debugging works best with just 1 AI kart, so set the number of karts
//to 2 in main.cpp with quickstart and run supertuxkart with the arg -N.
#ifdef DEBUG
// Enable AI graphical debugging
# undef AI_DEBUG
// Shows left and right lines when using new findNonCrashing function
# undef AI_DEBUG_NEW_FIND_NON_CRASHING
// Show the predicted turn circles
# undef AI_DEBUG_CIRCLES
// Show the heading of the kart
# undef AI_DEBUG_KART_HEADING
// Shows line from kart to its aim point
# undef AI_DEBUG_KART_AIM
#endif
#include "karts/controller/skidding_ai.hpp"
#ifdef AI_DEBUG
# include "graphics/glwrap.hpp"
# include "graphics/irr_driver.hpp"
#endif
#include "graphics/show_curve.hpp"
@ -110,6 +96,8 @@ SkiddingAI::SkiddingAI(AbstractKart *kart)
i==2 ? 128 : 0);
m_debug_sphere[i] = irr_driver->addSphere(1.0f, col_debug);
m_debug_sphere[i]->setVisible(false);
m_debug_sphere[i]->setMaterialTexture(0, getUnicolorTexture(video::SColor(128, 255, 105, 180)));
m_debug_sphere[i]->setMaterialTexture(1, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
}
m_debug_sphere[m_point_selection_algorithm]->setVisible(true);
m_item_sphere = irr_driver->addSphere(1.0f);
@ -166,7 +154,7 @@ SkiddingAI::~SkiddingAI()
{
delete m_curve[i];
}
delete m_curve;
delete [] m_curve;
#endif
} // ~SkiddingAI
@ -1843,7 +1831,7 @@ void SkiddingAI::findNonCrashingPointNew(Vec3 *result, int *last_node)
m_curve[CURVE_RIGHT]->addPoint(q[RIGHT_END_POINT]+eps1);
m_curve[CURVE_RIGHT]->addPoint(m_kart->getXYZ()+eps1);
#endif
#ifdef AI_DEBUG_KART_HEADING
#if defined(AI_DEBUG_KART_HEADING) || defined(AI_DEBUG_NEW_FIND_NON_CRASHING)
const Vec3 eps(0,0.5f,0);
m_curve[CURVE_KART]->clear();
m_curve[CURVE_KART]->addPoint(m_kart->getXYZ()+eps);

View File

@ -22,6 +22,27 @@
#ifndef HEADER_SKIDDING_AI_HPP
#define HEADER_SKIDDING_AI_HPP
// Some debugging features for the AI. For example you can visualise the
// point the AI is aiming at, or visualise the curve the AI is predicting.
// It works best with just 1 AI kart, so set the number of karts
// to 2 in main.cpp with quickstart and run supertuxkart with the arg -N.
// Or use --profile-laps=99 and run just one AI. Using the debug camera
// (top view) is useful, too
#ifdef DEBUG
// Enable AI graphical debugging
# undef AI_DEBUG
// Shows left and right lines when using new findNonCrashing function
# undef AI_DEBUG_NEW_FIND_NON_CRASHING
// Show the predicted turn circles
# undef AI_DEBUG_CIRCLES
// Show the heading of the kart
# undef AI_DEBUG_KART_HEADING
// Shows line from kart to its aim point
# undef AI_DEBUG_KART_AIM
#endif
#include "karts/controller/ai_base_controller.hpp"
#include "race/race_manager.hpp"
#include "tracks/graph_node.hpp"

View File

@ -164,6 +164,7 @@ Kart::Kart (const std::string& ident, unsigned int world_kart_id,
m_boing_sound = SFXManager::get()->createSoundSource( "boing" );
m_goo_sound = SFXManager::get()->createSoundSource( "goo" );
m_skid_sound = SFXManager::get()->createSoundSource( "skid" );
m_nitro_sound = SFXManager::get()->createSoundSource( "nitro" );
m_terrain_sound = NULL;
m_previous_terrain_sound = NULL;
@ -190,6 +191,7 @@ void Kart::init(RaceManager::KartType type)
m_crash_sound->setVolume( 1.0f / factor );
m_boing_sound->setVolume( 1.0f / factor );
m_beep_sound->setVolume( 1.0f / factor );
m_nitro_sound->setVolume( 1.0f / factor );
}
else
{
@ -198,6 +200,7 @@ void Kart::init(RaceManager::KartType type)
m_crash_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
m_beep_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
m_boing_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
m_nitro_sound->setVolume( 1.0f / race_manager->getNumberOfKarts() );
}
}
@ -254,6 +257,7 @@ Kart::~Kart()
m_goo_sound ->deleteSFX();
m_beep_sound ->deleteSFX();
m_boing_sound ->deleteSFX();
m_nitro_sound ->deleteSFX();
delete m_kart_gfx;
if(m_terrain_sound) m_terrain_sound->deleteSFX();
if(m_previous_terrain_sound) m_previous_terrain_sound->deleteSFX();
@ -602,7 +606,7 @@ void Kart::createPhysics()
// The y position of the wheels (i.e. the points where
// the suspension is attached to) is just at the
// bottom of the kart. That is half the kart height
// down.
// down.
wheel_pos[index].setY(- 0.5f*kart_height);
wheel_pos[index].setZ((0.5f*kart_length-0.25f)* z);
@ -1187,6 +1191,7 @@ void Kart::update(float dt)
m_crash_sound->setPosition ( getXYZ() );
m_skid_sound->setPosition ( getXYZ() );
m_boing_sound->setPosition ( getXYZ() );
m_nitro_sound->setPosition ( getXYZ() );
// Check if a kart is (nearly) upside down and not moving much -->
// automatic rescue
@ -1216,19 +1221,19 @@ void Kart::update(float dt)
m_xyz_front = getTrans()(front);
// After the physics step was done, the position of the wheels (as stored
// in wheelInfo) is actually outdated, since the chassis was moved
// in wheelInfo) is actually outdated, since the chassis was moved
// according to the force acting from the wheels. So the cnter of the
// chassis is not at the center of the wheels anymore, it is somewhat
// moved forward (depending on speed and fps). In very extreme cases
// (see bug 2246) the center of the chassis can actually be ahead of the
// front wheels. So if we do a raycast to detect the terrain from the
// current chassis, that raycast might be ahead of the wheels - which
// current chassis, that raycast might be ahead of the wheels - which
// results in incorrect rescues (the wheels are still on the ground,
// but the raycast happens ahead of the front wheels and are over
// a rescue texture).
// To avoid this problem, we do the raycast for terrain detection from
// the center of the 4 wheel positions (in world coordinates).
Vec3 from(0, 0, 0);
for (unsigned int i = 0; i < 4; i++)
from += m_vehicle->getWheelInfo(i).m_raycastInfo.m_hardPointWS;
@ -1710,18 +1715,25 @@ void Kart::updateNitro(float dt)
bool increase_speed = (m_controls.m_nitro && isOnGround());
if (!increase_speed && m_min_nitro_time <= 0.0f)
{
if(m_nitro_sound->getStatus() == SFXBase::SFX_PLAYING)
m_nitro_sound->stop();
return;
}
m_collected_energy -= dt * m_kart_properties->getNitroConsumption() *
m_difficulty->getNitroConsumption();
if (m_collected_energy < 0)
{
if(m_nitro_sound->getStatus() == SFXBase::SFX_PLAYING)
m_nitro_sound->stop();
m_collected_energy = 0;
return;
}
if (increase_speed)
{
if(m_nitro_sound->getStatus() != SFXBase::SFX_PLAYING)
m_nitro_sound->play();
m_max_speed->increaseMaxSpeed(MaxSpeed::MS_INCREASE_NITRO,
m_kart_properties->getNitroMaxSpeedIncrease() *
m_difficulty->getNitroMaxSpeedIncrease(),
@ -1732,6 +1744,11 @@ void Kart::updateNitro(float dt)
m_kart_properties->getNitroFadeOutTime() *
m_difficulty->getNitroFadeOutTime());
}
else
{
if(m_nitro_sound->getStatus() == SFXBase::SFX_PLAYING)
m_nitro_sound->stop();
}
} // updateNitro
// -----------------------------------------------------------------------------
@ -2475,7 +2492,7 @@ void Kart::kartIsInRestNow()
* physics-only simulation steps so that karts come to a rest). Then at
* race time, only the difference between the current suspension length and
* this default suspension length is used. The graphical kart chassis will be
* offset so that when the kart is in rest, i.e. suspension length ==
* offset so that when the kart is in rest, i.e. suspension length ==
* default suspension length, the kart will look the way it was modelled in
* blender. To explain the various offsets used, here a view from the side
* focusing on the Y axis only (X/Z position of the graphical chassis is
@ -2533,7 +2550,7 @@ void Kart::kartIsInRestNow()
* and so not easily visible), so if the suspension is compressed by more than
* that, the chassiswill appear to be in the ground. Testing on the sand track
* shows that the suspension is compressed by 0.12 (and up to 0.16 in some
* extreme points), which means that the chassis will appear to be in the
* extreme points), which means that the chassis will appear to be in the
* ground quite easily. Therefore the chassis is actually moved up a bit to
* avoid this problem. Historically (due to never sorting out that formula
* properly) the chassis was moved twice as high as its lowest point, e.g.
@ -2543,7 +2560,7 @@ void Kart::kartIsInRestNow()
* same amount higher.
*
* Of course this means that the Y position of the wheels (relative to the
* visual kart chassis) needs to be adjusted: if the kart is in rest, the
* visual kart chassis) needs to be adjusted: if the kart is in rest, the
* wheels are exactly on the ground. If the suspension is shorter, that wheel
* would appear to be partly in the ground, and if the suspension is longer,
* the wheel would not touch the ground.
@ -2551,7 +2568,7 @@ void Kart::kartIsInRestNow()
* The wheels must be offset by how much the current suspension length is
* longer or shorter than the default (i.e. at rest) suspension length.
* This is done in KartModel (pos is the position of the wheel relative
* to the visual kart chassis):
* to the visual kart chassis):
* pos.Y += m_default_physics_suspension[i]
* - wi.m_raycastInfo.m_suspensionLength
* But since the chassis is raised an additional 'getLowestPoint' (see
@ -2666,7 +2683,7 @@ void Kart::updateGraphics(float dt, const Vec3& offset_xyz,
if (m_shadow)
{
const bool emergency = getKartAnimation() != NULL;
m_shadow->update(isOnGround() && !emergency,
m_shadow->update(isOnGround() && !emergency,
m_terrain_info->getHoT() - getXYZ().getY()
- m_skidding->getGraphicalJumpOffset()
- m_graphical_y_offset
@ -2724,7 +2741,7 @@ void Kart::setOnScreenText(const wchar_t *text)
if (CVS->isGLSL())
{
gui::ScalableFont* font = GUIEngine::getFont() ? GUIEngine::getFont()
gui::ScalableFont* font = GUIEngine::getFont() ? GUIEngine::getFont()
: GUIEngine::getTitleFont();
new STKTextBillboard(text, font,
video::SColor(255, 255, 225, 0),

View File

@ -149,7 +149,7 @@ private:
/** True if fire button was pushed and not released */
bool m_fire_clicked;
/** Counter which is used for displaying wrong way message after a delay */
float m_wrongway_counter;
@ -200,6 +200,7 @@ private:
SFXBase *m_engine_sound;
SFXBase *m_crash_sound;
SFXBase *m_terrain_sound;
SFXBase *m_nitro_sound;
/** A pointer to the previous terrain sound needs to be saved so that an
* 'older' sfx can be finished and an abrupt end of the sfx is avoided. */
SFXBase *m_previous_terrain_sound;

View File

@ -452,7 +452,7 @@ public:
*/
core::stringw getName() const
{
return core::stringw(translations->w_gettext(m_name.c_str()));
return _LTR(m_name.c_str());
}
// ------------------------------------------------------------------------

View File

@ -848,7 +848,7 @@ int handleCmdLine()
race_manager->setNumKarts((int)l.size()+1);
} // --ai
if(CommandLine::has( "--mode", &s))
if(CommandLine::has( "--mode", &s) || CommandLine::has( "--difficulty", &s))
{
int n = atoi(s.c_str());
if(n<0 || n>RaceManager::DIFFICULTY_LAST)

View File

@ -199,9 +199,8 @@ void EasterEggHunt::getKartsDisplayInfo(
{
RaceGUIBase::KartIconDisplayInfo& rank_info = (*info)[i];
//I18n: number of collected eggs / overall number of eggs
rank_info.m_text = StringUtils::insertValues(_("Eggs: %d / %d"),
m_eggs_collected[i],
m_number_of_eggs);
rank_info.m_text = _("Eggs: %d / %d", m_eggs_collected[i],
m_number_of_eggs);
rank_info.m_color = video::SColor(255, 255, 255, 255);
}
} // getKartDisplayInfo

View File

@ -173,7 +173,15 @@ void LinearWorld::update(float dt)
// Nothing to do for karts that are currently being
// rescued or eliminated
if(kart->getKartAnimation()) continue;
// If the kart is off road, and 'flying' over a reset plane
// don't adjust the distance of the kart, to avoid a jump
// in the position of the kart (e.g. while falling the kart
// might get too close to another part of the track, shortly
// jump to position one, then on reset fall back to last)
if (!kart_info.getTrackSector()->isOnRoad() &&
(!kart->getMaterial() ||
kart->getMaterial()->isDriveReset()) )
continue;
kart_info.getTrackSector()->update(kart->getFrontXYZ());
kart_info.m_overall_distance = kart_info.m_race_lap
* m_track->getTrackLength()

View File

@ -173,10 +173,13 @@ namespace Online
// Check if failure happened during automatic (saved) signin.
else if (!isSuccess())
{
if (GUIEngine::getCurrentScreen() != MainMenuScreen::getInstance())
if (GUIEngine::getCurrentScreen() != MainMenuScreen::getInstance() ||
GUIEngine::ModalDialog::isADialogActive())
{
// User has already opened another menu, so use message queue
// to inform user that login failed.
// Same thing if a dialog is active, can't navigate to other
// screen when a dialog is active
MessageQueue::add(MessageQueue::MT_ERROR, getInfo());
return;
}

View File

@ -324,7 +324,6 @@ void PhysicalObject::init()
}
case MP_EXACT:
{
m_graphical_offset = Vec3(0,0,0);
extend.setY(0);
TriangleMesh* triangle_mesh = new TriangleMesh();
@ -450,7 +449,8 @@ void PhysicalObject::init()
triangle_mesh->createCollisionShape();
m_shape = &triangle_mesh->getCollisionShape();
m_triangle_mesh = triangle_mesh;
m_init_pos.setOrigin(m_init_pos.getOrigin() + m_graphical_offset);
// m_graphical_offset = Vec3(0,0,0);
break;
}
case MP_NONE:

View File

@ -167,8 +167,8 @@ public:
// -------------------------------------------------------------------------
enum GPReverseType getReverseType()
const { return m_reverse_type; }
static const char* getRandomGPID() { return "random"; }
static const wchar_t* getRandomGPName() { return _LTR("Random Grand Prix");}
static const char* getRandomGPID() { return "random"; }
static irr::core::stringw getRandomGPName() { return _LTR("Random Grand Prix"); }
}; // GrandPrixData
#endif

View File

@ -168,7 +168,7 @@ public:
/** Returns a (translated) name of a minor race mode.
* \param mode Minor race mode.
*/
static const wchar_t* getNameOf(const MinorRaceModeType mode)
static const core::stringw getNameOf(const MinorRaceModeType mode)
{
switch (mode)
{
@ -184,7 +184,7 @@ public:
case MINOR_MODE_EASTER_EGG: return _("Egg Hunt");
//I18N: Game mode
case MINOR_MODE_SOCCER: return _("Soccer");
default: assert(false); return NULL;
default: assert(false); return L"";
}
} // getNameOf

View File

@ -356,9 +356,8 @@ void AddonsLoading::doInstall()
bool error = !addons_manager->install(m_addon);
if(error)
{
core::stringw msg = StringUtils::insertValues(
_("Problems installing the addon '%s'."),
core::stringw(m_addon.getName().c_str()));
const core::stringw &name = m_addon.getName();
core::stringw msg = _("Problems installing the addon '%s'.", name);
getWidget<BubbleWidget>("description")->setText(msg.c_str());
}
@ -394,8 +393,8 @@ void AddonsLoading::doUninstall()
Log::warn("Addons", "Directory '%s' can not be removed.",
m_addon.getDataDir().c_str());
Log::warn("Addons", "Please remove this directory manually.");
core::stringw msg = StringUtils::insertValues(_("Problems removing the addon '%s'."),
core::stringw(m_addon.getName().c_str()));
const core::stringw &name = m_addon.getName();
core::stringw msg = _("Problems removing the addon '%s'.", name);
getWidget<BubbleWidget>("description")->setText(msg.c_str());
}

View File

@ -54,8 +54,8 @@ void GrandPrixEditorScreen::beforeAddingWidget()
tabs->clearAllChildren();
for (int i = 0; i < GrandPrixData::GP_GROUP_COUNT; i++)
{
tabs->addTextChild(getGroupName((enum GrandPrixData::GPGroupType)i),
StringUtils::toString(i));
core::stringw label = getGroupName((enum GrandPrixData::GPGroupType)i);
tabs->addTextChild(label.c_str(), StringUtils::toString(i));
}
}
@ -317,7 +317,7 @@ void GrandPrixEditorScreen::onConfirm()
}
// ----------------------------------------------------------------------------
const wchar_t* GrandPrixEditorScreen::getGroupName(enum GrandPrixData::GPGroupType group)
const core::stringw GrandPrixEditorScreen::getGroupName(enum GrandPrixData::GPGroupType group)
{
switch (group)
{

View File

@ -51,7 +51,7 @@ class GrandPrixEditorScreen :
void onNewGPWithName(const irr::core::stringw& newName);
void onConfirm();
static const wchar_t* getGroupName(enum GrandPrixData::GPGroupType group);
static const core::stringw getGroupName(enum GrandPrixData::GPGroupType group);
GrandPrixData* m_selection;
std::string m_action;

View File

@ -18,6 +18,7 @@
#include "states_screens/grand_prix_lose.hpp"
#include "audio/music_manager.hpp"
#include "audio/sfx_manager.hpp"
#include "challenges/unlock_manager.hpp"
#include "config/player_manager.hpp"
@ -209,3 +210,11 @@ void GrandPrixLose::setKarts(std::vector<std::string> ident_arg)
// -------------------------------------------------------------------------------------
MusicInformation* GrandPrixLose::getInGameMenuMusic() const
{
MusicInformation* mi = music_manager->getMusicInformation("lose_theme.music");
return mi;
}
// -------------------------------------------------------------------------------------

View File

@ -62,6 +62,7 @@ public:
void onUpdate(float dt) OVERRIDE;
/** \brief set which karts lost this GP */
void setKarts(std::vector<std::string> ident);
MusicInformation* getInGameMenuMusic() const OVERRIDE;
};
#endif

View File

@ -18,6 +18,7 @@
#include "states_screens/grand_prix_win.hpp"
#include "audio/music_manager.hpp"
#include "audio/sfx_manager.hpp"
#include "challenges/unlock_manager.hpp"
#include "config/player_manager.hpp"
@ -347,3 +348,12 @@ void GrandPrixWin::setKarts(const std::string idents_arg[3])
} // setKarts
// -------------------------------------------------------------------------------------
MusicInformation* GrandPrixWin::getInGameMenuMusic() const
{
MusicInformation* mi = music_manager->getMusicInformation("win_theme.music");
return mi;
}
// -------------------------------------------------------------------------------------

View File

@ -66,6 +66,7 @@ public:
void loadedFromFile() OVERRIDE {};
void onCutsceneEnd() OVERRIDE;
void onUpdate(float dt) OVERRIDE;
MusicInformation* getInGameMenuMusic() const OVERRIDE;
/** \pre must be called after pushing the screen, but before onUpdate had the chance to be invoked */
void setKarts(const std::string idents[3]);

View File

@ -175,7 +175,7 @@ void MainMenuScreen::onUpdate(float delta)
m_online->setLabel( _("Login" ));
m_user_id->setText(player->getName());
}
else
else
{
// now must be either logging in or logging out
m_online->setActive(false);
@ -297,7 +297,7 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
StoryModeStatus* sms = PlayerManager::getCurrentPlayer()->getStoryModeStatus();
sms->unlockFeature(const_cast<ChallengeStatus*>(sms->getChallengeStatus("gp1")),
RaceManager::DIFFICULTY_HARD);
StateManager::get()->enterGameState();
race_manager->setMinorMode(RaceManager::MINOR_MODE_CUTSCENE);
race_manager->setNumKarts(0);
@ -307,7 +307,7 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
FeatureUnlockedCutScene* scene =
FeatureUnlockedCutScene::getInstance();
std::vector<std::string> parts;
parts.push_back("featunlocked");
((CutsceneWorld*)World::getWorld())->setParts(parts);
@ -494,9 +494,12 @@ void MainMenuScreen::eventCallback(Widget* widget, const std::string& name,
if (PlayerManager::getCurrentOnlineId())
{
// For 0.8.2 disable the server menu, instead go to online profile
//OnlineScreen::getInstance()->push();
#ifdef ENABLE_NETWORK_MULTIPLAYER_SCREEN
OnlineScreen::getInstance()->push();
#else
ProfileManager::get()->setVisiting(PlayerManager::getCurrentOnlineId());
TabOnlineProfileAchievements::getInstance()->push();
#endif
}
else
{

View File

@ -35,6 +35,9 @@ using namespace Online;
DEFINE_SCREEN_SINGLETON( OnlineProfileFriends );
int OnlineProfileFriends::m_sort_column = 0;
bool OnlineProfileFriends::m_sort_increasing = true;
// -----------------------------------------------------------------------------
/** Constructor for a display of all friends.
*/
@ -55,6 +58,8 @@ void OnlineProfileFriends::loadedFromFile()
assert(m_search_button_widget != NULL);
m_search_box_widget = getWidget<TextBoxWidget>("search_box");
assert(m_search_box_widget != NULL);
m_friends_list_widget->setColumnListener(this);
} // loadedFromFile
// ----------------------------------------------------------------------------
@ -78,6 +83,8 @@ void OnlineProfileFriends::beforeAddingWidget()
void OnlineProfileFriends::init()
{
OnlineProfileBase::init();
m_sort_column = 0;
m_sort_increasing = true;
m_profile_tabs->select( m_friends_tab->m_properties[PROP_ID],
PLAYER_ID_GAME_MASTER );
assert(m_visiting_profile != NULL);
@ -104,19 +111,84 @@ void OnlineProfileFriends::eventCallback(Widget* widget,
}
else if (name == m_friends_list_widget->m_properties[GUIEngine::PROP_ID])
{
int index = m_friends_list_widget->getSelectionID();
if (index>-1)
new UserInfoDialog(m_visiting_profile->getFriends()[index]);
std::string str_selection = m_friends_list_widget->getSelectionInternalName();
int id;
if (StringUtils::parseString(str_selection, &id))
{
new UserInfoDialog(id);
}
}
} // eventCallback
// ----------------------------------------------------------------------------
void OnlineProfileFriends::onColumnClicked(int column_id)
{
if (column_id == m_sort_column)
m_sort_increasing = !m_sort_increasing;
else
{
m_sort_increasing = true;
}
m_sort_column = column_id;
displayResults();
} // onColumnClicked
// ----------------------------------------------------------------------------
bool OnlineProfileFriends::compareFriends(int f1, int f2)
{
Online::OnlineProfile *p1 = ProfileManager::get()->getProfileByID(f1);
Online::OnlineProfile *p2 = ProfileManager::get()->getProfileByID(f2);
switch (m_sort_column)
{
case 0: // sort by name
if (m_sort_increasing)
return p1->getUserName().lower_ignore_case(p2->getUserName());
else
return p2->getUserName().lower_ignore_case(p1->getUserName());
case 1: // sort by date
{
OnlineProfile::RelationInfo *r1 = p1->getRelationInfo();
OnlineProfile::RelationInfo *r2 = p2->getRelationInfo();
// While we are comparing dates that are strings, they are normalised
// i.e. contain leading 0 etc, so a string compare works as expected.
if (m_sort_increasing)
return r1->getDate().lower_ignore_case(r2->getDate());
else
return r2->getDate().lower_ignore_case(r1->getDate());
}
case 2: // sort by online status
{
OnlineProfile::RelationInfo *r1 = p1->getRelationInfo();
OnlineProfile::RelationInfo *r2 = p2->getRelationInfo();
// In case of same online status, sort by name
if (r1->isOnline() == r2->isOnline())
{
if (m_sort_increasing)
return p1->getUserName().lower_ignore_case(p2->getUserName());
else
return p2->getUserName().lower_ignore_case(p1->getUserName());
}
else
if (m_sort_increasing)
return r1->isOnline() < r2->isOnline();
else
return r2->isOnline() < r1->isOnline();
}
default:
break;
} // switch
return false;
} // compareFriends
// ----------------------------------------------------------------------------
/** Displays the friends from a given profile.
*/
void OnlineProfileFriends::displayResults()
{
m_friends_list_widget->clear();
const OnlineProfile::IDList &friends = m_visiting_profile->getFriends();
OnlineProfile::IDList friends = m_visiting_profile->getFriends();
std::sort(friends.begin(), friends.end(), compareFriends);
for (unsigned int i = 0; i < friends.size(); i++)
{
std::vector<ListWidget::ListCell> row;
@ -150,7 +222,7 @@ void OnlineProfileFriends::displayResults()
: _("Offline") );
row.push_back(ListWidget::ListCell(status, -1, 2, true));
}
m_friends_list_widget->addItem("friend", row);
m_friends_list_widget->addItem(StringUtils::toString(friends[i]), row);
}
m_waiting_for_friends = false;

View File

@ -34,7 +34,10 @@ namespace GUIEngine { class Widget; }
/** Online profile overview screen.
* \ingroup states_screens
*/
class OnlineProfileFriends : public OnlineProfileBase, public GUIEngine::ScreenSingleton<OnlineProfileFriends>
class OnlineProfileFriends : public OnlineProfileBase,
public GUIEngine::ScreenSingleton<OnlineProfileFriends>,
public GUIEngine::IListWidgetHeaderListener
{
private:
OnlineProfileFriends();
@ -45,8 +48,14 @@ private:
GUIEngine::TextBoxWidget *m_search_box_widget;
bool m_waiting_for_friends;
/** Which column to use for sorting. */
static int m_sort_column;
/** True is sorting should be increasing. */
static bool m_sort_increasing;
void displayResults();
static bool compareFriends(int f1, int f2);
public:
friend class GUIEngine::ScreenSingleton<OnlineProfileFriends>;
@ -63,6 +72,7 @@ public:
virtual void onUpdate(float delta) OVERRIDE;
virtual void beforeAddingWidget() OVERRIDE;
virtual void onColumnClicked(int columnId);
// ------------------------------------------------------------------------
/** Triggers a reload of the friend list next time this menu is shown. */

View File

@ -219,11 +219,6 @@ void OptionsScreenVideo::init()
// for some odd reason, irrlicht sometimes fails to report the good
// old standard resolutions
// those are always useful for windowed mode
// allow 800x600 only for debug mode
#ifdef DEBUG
bool found_800_600 = false;
#endif
bool found_1024_640 = false;
bool found_1024_768 = false;
for (int n=0; n<amount; n++)
@ -238,19 +233,7 @@ void OptionsScreenVideo::init()
found_config_res = true;
}
#ifdef DEBUG
if (r.width == 800 && r.height == 600)
{
found_800_600 = true;
}
else
#endif
if (r.width == 1024 && r.height == 640)
// This becomes an 'else if' when DEBUG is defined
{
found_1024_640 = true;
}
else if (r.width == 1024 && r.height == 768)
if (r.width == 1024 && r.height == 768)
{
found_1024_768 = true;
}
@ -262,39 +245,13 @@ void OptionsScreenVideo::init()
r.height = UserConfigParams::m_height;
resolutions.push_back(r);
#ifdef DEBUG
if (r.width == 800 && r.height == 600)
{
found_800_600 = true;
}
else
#endif
if (r.width == 1024 && r.height == 640)
// This becomes an 'else if' when DEBUG is defined
{
found_1024_640 = true;
}
else if (r.width == 1024 && r.height == 768)
if (r.width == 1024 && r.height == 768)
{
found_1024_768 = true;
}
} // next found resolution
// Add default resolutions that were not found by irrlicht
#ifdef DEBUG
if (!found_800_600)
{
r.width = 800;
r.height = 600;
resolutions.push_back(r);
}
#endif
if (!found_1024_640)
{
r.width = 1024;
r.height = 640;
resolutions.push_back(r);
}
if (!found_1024_768)
{
r.width = 1024;

View File

@ -98,10 +98,6 @@ RaceGUIBase::RaceGUIBase()
m_dist_show_overlap = 2;
m_icons_inertia = 2;
//I18N: When some GlobalPlayerIcons are hidden, write "Top 10" to show it
m_string_top = _("Top %i");
m_referee = NULL;
} // RaceGUIBase
@ -812,7 +808,8 @@ void RaceGUIBase::drawGlobalPlayerIcons(int bottom_margin)
static video::SColor color = video::SColor(255, 255, 255, 255);
pos_top.LowerRightCorner = pos_top.UpperLeftCorner;
font->draw(StringUtils::insertValues( m_string_top, position-1 ), pos_top, color);
//I18N: When some GlobalPlayerIcons are hidden, write "Top 10" to show it
font->draw(_("Top %i", position-1 ), pos_top, color);
break;
}

View File

@ -129,9 +129,6 @@ private:
/** Translated strings 'ready', 'set', 'go'. */
core::stringw m_string_ready, m_string_set, m_string_go, m_string_goal;
/** Translated string 'Top %d' displayed every frame. */
core::stringw m_string_top;
/** The position of the referee for all karts. */
std::vector<Vec3> m_referee_pos;

View File

@ -1229,14 +1229,14 @@ void RaceResultGUI::addGPProgressWidget(GUIEngine::Widget* widget)
// ----------------------------------------------------------------------------
void RaceResultGUI::displayGPProgress()
{
const wchar_t* msg = _("Grand Prix progress:");
core::stringw msg = _("Grand Prix progress:");
GUIEngine::Widget* result_table = getWidget("result-table");
assert(result_table != NULL);
video::SColor color = video::SColor(255,255,0,0);
core::recti dest_rect(
result_table->m_x + result_table->m_w - m_font->getDimension(msg).Width - 5,
result_table->m_x + result_table->m_w - m_font->getDimension(msg.c_str()).Width - 5,
m_top, 0, 0);
m_font->draw(msg, dest_rect, color, false, false, NULL, true);

View File

@ -20,6 +20,7 @@
#include "config/user_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/glwrap.hpp"
#include "io/xml_node.hpp"
#include "karts/abstract_kart.hpp"
#include "modes/linear_world.hpp"
@ -77,6 +78,7 @@ CheckLine::CheckLine(const XMLNode &node, unsigned int index)
scene::IMesh *mesh = irr_driver->createQuadMesh(&material,
/*create mesh*/true);
scene::IMeshBuffer *buffer = mesh->getMeshBuffer(0);
assert(buffer->getVertexType()==video::EVT_STANDARD);
irr::video::S3DVertex* vertices
= (video::S3DVertex*)buffer->getVertices();
@ -95,11 +97,14 @@ CheckLine::CheckLine(const XMLNode &node, unsigned int index)
for(unsigned int i=0; i<4; i++)
{
vertices[i].Color = m_active_at_reset
? video::SColor(0, 255, 0, 0)
: video::SColor(0, 128, 128, 128);
? video::SColor(128, 255, 0, 0)
: video::SColor(128, 128, 128, 128);
}
buffer->recalculateBoundingBox();
mesh->setBoundingBox(buffer->getBoundingBox());
buffer->getMaterial().setTexture(0, getUnicolorTexture(video::SColor(128, 255, 105, 180)));
buffer->getMaterial().setTexture(1, getUnicolorTexture(video::SColor(0, 0, 0, 0)));
buffer->getMaterial().BackfaceCulling = false;
//mesh->setBoundingBox(buffer->getBoundingBox());
m_debug_node = irr_driver->addMesh(mesh, "checkdebug");
mesh->drop();
}
@ -137,11 +142,14 @@ void CheckLine::changeDebugColor(bool is_active)
scene::IMeshBuffer *buffer = mesh->getMeshBuffer(0);
irr::video::S3DVertex* vertices
= (video::S3DVertex*)buffer->getVertices();
video::SColor color = is_active ? video::SColor(192, 255, 0, 0)
: video::SColor(192, 128, 128, 128);
for(unsigned int i=0; i<4; i++)
{
vertices[i].Color = is_active ? video::SColor(0, 255, 0, 0)
: video::SColor(0, 128, 128, 128);
vertices[i].Color = color;
}
buffer->getMaterial().setTexture(0, getUnicolorTexture(color));
} // changeDebugColor
// ----------------------------------------------------------------------------

View File

@ -310,7 +310,7 @@ void TrackObject::onWorldReady()
fn_signature << "bool " << fn_name << "(";
for (int i = 0; i < arguments.size(); i++)
for (unsigned int i = 0; i < arguments.size(); i++)
{
if (i > 0)
fn_signature << ",";
@ -328,7 +328,7 @@ void TrackObject::onWorldReady()
script_engine->runFunction(true, fn_signature.str(),
[&](asIScriptContext* ctx)
{
for (int i = 0; i < arguments.size(); i++)
for (unsigned int i = 0; i < arguments.size(); i++)
{
ctx->SetArgObject(i, &arguments[i]);
}

View File

@ -138,7 +138,7 @@ void TrackObjectPresentationSceneNode::move(const core::vector3df& xyz,
// ----------------------------------------------------------------------------
void TrackObjectPresentationSceneNode::setEnable(bool enabled)
{
if (m_node != NULL)
if (m_node != NULL && (!enabled || !m_force_always_hidden))
m_node->setVisible(enabled);
} // setEnable
@ -440,13 +440,30 @@ void TrackObjectPresentationMesh::init(const XMLNode* xml_node,
if (interaction == "physicsonly")
{
m_node = irr_driver->addMesh(m_mesh, m_model_file, parent);
enabled = false;
m_frame_start = 0;
m_frame_end = 0;
std::string type;
xml_node->get("type", &type);
if (type == "animation" || xml_node->hasChildNamed("curve"))
{
// Animated
//m_node = irr_driver->getSceneManager()->addEmptySceneNode();
m_node = irr_driver->addMesh(m_mesh, m_model_file, parent);
enabled = false;
m_force_always_hidden = true;
m_frame_start = 0;
m_frame_end = 0;
}
else
{
// Static
m_node = irr_driver->addMesh(m_mesh, m_model_file, parent);
enabled = false;
m_force_always_hidden = true;
m_frame_start = 0;
m_frame_end = 0;
if (World::getWorld() && World::getWorld()->getTrack() && xml_node)
World::getWorld()->getTrack()->addPhysicsOnlyNode(m_node);
if (World::getWorld() && World::getWorld()->getTrack() && xml_node)
World::getWorld()->getTrack()->addPhysicsOnlyNode(m_node);
}
}
else if (m_is_in_skybox)
{

View File

@ -124,6 +124,8 @@ class TrackObjectPresentationSceneNode : public TrackObjectPresentation
protected:
/** A pointer to the scene node of this object. */
scene::ISceneNode* m_node;
bool m_force_always_hidden;
public:
/** Constructor based on data from xml. */
@ -131,6 +133,7 @@ public:
TrackObjectPresentation(xml_node)
{
m_node = NULL;
m_force_always_hidden = false;
} // TrackObjectPresentationSceneNode
// ------------------------------------------------------------------------
/** Constructor based on a transform. */

View File

@ -25,12 +25,13 @@
#include "utils/utf8.h"
#include "coreutil.h"
#include <math.h>
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <stdio.h>
#include <cwchar>
#include <exception>
#include <assert.h>
namespace StringUtils
{
@ -167,7 +168,7 @@ namespace StringUtils
try
{
std::string::size_type start=0;
while(start!=std::string::npos && start<(unsigned int)s.size())
while(start < (unsigned int) s.size())
{
std::string::size_type i=s.find(c, start);
if (i!=std::string::npos)
@ -185,11 +186,11 @@ namespace StringUtils
}
else // end of string reached
{
if (keepSplitChar)
if (keepSplitChar && start != 0)
result.push_back(std::string(s,start-1));
else
result.push_back(std::string(s,start));
start = i;
return result;
}
}
return result;
@ -243,14 +244,13 @@ namespace StringUtils
}
else
{
if (keepSplitChar)
if (keepSplitChar && start != 0)
result.push_back( s.subString(start - 1,
s.size()-start + 1) );
else
result.push_back( s.subString(start, s.size()-start) );
return result;
//start = i+1;
}
}
return result;

View File

@ -136,210 +136,71 @@ namespace StringUtils
std::string insertValues(const std::string &s,
std::vector<std::string>& all_vals);
/** This no-op is useful when using variadic arguments, so that we may
* support the case with 0 variadic arguments */
template <class T1>
T1 insertValues(const T1& s) { return s; }
// ------------------------------------------------------------------------
/** Same as above but for wide-strings */
irr::core::stringw insertValues(const irr::core::stringw &s,
std::vector<irr::core::stringw>& all_vals);
// ------------------------------------------------------------------------
// Note: the order in which the templates are specified is important, since
// otherwise some compilers will not find the right template to use.
template <class T1, class T2, class T3, class T4, class T5, class T6>
std::string insertValues(const std::string &s, const T1 &v1,
const T2 &v2, const T3 &v3, const T4 &v4,
const T5 &v5,const T6 &v6)
{
std::vector<std::string> all_vals;
std::ostringstream dummy;
dummy << v1; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v2; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v3; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v4; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v5; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v6; all_vals.push_back(dummy.str());
return insertValues(s, all_vals);
} // insertValues(s, v1, ..., v6)
// ------------------------------------------------------------------------
template <class T1, class T2, class T3, class T4, class T5>
std::string insertValues(const std::string &s, const T1 &v1,
const T2 &v2, const T3 &v3, const T4 &v4,
const T5 &v5)
{
std::vector<std::string> all_vals;
std::ostringstream dummy;
dummy << v1; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v2; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v3; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v4; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v5; all_vals.push_back(dummy.str());
return insertValues(s, all_vals);
} // insertValues(s, v1, ..., v5)
// ------------------------------------------------------------------------
template <class T1, class T2, class T3, class T4>
std::string insertValues(const std::string &s, const T1 &v1,
const T2 &v2, const T3 &v3, const T4 &v4)
{
std::vector<std::string> all_vals;
std::ostringstream dummy;
dummy << v1; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v2; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v3; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v4; all_vals.push_back(dummy.str());
return insertValues(s, all_vals);
} // insertValues(s, v1, ..., v4)
// ------------------------------------------------------------------------
/** Shortcut insert_values taking three values, see above for
* full docs.
* \param s String in which all %s or %d are replaced.
* \param v1,v2, v3 Value(s) to replace all %s or %d with.
*/
template <class T1, class T2, class T3>
std::string insertValues(const std::string &s, const T1 &v1,
const T2 &v2, const T3 &v3)
{
std::vector<std::string> all_vals;
std::ostringstream dummy;
dummy << v1; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v2; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v3; all_vals.push_back(dummy.str());
return insertValues(s, all_vals);
} // insertValues(s, v1, ..., v3)
// ------------------------------------------------------------------------
// Note: the order in which the templates are specified is important, since
// otherwise some compilers will not find the right template to use.
/** Shortcut insert_values taking three values, see above for
* full docs.
* \param s String in which all %s or %d are replaced.
* \param v1,v2 Value(s) to replace all %s or %d with.
*/
template <class T1, class T2>
std::string insertValues(const std::string &s, const T1 &v1,
const T2 &v2)
{
std::vector<std::string> all_vals;
std::ostringstream dummy;
dummy << v1; all_vals.push_back(dummy.str()); dummy.str("");
dummy << v2; all_vals.push_back(dummy.str()); dummy.str("");
return insertValues(s, all_vals);
} // insertValues(s, v1, v2)
// ------------------------------------------------------------------------
/** Shortcut insert_values taking three values, see above for
* full docs.
* \param s String in which all %s, %d are replaced.
* \param v1 Value to replace.
*/
template <class T1>
std::string insertValues(const std::string &s, const T1 &v1)
{
std::vector<std::string> all_vals;
std::ostringstream dummy;
dummy << v1; all_vals.push_back(dummy.str()); dummy.str("");
return insertValues(s, all_vals);
} // insertValues(s, v1)
// ------------------------------------------------------------------------
/** Intermediate struct to fill a vector using variadic templates */
struct __FillStringwVector
struct FillStringVector
{
/** FillS takes a vector as the first argument and a variadic list of
* arguments. The arguments are recursively inserted into the vector
* which will contain all the arguments converted to strings in the end.
*/
template<typename T, typename...Args>
static void __Fill(std::vector<irr::core::stringw> &all_vals, T&& v, Args &&...args)
static void FillS(std::vector<std::string> &all_vals, T&& v, Args &&...args)
{
std::ostringstream oss;
oss << v;
all_vals.push_back(oss.str());
FillS(all_vals, std::forward<Args>(args)...);
}
static void FillS(std::vector<std::string>&) {}
/** This functions does the same as FillS but for wide strings. */
template<typename T, typename...Args>
static void FillW(std::vector<irr::core::stringw> &all_vals, T&& v, Args &&...args)
{
all_vals.push_back(irr::core::stringw(std::forward<T>(v)));
__Fill(all_vals, std::forward<Args>(args)...);
FillW(all_vals, std::forward<Args>(args)...);
}
static void __Fill(std::vector<irr::core::stringw>&) {}
static void FillW(std::vector<irr::core::stringw>&) {}
};
template <typename...Args>
std::string insertValues(const std::string &s, Args ...args)
{
std::vector<std::string> all_vals;
all_vals.reserve(sizeof...(args));
FillStringVector::FillS(all_vals, std::forward<Args>(args)...);
return insertValues(s, all_vals);
}
template <typename...Args>
std::string insertValues(const char *s, Args ...args)
{
return insertValues(std::string(s), std::forward<Args>(args)...);
}
/** Like the other ones above but for wide strings */
template <typename...Args>
irr::core::stringw insertValues(const irr::core::stringw &s, Args ...args)
{
std::vector<irr::core::stringw> all_vals;
__FillStringwVector::__Fill(all_vals, std::forward<Args>(args)...);
all_vals.reserve(sizeof...(args));
FillStringVector::FillW(all_vals, std::forward<Args>(args)...);
return insertValues(s, all_vals);
}
// ------------------------------------------------------------------------
/** Like the other ones above but for wide strings */
template <class T1, class T2, class T3, class T4, class T5>
irr::core::stringw insertValues(const wchar_t* chars, const T1 &v1,
const T2 &v2, const T3 &v3, const T4 &v4,
const T5 &v5)
template <typename...Args>
irr::core::stringw insertValues(const wchar_t *s, Args ...args)
{
irr::core::stringw s(chars);
return insertValues(s, v1, v2, v3, v4, v5);
} // insertValues(s, v1, ..., v5)
// ------------------------------------------------------------------------
/** Like the other ones above but for wide strings */
template <class T1, class T2, class T3>
irr::core::stringw insertValues(const wchar_t* chars, const T1 &v1,
const T2 &v2, const T3 &v3)
{
irr::core::stringw s(chars);
return insertValues(s, v1, v2, v3);
} // insertValues(s, v1, ..., v3)
// ------------------------------------------------------------------------
/** Like the other ones above but for wide strings */
template <class T1, class T2>
irr::core::stringw insertValues(const wchar_t* chars, const T1 &v1,
const T2 &v2)
{
irr::core::stringw s(chars);
return insertValues(s, v1, v2);
} // insertValues(s, v1, v2)
// ------------------------------------------------------------------------
/** Like the other ones above but for wide strings */
template <class T1>
irr::core::stringw insertValues(const wchar_t* chars, const T1 &v1)
{
irr::core::stringw s(chars);
return insertValues(s, v1);
} // insertValues(s, v1)
// ------------------------------------------------------------------------
/** Like the other ones above but for C strings */
template <class T1, class T2, class T3>
std::string insertValues(const char* chars, const T1 &v1,
const T2 &v2, const T3 &v3)
{
std::string s(chars);
return insertValues(s, v1, v2, v3);
} // insertValues(s, v1, ..., v3)
// ------------------------------------------------------------------------
/** Like the other ones above but for C strings */
template <class T1, class T2>
std::string insertValues(const char* chars, const T1 &v1,
const T2 &v2)
{
std::string s(chars);
return insertValues(s, v1, v2);
} // insertValues(s, v1, v2)
// ------------------------------------------------------------------------
/** Like the other ones above but for C strings */
template <class T1>
std::string insertValues(const char* chars, const T1 &v1)
{
std::string s(chars);
return insertValues(s, v1);
} // insertValues(s, v1)
return insertValues(irr::core::stringw(s), std::forward<Args>(args)...);
}
// ------------------------------------------------------------------------
template<typename T>
@ -371,5 +232,3 @@ namespace StringUtils
} // namespace StringUtils
#endif
/* EOF */

View File

@ -26,12 +26,13 @@
#include "utils/translation.hpp"
#include <algorithm>
#include <assert.h>
#include <locale.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <cassert>
#include <cerrno>
#include <clocale>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cwchar>
#include <iostream>
#include <vector>
@ -359,10 +360,23 @@ Translations::Translations() //: m_dictionary_manager("UTF-16")
// ----------------------------------------------------------------------------
Translations::~Translations()
{
} // ~Translations
// ----------------------------------------------------------------------------
const wchar_t* Translations::fribidize(const wchar_t* in_ptr)
{
if (isRTLText(in_ptr))
{
// Test if this string was already fribidized
std::map<const irr::core::stringw, const irr::core::stringw>::const_iterator
found = m_fribidized_strings.find(in_ptr);
if (found != m_fribidized_strings.cend())
return found->second.c_str();
// Use fribidi to fribidize the string
// Split text into lines
std::vector<core::stringw> input_lines = StringUtils::split(in_ptr, '\n');
// Reverse lines for RTL strings, irrlicht will reverse them back
@ -371,18 +385,25 @@ const wchar_t* Translations::fribidize(const wchar_t* in_ptr)
std::reverse(input_lines.begin(), input_lines.end());
// Fribidize and concat lines
core::stringw converted_string;
for (std::vector<core::stringw>::iterator it = input_lines.begin();
it != input_lines.end(); it++)
{
if (it == input_lines.begin())
m_converted_string = fribidizeLine(*it);
converted_string = fribidizeLine(*it);
else
{
m_converted_string += "\n";
m_converted_string += fribidizeLine(*it);
converted_string += "\n";
converted_string += fribidizeLine(*it);
}
}
return m_converted_string.c_str();
// Save it in the map
m_fribidized_strings.insert(std::pair<const irr::core::stringw, const irr::core::stringw>(
in_ptr, converted_string));
found = m_fribidized_strings.find(in_ptr);
return found->second.c_str();
}
else
return in_ptr;
@ -448,12 +469,13 @@ const wchar_t* Translations::w_gettext(const char* original, const char* context
if (original_t == original)
{
m_converted_string = StringUtils::utf8_to_wide(original);
static irr::core::stringw converted_string;
converted_string = StringUtils::utf8_to_wide(original);
#if TRANSLATE_VERBOSE
std::wcout << L" translation : " << m_converted_string << std::endl;
std::wcout << L" translation : " << converted_string << std::endl;
#endif
return m_converted_string.c_str();
return converted_string.c_str();
}
// print
@ -572,4 +594,3 @@ core::stringw Translations::fribidizeLine(const core::stringw &str)
return core::stringw(str);
#endif // ENABLE_BIDI
}

View File

@ -20,11 +20,14 @@
#define TRANSLATION_HPP
#include <irrString.h>
#include <vector>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "utils/string_utils.hpp"
# include "tinygettext/tinygettext.hpp"
#include "tinygettext/tinygettext.hpp"
# define _(String, ...) (translations->fribidize(StringUtils::insertValues(translations->w_gettext(String), ##__VA_ARGS__)))
#undef _C
@ -46,13 +49,15 @@ private:
tinygettext::DictionaryManager m_dictionary_manager;
tinygettext::Dictionary m_dictionary;
irr::core::stringw m_converted_string;
/** A map that saves all fribidized strings: Original string, fribidized string */
std::map<const irr::core::stringw, const irr::core::stringw> m_fribidized_strings;
bool m_rtl;
std::string m_current_language_name;
public:
Translations();
~Translations();
const wchar_t *w_gettext(const wchar_t* original, const char* context=NULL);
const wchar_t *w_gettext(const char* original, const char* context=NULL);