Start work to enable scripting
This commit is contained in:
parent
fc942433e2
commit
9f883db6f7
@ -339,7 +339,7 @@ int asCContext::Prepare(asIScriptFunction *func)
|
||||
asASSERT( m_engine );
|
||||
|
||||
// Make sure the function is from the same engine as the context to avoid mixups
|
||||
if( m_engine != func->GetEngine() )
|
||||
if (m_engine != func->GetEngine())
|
||||
{
|
||||
asCString str;
|
||||
str.Format(TXT_FAILED_IN_FUNC_s_WITH_s_d, "Prepare", func->GetDeclaration(true, true), asINVALID_ARG);
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "states_screens/dialogs/tutorial_message_dialog.hpp"
|
||||
#include "tracks/track_object_manager.hpp"
|
||||
#include "tracks/track.hpp"
|
||||
|
||||
#include "utils/profiler.hpp"
|
||||
|
||||
|
||||
using namespace Scripting;
|
||||
@ -38,8 +38,7 @@ namespace Scripting
|
||||
{
|
||||
|
||||
|
||||
//Line Callback
|
||||
void MessageCallback(const asSMessageInfo *msg, void *param)
|
||||
void AngelScript_ErrorCallback (const asSMessageInfo *msg, void *param)
|
||||
{
|
||||
const char *type = "ERR ";
|
||||
if (msg->type == asMSGTYPE_WARNING)
|
||||
@ -47,7 +46,7 @@ void MessageCallback(const asSMessageInfo *msg, void *param)
|
||||
else if (msg->type == asMSGTYPE_INFORMATION)
|
||||
type = "INFO";
|
||||
|
||||
printf("%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message);
|
||||
Log::warn("Scripting", "%s (%d, %d) : %s : %s\n", msg->section, msg->row, msg->col, type, msg->message);
|
||||
}
|
||||
|
||||
|
||||
@ -56,19 +55,19 @@ ScriptEngine::ScriptEngine()
|
||||
{
|
||||
// Create the script engine
|
||||
m_engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
|
||||
if( m_engine == 0 )
|
||||
if (m_engine == NULL)
|
||||
{
|
||||
std::cout << "Failed to create script engine." << std::endl;
|
||||
Log::error("Scripting", "Failed to create script engine.");
|
||||
}
|
||||
|
||||
// The script compiler will write any compiler messages to the callback.
|
||||
//m_engine->SetMessageCallback(asFUNCTION(MessageCallback), 0, asCALL_CDECL);
|
||||
m_engine->SetMessageCallback(asFUNCTION(AngelScript_ErrorCallback), 0, asCALL_CDECL);
|
||||
|
||||
// Configure the script engine with all the functions,
|
||||
// and variables that the script should be able to use.
|
||||
configureEngine(m_engine);
|
||||
|
||||
}
|
||||
|
||||
ScriptEngine::~ScriptEngine()
|
||||
{
|
||||
// Release the engine
|
||||
@ -85,12 +84,15 @@ std::string getScript(std::string scriptName)
|
||||
{
|
||||
std::string script_dir = file_manager->getAsset(FileManager::SCRIPT, "");
|
||||
script_dir += World::getWorld()->getTrack()->getIdent() + "/";
|
||||
if (scriptName != "update" && scriptName != "collisions" && scriptName!="start") scriptName = "triggers";
|
||||
if (scriptName != "update" && scriptName != "collisions" && scriptName != "start")
|
||||
scriptName = "triggers";
|
||||
|
||||
script_dir += scriptName + ".as";
|
||||
FILE *f = fopen(script_dir.c_str(), "rb");
|
||||
if( f == 0 )
|
||||
if (f == NULL)
|
||||
{
|
||||
std::cout << "Failed to open the script file " + scriptName + ".as" << std::endl;
|
||||
Log::debug("Scripting", "File does not exist : {0}.as", scriptName.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
// Determine the size of the file
|
||||
@ -103,25 +105,27 @@ std::string getScript(std::string scriptName)
|
||||
script.resize(len);
|
||||
int c = fread(&script[0], len, 1, f);
|
||||
fclose(f);
|
||||
if( c == 0 )
|
||||
if (c == NULL)
|
||||
{
|
||||
std::cout << "Failed to load script file." << std::endl;
|
||||
Log::error("Scripting", "Failed to load script file.");
|
||||
return "";
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** runs the specified script
|
||||
* \param string scriptName = name of script to run
|
||||
*/
|
||||
void ScriptEngine::runScript(std::string scriptName)
|
||||
{
|
||||
return; // Scripting disabled for now
|
||||
PROFILER_PUSH_CPU_MARKER("RunScript", 255, 0, 0);
|
||||
|
||||
// Create a context that will execute the script.
|
||||
asIScriptContext *ctx = m_engine->CreateContext();
|
||||
if (ctx == 0)
|
||||
if (ctx == NULL)
|
||||
{
|
||||
std::cout << "Failed to create the context." << std::endl;
|
||||
Log::error("Scripting", "Failed to create the context.");
|
||||
//m_engine->Release();
|
||||
return;
|
||||
}
|
||||
@ -132,16 +136,12 @@ void ScriptEngine::runScript(std::string scriptName)
|
||||
if (m_script_cache.find(scriptName) == m_script_cache.end())
|
||||
{
|
||||
// Compile the script code
|
||||
Log::debug("Scripting", "Compiling script '%s' (was not in cache)", scriptName.c_str());
|
||||
r = compileScript(m_engine, scriptName);
|
||||
if (r < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//set line callback here soon
|
||||
if (r < 0)
|
||||
{
|
||||
std::cout << "Failed to set the line callback function." << std::endl;
|
||||
Log::debug("Scripting", "Script '%s' is not available", scriptName.c_str());
|
||||
m_script_cache[scriptName] = NULL; // remember that this script is unavaiable
|
||||
ctx->Release();
|
||||
return;
|
||||
}
|
||||
@ -166,32 +166,40 @@ void ScriptEngine::runScript(std::string scriptName)
|
||||
//trigger type can have different names
|
||||
func = Scripting::Track::registerScriptCallbacks(m_engine, scriptName);
|
||||
}
|
||||
if (func == 0)
|
||||
|
||||
if (func == NULL)
|
||||
{
|
||||
std::cout << "The required function was not found." << std::endl;
|
||||
Log::warn("Scripting", "The required function was not found : %s", scriptName.c_str());
|
||||
ctx->Release();
|
||||
//m_engine->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
//CACHE UPDATE
|
||||
m_script_cache[scriptName] = func;
|
||||
func->AddRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Script present in cache
|
||||
// TODO: clear when done
|
||||
func = m_script_cache[scriptName];
|
||||
std::cout << "FOUND CACHED : " << scriptName << std::endl;
|
||||
}
|
||||
|
||||
if (func == NULL)
|
||||
{
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
return; // script unavailable
|
||||
}
|
||||
|
||||
// Prepare the script context with the function we wish to execute. Prepare()
|
||||
// must be called on the context before each new script function that will be
|
||||
// executed. Note, that if because we intend to execute the same function
|
||||
// several times, we will store the function returned by
|
||||
// GetFunctionByDecl(), so that this relatively slow call can be skipped.
|
||||
r = ctx->Prepare(func);
|
||||
if( r < 0 )
|
||||
if (r < 0)
|
||||
{
|
||||
std::cout << "Failed to prepare the context." << std::endl;
|
||||
Log::error("Scripting", "Failed to prepare the context.");
|
||||
ctx->Release();
|
||||
//m_engine->Release();
|
||||
return;
|
||||
@ -204,25 +212,29 @@ void ScriptEngine::runScript(std::string scriptName)
|
||||
|
||||
// Execute the function
|
||||
r = ctx->Execute();
|
||||
if( r != asEXECUTION_FINISHED )
|
||||
if (r != asEXECUTION_FINISHED)
|
||||
{
|
||||
// The execution didn't finish as we had planned. Determine why.
|
||||
if( r == asEXECUTION_ABORTED )
|
||||
std::cout << "The script was aborted before it could finish. Probably it timed out." << std::endl;
|
||||
else if( r == asEXECUTION_EXCEPTION )
|
||||
if (r == asEXECUTION_ABORTED)
|
||||
{
|
||||
std::cout << "The script ended with an exception." << std::endl;
|
||||
Log::error("Scripting", "The script was aborted before it could finish. Probably it timed out.");
|
||||
}
|
||||
else if (r == asEXECUTION_EXCEPTION)
|
||||
{
|
||||
Log::error("Scripting", "The script ended with an exception.");
|
||||
|
||||
// Write some information about the script exception
|
||||
asIScriptFunction *func = ctx->GetExceptionFunction();
|
||||
std::cout << "func: " << func->GetDeclaration() << std::endl;
|
||||
std::cout << "modl: " << func->GetModuleName() << std::endl;
|
||||
std::cout << "sect: " << func->GetScriptSectionName() << std::endl;
|
||||
std::cout << "line: " << ctx->GetExceptionLineNumber() << std::endl;
|
||||
std::cout << "desc: " << ctx->GetExceptionString() << std::endl;
|
||||
//std::cout << "func: " << func->GetDeclaration() << std::endl;
|
||||
//std::cout << "modl: " << func->GetModuleName() << std::endl;
|
||||
//std::cout << "sect: " << func->GetScriptSectionName() << std::endl;
|
||||
//std::cout << "line: " << ctx->GetExceptionLineNumber() << std::endl;
|
||||
//std::cout << "desc: " << ctx->GetExceptionString() << std::endl;
|
||||
}
|
||||
else
|
||||
std::cout << "The script ended for some unforeseen reason (" << r << ")." << std::endl;
|
||||
{
|
||||
Log::error("Scripting", "The script ended for some unforeseen reason (%i)", r);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -234,8 +246,19 @@ void ScriptEngine::runScript(std::string scriptName)
|
||||
// We must release the contexts when no longer using them
|
||||
ctx->Release();
|
||||
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ScriptEngine::cleanupCache()
|
||||
{
|
||||
for (auto curr : m_script_cache)
|
||||
{
|
||||
curr.second->Release();
|
||||
}
|
||||
m_script_cache.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Configures the script engine by binding functions, enums
|
||||
@ -245,6 +268,7 @@ void ScriptEngine::configureEngine(asIScriptEngine *engine)
|
||||
{
|
||||
// Register the script string type
|
||||
RegisterStdString(engine); //register std::string
|
||||
RegisterStdStringUtils(engine);
|
||||
RegisterVec3(engine); //register Vec3
|
||||
|
||||
Scripting::Track::registerScriptFunctions(m_engine);
|
||||
@ -266,13 +290,17 @@ void ScriptEngine::configureEngine(asIScriptEngine *engine)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
int ScriptEngine::compileScript(asIScriptEngine *engine, std::string scriptName)
|
||||
{
|
||||
int r;
|
||||
|
||||
std::string script = getScript(scriptName);
|
||||
if (script.size() == 0)
|
||||
{
|
||||
// No such file
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Add the script sections that will be compiled into executable code.
|
||||
// If we want to combine more than one file into the same script, then
|
||||
// we can call AddScriptSection() several times for the same module and
|
||||
@ -280,9 +308,9 @@ int ScriptEngine::compileScript(asIScriptEngine *engine, std::string scriptName)
|
||||
// section name, will allow us to localize any errors in the script code.
|
||||
asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
|
||||
r = mod->AddScriptSection("script", &script[0], script.size());
|
||||
if( r < 0 )
|
||||
if (r < 0)
|
||||
{
|
||||
std::cout << "AddScriptSection() failed" << std::endl;
|
||||
Log::error("Scripting", "AddScriptSection() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -291,9 +319,9 @@ int ScriptEngine::compileScript(asIScriptEngine *engine, std::string scriptName)
|
||||
// script engine. If there are no errors, and no warnings, nothing will
|
||||
// be written to the stream.
|
||||
r = mod->Build();
|
||||
if( r < 0 )
|
||||
if (r < 0)
|
||||
{
|
||||
std::cout << "Build() failed" << std::endl;
|
||||
Log::error("Scripting", "Build() failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -65,6 +65,7 @@ namespace Scripting
|
||||
~ScriptEngine();
|
||||
|
||||
void runScript(std::string scriptName);
|
||||
void cleanupCache();
|
||||
|
||||
private:
|
||||
asIScriptEngine *m_engine;
|
||||
|
@ -156,7 +156,7 @@ namespace Scripting
|
||||
void displayMessage(asIScriptGeneric *gen)
|
||||
{
|
||||
std::string *input = (std::string*)gen->GetArgAddress(0);
|
||||
irr::core::stringw out = irr::core::stringw((*input).c_str()); //irr::core::stringw supported by message dialogs
|
||||
irr::core::stringw out = StringUtils::utf8_to_wide(input->c_str());
|
||||
new TutorialMessageDialog((out), true);
|
||||
}
|
||||
//generic disable method for track objects
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "scriptarray.hpp"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "utils/translation.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -125,22 +126,110 @@ static void StringJoin_Generic(asIScriptGeneric *gen)
|
||||
new(gen->GetAddressOfReturnLocation()) string(StringJoin(*array, *delim));
|
||||
}
|
||||
|
||||
void translate(asIScriptGeneric *gen)
|
||||
{
|
||||
// Get the arguments
|
||||
std::string *input = (std::string*)gen->GetArgAddress(0);
|
||||
|
||||
irr::core::stringw out = translations->fribidize(translations->w_gettext(input->c_str()));
|
||||
|
||||
// Return the string
|
||||
new(gen->GetAddressOfReturnLocation()) string(StringUtils::wide_to_utf8(out.c_str()));
|
||||
}
|
||||
|
||||
void insertValues1(asIScriptGeneric *gen)
|
||||
{
|
||||
// Get the arguments
|
||||
std::string *input = (std::string*)gen->GetArgAddress(0);
|
||||
std::string *arg1 = (std::string*)gen->GetArgAddress(1);
|
||||
|
||||
irr::core::stringw out = StringUtils::insertValues(StringUtils::utf8_to_wide(input->c_str()),
|
||||
StringUtils::utf8_to_wide(arg1->c_str()));
|
||||
|
||||
// Return the string
|
||||
new(gen->GetAddressOfReturnLocation()) string(StringUtils::wide_to_utf8(out.c_str()));
|
||||
}
|
||||
|
||||
void insertValues2(asIScriptGeneric *gen)
|
||||
{
|
||||
// Get the arguments
|
||||
std::string *input = (std::string*)gen->GetArgAddress(0);
|
||||
std::string *arg1 = (std::string*)gen->GetArgAddress(1);
|
||||
std::string *arg2 = (std::string*)gen->GetArgAddress(2);
|
||||
|
||||
irr::core::stringw out = StringUtils::insertValues(StringUtils::utf8_to_wide(input->c_str()),
|
||||
StringUtils::utf8_to_wide(arg1->c_str()),
|
||||
StringUtils::utf8_to_wide(arg2->c_str()));
|
||||
|
||||
// Return the string
|
||||
new(gen->GetAddressOfReturnLocation()) string(StringUtils::wide_to_utf8(out.c_str()));
|
||||
}
|
||||
|
||||
void insertValues3(asIScriptGeneric *gen)
|
||||
{
|
||||
// Get the arguments
|
||||
std::string *input = (std::string*)gen->GetArgAddress(0);
|
||||
std::string *arg1 = (std::string*)gen->GetArgAddress(1);
|
||||
std::string *arg2 = (std::string*)gen->GetArgAddress(2);
|
||||
std::string *arg3 = (std::string*)gen->GetArgAddress(3);
|
||||
|
||||
irr::core::stringw out = StringUtils::insertValues(StringUtils::utf8_to_wide(input->c_str()),
|
||||
StringUtils::utf8_to_wide(arg1->c_str()),
|
||||
StringUtils::utf8_to_wide(arg2->c_str()),
|
||||
StringUtils::utf8_to_wide(arg3->c_str()));
|
||||
|
||||
// Return the string
|
||||
new(gen->GetAddressOfReturnLocation()) string(StringUtils::wide_to_utf8(out.c_str()));
|
||||
}
|
||||
|
||||
/*
|
||||
void insertValues(asIScriptGeneric *gen)
|
||||
{
|
||||
// Get the arguments
|
||||
std::string *input = (std::string*)gen->GetArgAddress(0);
|
||||
CScriptArray *array = *(CScriptArray**)gen->GetAddressOfArg(1);
|
||||
|
||||
int size = array->GetSize();
|
||||
vector<string> all_values;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
string* curr = (string*)array->At(i);
|
||||
all_values.push_back(curr);
|
||||
}
|
||||
|
||||
StringUtils::insertValues(*input, all_values);
|
||||
|
||||
irr::core::stringw out = translations->fribidize(translations->w_gettext(input->c_str()));
|
||||
|
||||
// Return the string
|
||||
new(gen->GetAddressOfReturnLocation()) string(irr::core::stringc(out).c_str());
|
||||
}
|
||||
*/
|
||||
|
||||
// This is where the utility functions are registered.
|
||||
// The string type must have been registered first.
|
||||
void RegisterStdStringUtils(asIScriptEngine *engine)
|
||||
{
|
||||
int r;
|
||||
|
||||
if( strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
|
||||
{
|
||||
r = engine->RegisterObjectMethod("string", "array<string>@ split(const string &in) const", asFUNCTION(StringSplit_Generic), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("string join(const array<string> &in, const string &in)", asFUNCTION(StringJoin_Generic), asCALL_GENERIC); assert(r >= 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
r = engine->RegisterObjectMethod("string", "array<string>@ split(const string &in) const", asFUNCTION(StringSplit), asCALL_CDECL_OBJLAST); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("string join(const array<string> &in, const string &in)", asFUNCTION(StringJoin), asCALL_CDECL); assert(r >= 0);
|
||||
}
|
||||
//if (strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY"))
|
||||
//{
|
||||
//r = engine->RegisterObjectMethod("string", "array<string>@ split(const string &in) const", asFUNCTION(StringSplit_Generic), asCALL_GENERIC); assert(r >= 0);
|
||||
//r = engine->RegisterGlobalFunction("string join(const array<string> &in, const string &in)", asFUNCTION(StringJoin_Generic), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("string translate(const string &in)", asFUNCTION(translate), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("string insertValues(const string &in, const string &in)", asFUNCTION(insertValues1), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("string insertValues(const string &in, const string &in, const string &in)", asFUNCTION(insertValues2), asCALL_GENERIC); assert(r >= 0);
|
||||
r = engine->RegisterGlobalFunction("string insertValues(const string &in, const string &in, const string &in, const string &in)", asFUNCTION(insertValues3), asCALL_GENERIC); assert(r >= 0);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// //r = engine->RegisterObjectMethod("string", "array<string>@ split(const string &in) const", asFUNCTION(StringSplit), asCALL_CDECL_OBJLAST); assert(r >= 0);
|
||||
// //r = engine->RegisterGlobalFunction("string join(const array<string> &in, const string &in)", asFUNCTION(StringJoin), asCALL_CDECL); assert(r >= 0);
|
||||
// r = engine->RegisterGlobalFunction("string translate(const string &in)", asFUNCTION(translate), asCALL_CDECL); assert(r >= 0);
|
||||
// r = engine->RegisterGlobalFunction("string insertValues(const string &in, const string &arg1)", asFUNCTION(insertValues1), asCALL_CDECL); assert(r >= 0);
|
||||
// r = engine->RegisterGlobalFunction("string insertValues(const string &in, const string &arg1, const string &arg2)", asFUNCTION(insertValues2), asCALL_CDECL); assert(r >= 0);
|
||||
// r = engine->RegisterGlobalFunction("string insertValues(const string &in, const string &arg1, const string &arg2, const string &arg3)", asFUNCTION(insertValues3), asCALL_CDECL); assert(r >= 0);
|
||||
//}
|
||||
}
|
||||
|
||||
END_AS_NAMESPACE
|
||||
|
@ -448,6 +448,10 @@ void Track::cleanup()
|
||||
Log::info("CACHE", "[%i] %s", i, path.getPath().c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
Scripting::ScriptEngine* script_engine =
|
||||
World::getWorld()->getScriptEngine();
|
||||
script_engine->cleanupCache();
|
||||
} // cleanup
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -921,6 +921,7 @@ void TrackObjectPresentationActionTrigger::onTriggerItemApproached(Item* who)
|
||||
_("Complete all challenges to unlock the big door!"), true);
|
||||
}
|
||||
}
|
||||
/*
|
||||
else if (m_action == "tutorial_drive")
|
||||
{
|
||||
//if (World::getWorld()->getPhase() == World::RACE_PHASE)
|
||||
@ -1036,19 +1037,19 @@ void TrackObjectPresentationActionTrigger::onTriggerItemApproached(Item* who)
|
||||
|
||||
new TutorialMessageDialog(_("You are now ready to race. Good luck!"),
|
||||
true);
|
||||
}
|
||||
}*/
|
||||
else if (m_action == "tutorial_exit")
|
||||
{
|
||||
// TODO: move to scripting
|
||||
World::getWorld()->scheduleExitRace();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO move all above functions into scripts and remove the ifs
|
||||
Scripting::ScriptEngine* m_script_engine =
|
||||
Scripting::ScriptEngine* script_engine =
|
||||
World::getWorld()->getScriptEngine();
|
||||
m_action_active = false;
|
||||
m_script_engine->runScript(m_action);
|
||||
script_engine->runScript(m_action);
|
||||
|
||||
/*
|
||||
Catch exception -> script not found
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
#include "utils/utf8.h"
|
||||
#include "coreutil.h"
|
||||
|
||||
#include <math.h>
|
||||
@ -684,6 +684,32 @@ namespace StringUtils
|
||||
return output.str();
|
||||
} // xmlEncode
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
std::string wide_to_utf8(const wchar_t* input)
|
||||
{
|
||||
static std::vector<char> utf8line;
|
||||
utf8line.clear();
|
||||
|
||||
utf8::utf16to8(input, input + wcslen(input), back_inserter(utf8line));
|
||||
utf8line.push_back(0);
|
||||
|
||||
return std::string(&utf8line[0]);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
irr::core::stringw utf8_to_wide(const char* input)
|
||||
{
|
||||
static std::vector<wchar_t> utf16line;
|
||||
utf16line.clear();
|
||||
|
||||
utf8::utf8to16(input, input + strlen(input), back_inserter(utf16line));
|
||||
utf16line.push_back(0);
|
||||
|
||||
return irr::core::stringw(&utf16line[0]);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
/** Converts a version string (in the form of 'X.Y.Za-rcU' into an
|
||||
* integer number.
|
||||
|
@ -259,7 +259,7 @@ namespace StringUtils
|
||||
all_vals.push_back(irr::core::stringw(std::forward<T>(v)));
|
||||
__Fill(all_vals, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
static void __Fill(std::vector<irr::core::stringw>&) {}
|
||||
};
|
||||
|
||||
@ -363,6 +363,11 @@ namespace StringUtils
|
||||
return parseString(input.c_str(), output);
|
||||
} // parseString
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
std::string wide_to_utf8(const wchar_t* input);
|
||||
irr::core::stringw utf8_to_wide(const char* input);
|
||||
|
||||
} // namespace StringUtils
|
||||
|
||||
#endif
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include "io/file_manager.hpp"
|
||||
#include "utils/constants.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/utf8.h"
|
||||
|
||||
|
||||
// set to 1 to debug i18n
|
||||
@ -71,29 +70,6 @@ const LanguageList* Translations::getLanguageList() const
|
||||
return &g_language_list;
|
||||
}
|
||||
|
||||
|
||||
char* wide_to_utf8(const wchar_t* input)
|
||||
{
|
||||
static std::vector<char> utf8line;
|
||||
utf8line.clear();
|
||||
|
||||
utf8::utf16to8(input, input + wcslen(input), back_inserter(utf8line));
|
||||
utf8line.push_back(0);
|
||||
|
||||
return &utf8line[0];
|
||||
}
|
||||
|
||||
wchar_t* utf8_to_wide(const char* input)
|
||||
{
|
||||
static std::vector<wchar_t> utf16line;
|
||||
utf16line.clear();
|
||||
|
||||
utf8::utf8to16(input, input + strlen(input), back_inserter(utf16line));
|
||||
utf16line.push_back(0);
|
||||
|
||||
return &utf16line[0];
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Frees the memory allocated for the result of toFribidiChar(). */
|
||||
void freeFribidiChar(FriBidiChar *str)
|
||||
@ -439,7 +415,8 @@ bool Translations::isRTLText(const wchar_t *in_ptr)
|
||||
*/
|
||||
const wchar_t* Translations::w_gettext(const wchar_t* original, const char* context)
|
||||
{
|
||||
return w_gettext( wide_to_utf8(original), context );
|
||||
std::string in = StringUtils::wide_to_utf8(original);
|
||||
return w_gettext(in.c_str(), context);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -461,7 +438,7 @@ const wchar_t* Translations::w_gettext(const char* original, const char* context
|
||||
|
||||
if (original_t == original)
|
||||
{
|
||||
m_converted_string = utf8_to_wide(original);
|
||||
m_converted_string = StringUtils::utf8_to_wide(original);
|
||||
|
||||
#if TRANSLATE_VERBOSE
|
||||
std::wcout << L" translation : " << m_converted_string << std::endl;
|
||||
@ -472,9 +449,10 @@ const wchar_t* Translations::w_gettext(const char* original, const char* context
|
||||
// print
|
||||
//for (int n=0;; n+=4)
|
||||
|
||||
wchar_t* original_tw = utf8_to_wide(original_t.c_str());
|
||||
static core::stringw original_tw;
|
||||
original_tw = StringUtils::utf8_to_wide(original_t.c_str());
|
||||
|
||||
wchar_t* out_ptr = original_tw;
|
||||
const wchar_t* out_ptr = original_tw.c_str();
|
||||
if (REMOVE_BOM) out_ptr++;
|
||||
|
||||
#if TRANSLATE_VERBOSE
|
||||
@ -493,7 +471,9 @@ const wchar_t* Translations::w_gettext(const char* original, const char* context
|
||||
*/
|
||||
const wchar_t* Translations::w_ngettext(const wchar_t* singular, const wchar_t* plural, int num, const char* context)
|
||||
{
|
||||
return w_ngettext( wide_to_utf8(singular), wide_to_utf8(plural), num, context);
|
||||
std::string in = StringUtils::wide_to_utf8(singular);
|
||||
std::string in2 = StringUtils::wide_to_utf8(plural);
|
||||
return w_ngettext(in.c_str(), in2.c_str(), num, context);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -509,7 +489,9 @@ const wchar_t* Translations::w_ngettext(const char* singular, const char* plural
|
||||
m_dictionary.translate_plural(singular, plural, num) :
|
||||
m_dictionary.translate_ctxt_plural(context, singular, plural, num));
|
||||
|
||||
wchar_t* out_ptr = utf8_to_wide(res.c_str());
|
||||
static core::stringw str_buffer;
|
||||
str_buffer = StringUtils::utf8_to_wide(res.c_str());
|
||||
const wchar_t* out_ptr = str_buffer.c_str();
|
||||
if (REMOVE_BOM) out_ptr++;
|
||||
|
||||
#if TRANSLATE_VERBOSE
|
||||
|
Loading…
x
Reference in New Issue
Block a user