mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-07 03:12:36 +01:00
Add GXT loading support and i18n of prints.
This commit is contained in:
parent
5b9c95d346
commit
688ee493b4
26
rwengine/include/data/GameTexts.hpp
Normal file
26
rwengine/include/data/GameTexts.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _GAMETEXTS_HPP_
|
||||||
|
#define _GAMETEXTS_HPP_
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class GameTexts
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, std::string> _textDB;
|
||||||
|
public:
|
||||||
|
|
||||||
|
void addText(const std::string& id, const std::string& text) {
|
||||||
|
_textDB.insert({ id, text });
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string text(const std::string& id) {
|
||||||
|
auto a = _textDB.find(id);
|
||||||
|
if( a != _textDB.end() ) {
|
||||||
|
return a->second;
|
||||||
|
}
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -11,6 +11,7 @@
|
|||||||
#include <loaders/WeatherLoader.hpp>
|
#include <loaders/WeatherLoader.hpp>
|
||||||
#include <objects/VehicleInfo.hpp>
|
#include <objects/VehicleInfo.hpp>
|
||||||
#include <data/CollisionModel.hpp>
|
#include <data/CollisionModel.hpp>
|
||||||
|
#include <data/GameTexts.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -106,6 +107,8 @@ public:
|
|||||||
void loadHandling(const std::string& path);
|
void loadHandling(const std::string& path);
|
||||||
|
|
||||||
SCMFile* loadSCM(const std::string& path);
|
SCMFile* loadSCM(const std::string& path);
|
||||||
|
|
||||||
|
void loadGXT(const std::string& name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads water level data
|
* Loads water level data
|
||||||
@ -280,6 +283,8 @@ public:
|
|||||||
|
|
||||||
int getWaterIndexAt(const glm::vec3& ws) const;
|
int getWaterIndexAt(const glm::vec3& ws) const;
|
||||||
float getWaveHeightAt(const glm::vec3& ws) const;
|
float getWaveHeightAt(const glm::vec3& ws) const;
|
||||||
|
|
||||||
|
GameTexts texts;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
13
rwengine/include/loaders/LoaderGXT.hpp
Normal file
13
rwengine/include/loaders/LoaderGXT.hpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef _LOADERGXT_HPP_
|
||||||
|
#define _LOADERGXT_HPP_
|
||||||
|
#include <engine/RWTypes.hpp>
|
||||||
|
#include <data/GameTexts.hpp>
|
||||||
|
|
||||||
|
class LoaderGXT
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void load( GameTexts& texts, FileHandle& file );
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -9,6 +9,8 @@
|
|||||||
#include <data/WeaponData.hpp>
|
#include <data/WeaponData.hpp>
|
||||||
#include <script/SCMFile.hpp>
|
#include <script/SCMFile.hpp>
|
||||||
|
|
||||||
|
#include <loaders/LoaderGXT.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -88,6 +90,7 @@ void GameData::load()
|
|||||||
_knownFiles.insert({"loplyguy.dff", {false, datpath+"/models/Generic/loplyguy.dff"}});
|
_knownFiles.insert({"loplyguy.dff", {false, datpath+"/models/Generic/loplyguy.dff"}});
|
||||||
_knownFiles.insert({"weapons.dff", {false, datpath+"/models/Generic/weapons.dff"}});
|
_knownFiles.insert({"weapons.dff", {false, datpath+"/models/Generic/weapons.dff"}});
|
||||||
_knownFiles.insert({"particle.txd", {false, datpath+"/models/particle.txd"}});
|
_knownFiles.insert({"particle.txd", {false, datpath+"/models/particle.txd"}});
|
||||||
|
_knownFiles.insert({"english.gxt", {false, datpath+"/TEXT/english.gxt"}});
|
||||||
|
|
||||||
loadDFF("wheels.DFF");
|
loadDFF("wheels.DFF");
|
||||||
loadDFF("weapons.dff");
|
loadDFF("weapons.dff");
|
||||||
@ -368,6 +371,15 @@ SCMFile *GameData::loadSCM(const std::string &path)
|
|||||||
return scm;
|
return scm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameData::loadGXT(const std::string &name)
|
||||||
|
{
|
||||||
|
auto d = openFile2(name);
|
||||||
|
|
||||||
|
LoaderGXT loader;
|
||||||
|
|
||||||
|
loader.load( texts, d );
|
||||||
|
}
|
||||||
|
|
||||||
void GameData::loadWaterpro(const std::string& path)
|
void GameData::loadWaterpro(const std::string& path)
|
||||||
{
|
{
|
||||||
std::ifstream ifstr(path.c_str());
|
std::ifstream ifstr(path.c_str());
|
||||||
|
48
rwengine/src/loaders/LoaderGXT.cpp
Normal file
48
rwengine/src/loaders/LoaderGXT.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include <loaders/LoaderGXT.hpp>
|
||||||
|
#include <iconv.h>
|
||||||
|
|
||||||
|
void LoaderGXT::load(GameTexts &texts, FileHandle &file)
|
||||||
|
{
|
||||||
|
auto data = file->data;
|
||||||
|
|
||||||
|
data += 4; // TKEY
|
||||||
|
|
||||||
|
std::uint32_t blocksize = *(std::uint32_t*)data;
|
||||||
|
|
||||||
|
data += 4;
|
||||||
|
|
||||||
|
auto tdata = data+blocksize+8;
|
||||||
|
|
||||||
|
// This is not supported in GCC 4.8.1
|
||||||
|
//std::wstring_convert<std::codecvt<char16_t,char,std::mbstate_t>,char16_t> convert;
|
||||||
|
|
||||||
|
auto icv = iconv_open("UTF-8", "UTF-16");
|
||||||
|
|
||||||
|
for( size_t t = 0; t < blocksize/12; ++t ) {
|
||||||
|
size_t offset = *(std::uint32_t*)(data+(t * 12 + 0));
|
||||||
|
std::string id(data+(t * 12 + 4));
|
||||||
|
|
||||||
|
// Find the terminating bytes
|
||||||
|
size_t bytes = 0;
|
||||||
|
for(;; bytes++ ) {
|
||||||
|
if(tdata[offset+bytes-1] == 0 && tdata[offset+bytes] == 0) break;
|
||||||
|
}
|
||||||
|
size_t len = bytes/2;
|
||||||
|
|
||||||
|
size_t outSize = 1024;
|
||||||
|
char u8buff[1024];
|
||||||
|
char *uwot = u8buff;
|
||||||
|
|
||||||
|
char* strbase = tdata+offset;
|
||||||
|
|
||||||
|
iconv(icv, &strbase, &bytes, &uwot, &outSize);
|
||||||
|
|
||||||
|
u8buff[len] = '\0';
|
||||||
|
|
||||||
|
std::string message(u8buff);
|
||||||
|
|
||||||
|
texts.addText(id, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
iconv_close(icv);
|
||||||
|
}
|
@ -230,7 +230,9 @@ SCMMicrocodeTable ops_game = {
|
|||||||
})
|
})
|
||||||
|
|
||||||
OPC( 0x00BC, "Print Message Now", 3, {
|
OPC( 0x00BC, "Print Message Now", 3, {
|
||||||
m->getWorld()->state.osTextString = p->at(0).string;
|
std::string str(p->at(0).string);
|
||||||
|
str = m->getWorld()->gameData.texts.text(str);
|
||||||
|
m->getWorld()->state.osTextString = str;
|
||||||
m->getWorld()->state.osTextTime = p->at(1).integer / 1000.f;
|
m->getWorld()->state.osTextTime = p->at(1).integer / 1000.f;
|
||||||
m->getWorld()->state.osTextStart= m->getWorld()->gameTime;
|
m->getWorld()->state.osTextStart= m->getWorld()->gameTime;
|
||||||
m->getWorld()->state.osTextStyle = p->at(2).integer;
|
m->getWorld()->state.osTextStyle = p->at(2).integer;
|
||||||
|
@ -212,6 +212,8 @@ void init(std::string gtapath, bool loadWorld)
|
|||||||
// Load dynamic object data
|
// Load dynamic object data
|
||||||
gta->gameData.loadDynamicObjects(gtapath + "/data/object.dat");
|
gta->gameData.loadDynamicObjects(gtapath + "/data/object.dat");
|
||||||
|
|
||||||
|
gta->gameData.loadGXT("english.gxt");
|
||||||
|
|
||||||
gta->gameTime = 0.f;
|
gta->gameTime = 0.f;
|
||||||
|
|
||||||
debugDrawer = new DebugDraw;
|
debugDrawer = new DebugDraw;
|
||||||
@ -404,7 +406,8 @@ void render(float alpha)
|
|||||||
auto sz = window.getSize();
|
auto sz = window.getSize();
|
||||||
|
|
||||||
auto b = messageText.getLocalBounds();
|
auto b = messageText.getLocalBounds();
|
||||||
messageText.setPosition(sz.x / 2.f - std::round(b.width / 2.f), sz.y / 2.f - std::round(b.height / 2.f));
|
float lowerBar = sz.y - sz.y * 0.1f;
|
||||||
|
messageText.setPosition(sz.x / 2.f - std::round(b.width / 2.f), lowerBar - std::round(b.height / 2.f));
|
||||||
window.draw(messageText);
|
window.draw(messageText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
23
tests/test_text.cpp
Normal file
23
tests/test_text.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include "test_globals.hpp"
|
||||||
|
#include <data/GameTexts.hpp>
|
||||||
|
#include <loaders/LoaderGXT.hpp>
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(TextTests)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(load_test)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto d = Global::get().e->gameData.openFile2("english.gxt");
|
||||||
|
|
||||||
|
GameTexts texts;
|
||||||
|
|
||||||
|
LoaderGXT loader;
|
||||||
|
|
||||||
|
loader.load( texts, d );
|
||||||
|
|
||||||
|
BOOST_CHECK_EQUAL( texts.text("1008"), "BUSTED" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
Loading…
Reference in New Issue
Block a user