Merged with master and solved conflicts
This commit is contained in:
commit
b7ab99e5e2
@ -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" )
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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 |
@ -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
@ -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)
|
||||
|
112
lib/irrlicht/include/utfwrapping.h
Normal file
112
lib/irrlicht/include/utfwrapping.h
Normal 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
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -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]);
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user