1
0
forked from 0ad/0ad

Improve UTF-8 character handling in Atlas

(Also prevents the compile-time warnings reported in the abandoned
D1432)

Accepted by: Itms
Patch linting by: Stan, Vladislav, wraitii
Also tested by: Imarok
Fixes: #4936
Differential Revision: https://code.wildfiregames.com/D1395
This was SVN commit r22335.
This commit is contained in:
s0600204 2019-06-03 20:19:53 +00:00
parent 4b65cc0317
commit 800bf0da24
21 changed files with 173 additions and 311 deletions

View File

@ -1,8 +1,8 @@
{
"settings" : {
"Name" : "Fields of Meroe",
"Name" : "Fields of Meroë",
"Script" : "fields_of_meroe.js",
"Description" : "The \"Island of Meroe\", a vast peninsula flanked by the Nile and Atbarah rivers, formed the heartland of ancient Kush. Where the harsh deserts start making way for the semi-arid savannahs and small acacia forests dot the landscape. The area is rich in resources and the ever-present Nile brings life, but grave threats loom on the opposite riverbank.",
"Description" : "The \"Island of Meroë\", a vast peninsula flanked by the Nile and Atbarah rivers, formed the heartland of ancient Kush. Where the harsh deserts start making way for the semi-arid savannahs and small acacia forests dot the landscape. The area is rich in resources and the ever-present Nile brings life, but grave threats loom on the opposite riverbank.",
"Preview" : "fields_of_meroe_dry.png",
"Keywords": [],
"CircularMap" : true,

View File

@ -1100,8 +1100,7 @@ function setup_atlas_projects()
},{ -- extern_libs
"boost",
"iconv",
"libxml2",
"wxwidgets"
"libxml2"
},{ -- extra_params
no_pch = 1
})
@ -1346,7 +1345,6 @@ function setup_tests()
links { "mocks_test" }
if _OPTIONS["atlas"] then
links { "AtlasObject" }
project_add_extern_libs({"wxwidgets"}, target_type)
end
extra_params = {
extra_files = { "test_setup.cpp" },

View File

@ -28,7 +28,6 @@
# define _CRT_SECURE_NO_WARNINGS // Disable deprecation warning in VS2008
#endif
#include <wchar.h> // for wchar_t
#include <string>
class wxString;
@ -119,7 +118,7 @@ public:
const AtObj operator* () const;
// Return the string value of the AtObj currently pointed to by this iterator
operator const wchar_t* () const;
operator const char* () const;
// Private implementation. (But not 'private:', because it's a waste of time
// adding loads of friend functions)
@ -137,13 +136,14 @@ public:
const AtIter operator[] (const char* key) const;
// Return the string value of this object
operator const wchar_t* () const;
operator const char* () const;
// Return the floating point value of this object
double getDouble() const;
// Return the integer value of this object
int getInt() const;
long getLong() const;
// Check whether the object contains anything (even if those things are empty)
bool defined() const { return static_cast<bool>(m_Node); }
@ -151,22 +151,20 @@ public:
// Check recursively whether there's actually any non-empty data in the object
bool hasContent() const;
// Add or set a child. The wchar_t* and wxString& versions create a new
// AtObj with the appropriate string value, then use that as the child.
// Add or set a child. The char* version creates a new AtObj with
// the appropriate string value, then uses that as the child.
//
// These alter the AtObj's internal pointer, and the pointed-to data is
// never actually altered. Copies of this AtObj (including copies stored
// inside other AtObjs) will not be affected.
void add(const char* key, const wchar_t* value);
void add(const char* key, const wxString& value);
void add(const char* key, const char* value);
void add(const char* key, AtObj& data);
void set(const char* key, const wchar_t* value);
void set(const char* key, const wxString& value);
void set(const char* key, const char* value);
void set(const char* key, AtObj& data);
void setBool(const char* key, bool value);
void setDouble(const char* key, double value);
void setInt(const char* key, int value);
void setString(const wchar_t* value);
void setString(const char* value);
void addOverlay(AtObj& data);
AtSmartPtr<const AtNode> m_Node;

View File

@ -21,8 +21,6 @@
#include <assert.h>
#include <sstream>
#include <wx/string.h>
#define ATSMARTPTR_IMPL(T) \
template<> void AtSmartPtr<T>::inc_ref() \
{ \
@ -53,12 +51,9 @@ const AtIter AtIter::operator [] (const char* key) const
return AtIter();
}
AtIter::operator const wchar_t* () const
AtIter::operator const char* () const
{
if (m_Impl)
return m_Impl->iter->second->m_Value.c_str();
else
return L"";
return m_Impl ? m_Impl->iter->second->m_Value.c_str() : "";
}
//AtIter::operator const AtObj () const
@ -122,23 +117,16 @@ const AtIter AtObj::operator [] (const char* key) const
return AtIter();
}
AtObj::operator const wchar_t* () const
AtObj::operator const char* () const
{
if (m_Node)
return m_Node->m_Value.c_str();
else
return L"";
return m_Node ? m_Node->m_Value.c_str() : "";
}
double AtObj::getDouble() const
{
double val = 0;
if (m_Node)
{
std::wstringstream s;
s << m_Node->m_Value;
s >> val;
}
static_cast<std::stringstream>(m_Node->m_Value) >> val;
return val;
}
@ -146,11 +134,15 @@ int AtObj::getInt() const
{
int val = 0;
if (m_Node)
{
std::wstringstream s;
s << m_Node->m_Value;
s >> val;
static_cast<std::stringstream>(m_Node->m_Value) >> val;
return val;
}
long AtObj::getLong() const
{
long val = 0;
if (m_Node)
static_cast<std::stringstream>(m_Node->m_Value) >> val;
return val;
}
@ -162,12 +154,7 @@ void AtObj::add(const char* key, AtObj& data)
m_Node = m_Node->addChild(key, data.m_Node);
}
void AtObj::add(const char* key, const wxString& value)
{
add(key, value.wc_str());
}
void AtObj::add(const char* key, const wchar_t* value)
void AtObj::add(const char* key, const char* value)
{
const AtNode* o = new AtNode(value);
@ -185,12 +172,7 @@ void AtObj::set(const char* key, AtObj& data)
m_Node = m_Node->setChild(key, data.m_Node);
}
void AtObj::set(const char* key, const wxString& value)
{
set(key, value.wc_str());
}
void AtObj::set(const char* key, const wchar_t* value)
void AtObj::set(const char* key, const char* value)
{
const AtNode* o = new AtNode(value);
@ -202,7 +184,7 @@ void AtObj::set(const char* key, const wchar_t* value)
void AtObj::setBool(const char* key, bool value)
{
AtNode* o = new AtNode(value ? L"true" : L"false");
AtNode* o = new AtNode(value ? "true" : "false");
o->m_Children.insert(AtNode::child_pairtype("@boolean", AtNode::Ptr(new AtNode())));
if (!m_Node)
@ -213,7 +195,7 @@ void AtObj::setBool(const char* key, bool value)
void AtObj::setDouble(const char* key, double value)
{
std::wstringstream str;
std::stringstream str;
str << value;
AtNode* o = new AtNode(str.str().c_str());
o->m_Children.insert(AtNode::child_pairtype("@number", AtNode::Ptr(new AtNode())));
@ -226,7 +208,7 @@ void AtObj::setDouble(const char* key, double value)
void AtObj::setInt(const char* key, int value)
{
std::wstringstream str;
std::stringstream str;
str << value;
AtNode* o = new AtNode(str.str().c_str());
o->m_Children.insert(AtNode::child_pairtype("@number", AtNode::Ptr(new AtNode())));
@ -237,7 +219,7 @@ void AtObj::setInt(const char* key, int value)
m_Node = m_Node->setChild(key, AtNode::Ptr(o));
}
void AtObj::setString(const wchar_t* value)
void AtObj::setString(const char* value)
{
if (!m_Node)
m_Node = new AtNode();
@ -289,7 +271,7 @@ bool AtNode::hasContent() const
return false;
}
const AtNode::Ptr AtNode::setValue(const wchar_t* value) const
const AtNode::Ptr AtNode::setValue(const char* value) const
{
AtNode* newNode = new AtNode();
newNode->m_Children = m_Children;

View File

@ -41,11 +41,11 @@ public:
AtNode() : m_Refcount(0) {}
explicit AtNode(const AtNode* n) { *this = *n; m_Refcount = 0; }
explicit AtNode(const wchar_t* text) : m_Refcount(0), m_Value(text) {}
explicit AtNode(const char* text) : m_Refcount(0), m_Value(text) {}
// Create a new AtNode (since AtNodes are immutable, so it's not possible
// to just change this one), with the relevant alterations to its content.
const AtNode::Ptr setValue(const wchar_t* value) const;
const AtNode::Ptr setValue(const char* value) const;
const AtNode::Ptr addChild(const char* key, const AtNode::Ptr &data) const;
const AtNode::Ptr setChild(const char* key, const AtNode::Ptr &data) const;
const AtNode::Ptr addOverlay(const AtNode::Ptr &data) const;
@ -57,7 +57,7 @@ public:
//private: // (but not actually private, since I'm still too lazy to waste
// time with dozens of friends)
std::wstring m_Value;
std::string m_Value;
typedef std::multimap<std::string, AtNode::Ptr> child_maptype;
typedef std::pair<std::string, AtNode::Ptr> child_pairtype;

View File

@ -24,8 +24,6 @@
# pragma warning(disable:4996) // deprecated CRT
#endif
#include "wx/log.h"
#include <sstream>
static AtSmartPtr<AtNode> ConvertNode(json_spirit::Value node);
@ -47,11 +45,11 @@ static AtSmartPtr<AtNode> ConvertNode(json_spirit::Value node)
if (node.type() == json_spirit::str_type)
{
obj->m_Value = std::wstring(node.get_str().begin(),node.get_str().end());
obj->m_Value = node.get_str();
}
else if (node.type() == json_spirit::int_type || node.type() == json_spirit::real_type)
{
std::wstringstream stream;
std::stringstream stream;
if (node.type() == json_spirit::int_type)
stream << node.get_int();
if (node.type() == json_spirit::real_type)
@ -64,10 +62,7 @@ static AtSmartPtr<AtNode> ConvertNode(json_spirit::Value node)
}
else if (node.type() == json_spirit::bool_type)
{
if (node.get_bool())
obj->m_Value = L"true";
else
obj->m_Value = L"false";
obj->m_Value = node.get_bool() ? "true" : "false";
obj->m_Children.insert(AtNode::child_pairtype(
"@boolean", AtSmartPtr<AtNode>(new AtNode())
@ -125,10 +120,8 @@ json_spirit::Value BuildJSONNode(AtNode::Ptr p)
if (p->m_Children.count("@number"))
{
// Convert to double
std::wstringstream str;
str << p->m_Value;
double val = 0;
str >> val;
static_cast<std::stringstream>(p->m_Value) >> val;
json_spirit::Value rval(val);
return rval;
@ -136,7 +129,7 @@ json_spirit::Value BuildJSONNode(AtNode::Ptr p)
else if (p->m_Children.count("@boolean"))
{
bool val = false;
if (p->m_Value == L"true")
if (p->m_Value == "true")
val = true;
json_spirit::Value rval(val);
@ -146,7 +139,7 @@ json_spirit::Value BuildJSONNode(AtNode::Ptr p)
// If no children, then use the value string instead
if (p->m_Children.empty())
{
json_spirit::Value rval(std::string(p->m_Value.begin(), p->m_Value.end()));
json_spirit::Value rval(p->m_Value);
return rval;
}
@ -190,5 +183,5 @@ json_spirit::Value BuildJSONNode(AtNode::Ptr p)
std::string AtlasObject::SaveToJSON(AtObj& obj)
{
json_spirit::Value root = BuildJSONNode(obj.m_Node);
return json_spirit::write_string(root, 0);
return json_spirit::write_string(root, json_spirit::raw_utf8);
}

View File

@ -19,7 +19,7 @@
#include "AtlasObjectImpl.h"
#include "AtlasObject.h"
static std::wstring ConvertRecursive(const AtNode::Ptr obj, bool use_brackets = true)
static std::string ConvertRecursive(const AtNode::Ptr obj, bool use_brackets = true)
{
// Convert (1, ()) into "1"
// Convert (3, (d: (...), e: (...))) into "3 (conv(...), conv(...))"
@ -28,30 +28,30 @@ static std::wstring ConvertRecursive(const AtNode::Ptr obj, bool use_brackets =
// [alphabetical by key] ordering of children, but at least it's fairly readable
if (!obj)
return L"";
return "";
std::wstring result;
std::string result;
bool has_value = !obj->m_Value.empty();
bool has_children = !obj->m_Children.empty();
if (has_value && has_children)
result = obj->m_Value + L" ";
result = obj->m_Value + " ";
else if (has_value)
result = obj->m_Value;
// else no value; result = L""
// else no value; result = ""
if (has_children)
{
if (use_brackets)
result += L"(";
result += "(";
bool first_child = true; // so we can add ", " in appropriate places
for (const AtNode::child_maptype::value_type& child : obj->m_Children)
{
if (!first_child)
result += L", ";
result += ", ";
else
first_child = false;
@ -59,13 +59,13 @@ static std::wstring ConvertRecursive(const AtNode::Ptr obj, bool use_brackets =
}
if (use_brackets)
result += L")";
result += ")";
}
return result;
}
std::wstring AtlasObject::ConvertToString(const AtObj& obj)
std::string AtlasObject::ConvertToString(const AtObj& obj)
{
return ConvertRecursive(obj.m_Node, false);
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -15,18 +15,12 @@
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
// Public interface to text-related functions that make use of std::wstring
// Public interface to text-related functions that make use of std::string
//
// (This is done in order to avoid forcing inclusion of all the
// STL headers when they're not needed)
//#ifdef new // HACK: to make the STL headers happy with a redefined 'new'
//# undef new
//# include <string>
//# define new new(_NORMAL_BLOCK ,__FILE__, __LINE__)
//#else
# include <string>
//#endif
class AtObj;
@ -35,5 +29,5 @@ namespace AtlasObject
// Generate a human-readable string representation of the AtObj,
// as an easy way of visualising the data (without any horridly ugly
// XML junk)
std::wstring ConvertToString(const AtObj& obj);
std::string ConvertToString(const AtObj& obj);
}

View File

@ -26,89 +26,6 @@
#include <libxml/parser.h>
// UTF conversion code adapted from http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const char trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 };
static const unsigned long offsetsFromUTF8[6] = {
0x00000000UL, 0x00003080UL, 0x000E2080UL,
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
class toXmlChar
{
public:
toXmlChar(const std::wstring& str)
{
for(wchar_t ch : str)
{
unsigned short bytesToWrite;
if (ch < 0x80) bytesToWrite = 1;
else if (ch < 0x800) bytesToWrite = 2;
else if (ch < 0x10000) bytesToWrite = 3;
else if (ch < 0x110000) bytesToWrite = 4;
else bytesToWrite = 3, ch = 0xFFFD; // replacement character
char buf[4];
char* target = &buf[bytesToWrite];
// GCC sometimes warns "array subscript is above array bounds [-Warray-bounds]"
// for the above line, which is a false positive - the C++ standard allows a
// pointer to just after the last element in an array, as long as it's not
// dereferenced (which it isn't here)
switch (bytesToWrite)
{
case 4: *--target = ((ch | 0x80) & 0xBF); ch >>= 6;
case 3: *--target = ((ch | 0x80) & 0xBF); ch >>= 6;
case 2: *--target = ((ch | 0x80) & 0xBF); ch >>= 6;
case 1: *--target = (char)(ch | firstByteMark[bytesToWrite]);
}
data += std::string(buf, bytesToWrite);
}
}
operator const xmlChar*()
{
return (const xmlChar*)data.c_str();
}
private:
std::string data;
};
std::wstring fromXmlChar(const xmlChar* str)
{
std::wstring result;
const xmlChar* source = str;
const xmlChar* sourceEnd = str + strlen((const char*)str);
while (source < sourceEnd)
{
unsigned long ch = 0;
int extraBytesToRead = trailingBytesForUTF8[*source];
assert(source + extraBytesToRead < sourceEnd);
switch (extraBytesToRead)
{
case 5: ch += *source++; ch <<= 6;
case 4: ch += *source++; ch <<= 6;
case 3: ch += *source++; ch <<= 6;
case 2: ch += *source++; ch <<= 6;
case 1: ch += *source++; ch <<= 6;
case 0: ch += *source++;
}
ch -= offsetsFromUTF8[extraBytesToRead];
// Make sure it fits in a 16-bit wchar_t
if (ch > 0xFFFF)
ch = 0xFFFD;
result += (wchar_t)ch;
}
return result;
}
// TODO: replace most of the asserts below (e.g. for when it fails to load
// a file) with some proper logging/reporting system
@ -142,9 +59,9 @@ static AtSmartPtr<AtNode> ConvertNode(xmlNodePtr node)
for (xmlAttrPtr cur_attr = node->properties; cur_attr; cur_attr = cur_attr->next)
{
std::string name ("@");
name += (const char*)cur_attr->name;
name += reinterpret_cast<const char*>(cur_attr->name);
xmlChar* content = xmlNodeGetContent(cur_attr->children);
std::wstring value (fromXmlChar(content));
std::string value = reinterpret_cast<char*>(content);
xmlFree(content);
AtNode* newNode = new AtNode(value.c_str());
@ -159,23 +76,23 @@ static AtSmartPtr<AtNode> ConvertNode(xmlNodePtr node)
if (cur_node->type == XML_ELEMENT_NODE)
{
obj->m_Children.insert(AtNode::child_pairtype(
(const char*)cur_node->name, ConvertNode(cur_node)
reinterpret_cast<const char*>(cur_node->name), ConvertNode(cur_node)
));
}
else if (cur_node->type == XML_TEXT_NODE)
{
xmlChar* content = xmlNodeGetContent(cur_node);
std::wstring value (fromXmlChar(content));
std::string value = reinterpret_cast<char*>(content);
xmlFree(content);
obj->m_Value += value;
}
}
// Trim whitespace surrounding the string value
const std::wstring whitespace = L" \t\r\n";
const std::string whitespace = " \t\r\n";
size_t first = obj->m_Value.find_first_not_of(whitespace);
if (first == std::wstring::npos)
obj->m_Value = L"";
if (first == std::string::npos)
obj->m_Value = "";
else
{
size_t last = obj->m_Value.find_last_not_of(whitespace);
@ -191,7 +108,7 @@ static void BuildDOMNode(xmlDocPtr doc, xmlNodePtr node, AtNode::Ptr p)
if (p)
{
if (p->m_Value.length())
xmlNodeAddContent(node, toXmlChar(p->m_Value));
xmlNodeAddContent(node, reinterpret_cast<const xmlChar*>(p->m_Value.c_str()));
for (const AtNode::child_maptype::value_type& child : p->m_Children)
{
@ -202,7 +119,7 @@ static void BuildDOMNode(xmlDocPtr doc, xmlNodePtr node, AtNode::Ptr p)
{
assert(child.second);
assert(child.second->m_Children.empty());
xmlNewProp(node, first_child + 1, toXmlChar(child.second->m_Value));
xmlNewProp(node, first_child + 1, reinterpret_cast<const xmlChar*>(child.second->m_Value.c_str()));
}
else
{

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2009 Wildfire Games.
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -141,7 +141,7 @@ public:
try_parse_save(
"<?xml version=\"1.0\" encoding=\"utf-8\"?><foo>&#xfffc;&#xfffd;&#x10000;&#x10ffff;</foo>",
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<foo>\xEF\xBF\xBC\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD</foo>\n"
"<foo>\xEF\xBF\xBC\xEF\xBF\xBD\xF0\x90\x80\x80\xF4\x8F\xBF\xBF</foo>\n"
);
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2014 Wildfire Games.
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -17,6 +17,8 @@
#include "precompiled.h"
#include <boost/algorithm/string.hpp>
#include "ActorEditor.h"
#include "ActorEditorListCtrl.h"
@ -123,10 +125,10 @@ AtObj ActorEditor::FreezeData()
AtObj actor (m_ActorEditorListCtrl->FreezeData());
if (m_CastShadows->IsChecked())
actor.set("castshadow", L"");
actor.set("castshadow", "");
if (m_Float->IsChecked())
actor.set("float", L"");
actor.set("float", "");
if (m_Material->GetValue().length())
actor.set("material", m_Material->GetValue());
@ -142,7 +144,7 @@ static AtObj ConvertToLatestFormat(AtObj in)
{
// 'Importing' a new blank file. Fill it in with default values:
AtObj actor;
actor.add("@version", L"1");
actor.add("@version", "1");
in.add("actor", actor);
}
@ -155,12 +157,7 @@ static AtObj ConvertToLatestFormat(AtObj in)
version = -1;
}
else if (in["actor"].defined())
{
if (in["actor"]["@version"].defined())
wxString(in["actor"]["@version"]).ToLong(&version);
else
version = 0;
}
version = (in["actor"]["@version"].defined()) ? (*in["actor"]["@version"]).getLong() : 0;
else
{
wxLogError(_("Failed to determine actor file format version"));
@ -175,47 +172,44 @@ static AtObj ConvertToLatestFormat(AtObj in)
AtObj actor;
// Handle the global actor properties
if (wxString(in["Object"]["Properties"]["@autoflatten"]) == _T("1"))
actor.add("autoflatten", L"");
if (in["Object"]["Properties"]["@autoflatten"] == "1")
actor.add("autoflatten", "");
if (wxString(in["Object"]["Properties"]["@castshadows"]) == _T("1"))
actor.add("castshadow", L"");
if (in["Object"]["Properties"]["@castshadows"] == "1")
actor.add("castshadow", "");
// Things to strip leading strings (for converting filenames, since the
// new format doesn't store the entire path)
#define THING1(out,outname, in,inname, prefix) \
wxASSERT( wxString(in["Object"][inname]).StartsWith(_T(prefix)) ); \
out.add(outname, wxString(in["Object"][inname]).Mid(wxString(_T(prefix)).Length()))
wxASSERT( wxString::FromUTF8(in["Object"][inname]).StartsWith(_T(prefix)) ); \
out.add(outname, wxString::FromUTF8(in["Object"][inname]).Mid(wxString(_T(prefix)).Length()))
#define THING2(out,outname, in,inname, prefix) \
wxASSERT( wxString(in[inname]).StartsWith(_T(prefix)) ); \
out.add(outname, wxString(in[inname]).Mid(wxString(_T(prefix)).Length()))
wxASSERT( wxString::FromUTF8(in[inname]).StartsWith(_T(prefix)) ); \
out.add(outname, wxString::FromUTF8(in[inname]).Mid(wxString(_T(prefix)).Length()))
if (wxString(in["Object"]["Material"]).Len())
if (wxString::FromUTF8(in["Object"]["Material"]).Len())
{
THING1(actor,"material", in,"Material", "art/materials/");
}
// Create a single variant to contain all the old data
AtObj var;
var.add("@name", L"Base");
var.add("@frequency", L"100"); // 100 == default frequency
var.add("@name", "Base");
var.add("@frequency", "100"); // 100 == default frequency
THING1(var,"mesh", in,"ModelName", "art/meshes/");
// XXX
if (wxString(in["Object"]["TextureName"]).StartsWith(_T("art/textures/ui/session/portraits/ui_portrait_sheet_civ_")))
{
var.add("texture", L"temp/" + wxString(in["Object"]["TextureName"]).Mid(strlen("art/textures/ui/session/portraits/")));
}
std::string textureName(in["Object"]["TextureName"]);
if (boost::algorithm::starts_with(textureName, "art/textures/ui/session/portraits/ui_portrait_sheet_civ_"))
var.add("texture", ("temp/" + textureName.substr(strlen("art/textures/ui/session/portraits/"))).c_str());
else
{
THING1(var,"texture", in,"TextureName", "art/textures/skins/");
}
AtObj anims;
for (AtIter animit = in["Object"]["Animations"]["Animation"]; animit.defined(); ++animit)
{
if (wcslen(animit["@file"]))
if (strlen(animit["@file"]))
{
AtObj anim;
anim.add("@name", animit["@name"]);
@ -245,7 +239,7 @@ static AtObj ConvertToLatestFormat(AtObj in)
#undef THING1
#undef THING2
actor.set("@version", L"1");
actor.set("@version", "1");
in = AtObj();
in.set("actor", actor);
}
@ -295,7 +289,7 @@ static AtObj ConvertToLatestFormat(AtObj in)
actor.add("group", grp);
}
actor.set("@version", L"1");
actor.set("@version", "1");
in.set("actor", actor);
}
else if (version == 1)
@ -333,13 +327,13 @@ AtObj ActorEditor::ExportData()
// Export the group/variant/etc data
AtObj actor (m_ActorEditorListCtrl->ExportData());
actor.set("@version", L"1");
actor.set("@version", "1");
if (m_CastShadows->IsChecked())
actor.set("castshadow", L"");
actor.set("castshadow", "");
if (m_Float->IsChecked())
actor.set("float", L"");
actor.set("float", "");
if (m_Material->GetValue().length())
actor.set("material", m_Material->GetValue());

View File

@ -514,7 +514,7 @@ ScenarioEditor::ScenarioEditor(wxWindow* parent)
menuHelp->Append(ID_##id, _(wxString(data[#id]["title"])), _(wxString(data[#id]["tooltip"]))); \
m_HelpData.insert(std::make_pair( \
ID_##id, \
HelpItem(wxString(data[#id]["title"]), wxString(data[#id]["tooltip"]), wxString(data[#id]["url"])) \
HelpItem(wxString::FromUTF8(data[#id]["title"]), wxString::FromUTF8(data[#id]["tooltip"]), wxString::FromUTF8(data[#id]["url"])) \
)); \
} while (0)
ADD_HELP_ITEM(Manual);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2018 Wildfire Games.
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -112,8 +112,8 @@ private:
OnConquestChanged();
}
std::set<std::wstring> m_MapSettingsKeywords;
std::set<std::wstring> m_MapSettingsVictoryConditions;
std::set<std::string> m_MapSettingsKeywords;
std::set<std::string> m_MapSettingsVictoryConditions;
std::vector<wxChoice*> m_PlayerCivChoices;
Observable<AtObj>& m_MapSettings;
@ -203,21 +203,21 @@ void MapSettingsControl::ReadFromEngine()
}
// map name
wxDynamicCast(FindWindow(ID_MapName), wxTextCtrl)->ChangeValue(wxString(m_MapSettings["Name"]));
wxDynamicCast(FindWindow(ID_MapName), wxTextCtrl)->ChangeValue(wxString::FromUTF8(m_MapSettings["Name"]));
// map description
wxDynamicCast(FindWindow(ID_MapDescription), wxTextCtrl)->ChangeValue(wxString(m_MapSettings["Description"]));
wxDynamicCast(FindWindow(ID_MapDescription), wxTextCtrl)->ChangeValue(wxString::FromUTF8(m_MapSettings["Description"]));
// map preview
wxDynamicCast(FindWindow(ID_MapPreview), wxTextCtrl)->ChangeValue(wxString(m_MapSettings["Preview"]));
wxDynamicCast(FindWindow(ID_MapPreview), wxTextCtrl)->ChangeValue(wxString::FromUTF8(m_MapSettings["Preview"]));
// reveal map
wxDynamicCast(FindWindow(ID_MapReveal), wxCheckBox)->SetValue(wxString(m_MapSettings["RevealMap"]) == L"true");
wxDynamicCast(FindWindow(ID_MapReveal), wxCheckBox)->SetValue(wxString::FromUTF8(m_MapSettings["RevealMap"]) == "true");
// victory conditions
m_MapSettingsVictoryConditions.clear();
for (AtIter victoryCondition = m_MapSettings["VictoryConditions"]["item"]; victoryCondition.defined(); ++victoryCondition)
m_MapSettingsVictoryConditions.insert(std::wstring(victoryCondition));
m_MapSettingsVictoryConditions.insert(std::string(victoryCondition));
wxWindow* window;
#define INIT_CHECKBOX(ID, mapSettings, value) \
@ -225,25 +225,25 @@ void MapSettingsControl::ReadFromEngine()
if (window != nullptr) \
wxDynamicCast(window, wxCheckBox)->SetValue(mapSettings.count(value) != 0);
INIT_CHECKBOX(ID_VC_Conquest, m_MapSettingsVictoryConditions, L"conquest");
INIT_CHECKBOX(ID_VC_ConquestUnits, m_MapSettingsVictoryConditions, L"conquest_units");
INIT_CHECKBOX(ID_VC_ConquestStructures, m_MapSettingsVictoryConditions, L"conquest_structures");
INIT_CHECKBOX(ID_VC_CaptureTheRelic, m_MapSettingsVictoryConditions, L"capture_the_relic");
INIT_CHECKBOX(ID_VC_Wonder, m_MapSettingsVictoryConditions, L"wonder");
INIT_CHECKBOX(ID_VC_Regicide, m_MapSettingsVictoryConditions, L"regicide");
INIT_CHECKBOX(ID_VC_Conquest, m_MapSettingsVictoryConditions, "conquest");
INIT_CHECKBOX(ID_VC_ConquestUnits, m_MapSettingsVictoryConditions, "conquest_units");
INIT_CHECKBOX(ID_VC_ConquestStructures, m_MapSettingsVictoryConditions, "conquest_structures");
INIT_CHECKBOX(ID_VC_CaptureTheRelic, m_MapSettingsVictoryConditions, "capture_the_relic");
INIT_CHECKBOX(ID_VC_Wonder, m_MapSettingsVictoryConditions, "wonder");
INIT_CHECKBOX(ID_VC_Regicide, m_MapSettingsVictoryConditions, "regicide");
OnConquestChanged();
// lock teams
wxDynamicCast(FindWindow(ID_MapTeams), wxCheckBox)->SetValue(wxString(m_MapSettings["LockTeams"]) == L"true");
wxDynamicCast(FindWindow(ID_MapTeams), wxCheckBox)->SetValue(wxString::FromUTF8(m_MapSettings["LockTeams"]) == "true");
// keywords
{
m_MapSettingsKeywords.clear();
for (AtIter keyword = m_MapSettings["Keywords"]["item"]; keyword.defined(); ++keyword)
m_MapSettingsKeywords.insert(std::wstring(keyword));
m_MapSettingsKeywords.insert(std::string(keyword));
INIT_CHECKBOX(ID_MapKW_Demo, m_MapSettingsKeywords, L"demo");
INIT_CHECKBOX(ID_MapKW_Naval, m_MapSettingsKeywords, L"naval");
INIT_CHECKBOX(ID_MapKW_Demo, m_MapSettingsKeywords, "demo");
INIT_CHECKBOX(ID_MapKW_Naval, m_MapSettingsKeywords, "naval");
}
#undef INIT_CHECKBOX
@ -276,13 +276,13 @@ void MapSettingsControl::OnConquestChanged()
AtObj MapSettingsControl::UpdateSettingsObject()
{
// map name
m_MapSettings.set("Name", wxDynamicCast(FindWindow(ID_MapName), wxTextCtrl)->GetValue());
m_MapSettings.set("Name", wxDynamicCast(FindWindow(ID_MapName), wxTextCtrl)->GetValue().utf8_str());
// map description
m_MapSettings.set("Description", wxDynamicCast(FindWindow(ID_MapDescription), wxTextCtrl)->GetValue());
m_MapSettings.set("Description", wxDynamicCast(FindWindow(ID_MapDescription), wxTextCtrl)->GetValue().utf8_str());
// map preview
m_MapSettings.set("Preview", wxDynamicCast(FindWindow(ID_MapPreview), wxTextCtrl)->GetValue());
m_MapSettings.set("Preview", wxDynamicCast(FindWindow(ID_MapPreview), wxTextCtrl)->GetValue().utf8_str());
// reveal map
m_MapSettings.setBool("RevealMap", wxDynamicCast(FindWindow(ID_MapReveal), wxCheckBox)->GetValue());
@ -294,37 +294,37 @@ AtObj MapSettingsControl::UpdateSettingsObject()
else \
m_MapSettingsVictoryConditions.erase(name);
INSERT_VICTORY_CONDITION_CHECKBOX(L"conquest", ID_VC_Conquest);
INSERT_VICTORY_CONDITION_CHECKBOX(L"conquest_units", ID_VC_ConquestUnits);
INSERT_VICTORY_CONDITION_CHECKBOX(L"conquest_structures", ID_VC_ConquestStructures);
INSERT_VICTORY_CONDITION_CHECKBOX(L"capture_the_relic", ID_VC_CaptureTheRelic);
INSERT_VICTORY_CONDITION_CHECKBOX(L"wonder", ID_VC_Wonder);
INSERT_VICTORY_CONDITION_CHECKBOX(L"regicide", ID_VC_Regicide);
INSERT_VICTORY_CONDITION_CHECKBOX("conquest", ID_VC_Conquest);
INSERT_VICTORY_CONDITION_CHECKBOX("conquest_units", ID_VC_ConquestUnits);
INSERT_VICTORY_CONDITION_CHECKBOX("conquest_structures", ID_VC_ConquestStructures);
INSERT_VICTORY_CONDITION_CHECKBOX("capture_the_relic", ID_VC_CaptureTheRelic);
INSERT_VICTORY_CONDITION_CHECKBOX("wonder", ID_VC_Wonder);
INSERT_VICTORY_CONDITION_CHECKBOX("regicide", ID_VC_Regicide);
#undef INSERT_VICTORY_CONDITION_CHECKBOX
AtObj victoryConditions;
victoryConditions.set("@array", L"");
for (std::set<std::wstring>::iterator it = m_MapSettingsVictoryConditions.begin(); it != m_MapSettingsVictoryConditions.end(); ++it)
victoryConditions.add("item", it->c_str());
victoryConditions.set("@array", "");
for (const std::string& victoryCondition : m_MapSettingsVictoryConditions)
victoryConditions.add("item", victoryCondition.c_str());
m_MapSettings.set("VictoryConditions", victoryConditions);
// keywords
{
if (wxDynamicCast(FindWindow(ID_MapKW_Demo), wxCheckBox)->GetValue())
m_MapSettingsKeywords.insert(L"demo");
m_MapSettingsKeywords.insert("demo");
else
m_MapSettingsKeywords.erase(L"demo");
m_MapSettingsKeywords.erase("demo");
if (wxDynamicCast(FindWindow(ID_MapKW_Naval), wxCheckBox)->GetValue())
m_MapSettingsKeywords.insert(L"naval");
m_MapSettingsKeywords.insert("naval");
else
m_MapSettingsKeywords.erase(L"naval");
m_MapSettingsKeywords.erase("naval");
AtObj keywords;
keywords.set("@array", L"");
for (std::set<std::wstring>::iterator it = m_MapSettingsKeywords.begin(); it != m_MapSettingsKeywords.end(); ++it)
keywords.add("item", it->c_str());
keywords.set("@array", "");
for (const std::string& keyword : m_MapSettingsKeywords)
keywords.add("item", keyword.c_str());
m_MapSettings.set("Keywords", keywords);
}
@ -447,11 +447,7 @@ void MapSidebar::OnFirstDisplay()
AtObj sizes = AtlasObject::LoadFromJSON(*qrySizes.sizes);
wxChoice* sizeChoice = wxDynamicCast(FindWindow(ID_RandomSize), wxChoice);
for (AtIter s = sizes["Data"]["item"]; s.defined(); ++s)
{
long tiles = 0;
wxString(s["Tiles"]).ToLong(&tiles);
sizeChoice->Append(wxString(s["Name"]), (void*)(intptr_t)tiles);
}
sizeChoice->Append(wxString::FromUTF8(s["Name"]), reinterpret_cast<void*>((*s["Tiles"]).getLong()));
sizeChoice->SetSelection(0);
// Load the RMS script list
@ -463,7 +459,7 @@ void MapSidebar::OnFirstDisplay()
for (size_t i = 0; i < scripts.size(); ++i)
{
AtObj data = AtlasObject::LoadFromJSON(scripts[i]);
wxString name(data["settings"]["Name"]);
wxString name = wxString::FromUTF8(data["settings"]["Name"]);
if (!name.IsEmpty())
scriptChoice->Append(name, new AtObjClientData(*data["settings"]));
}
@ -616,7 +612,7 @@ void MapSidebar::OnRandomGenerate(wxCommandEvent& WXUNUSED(evt))
wxBusyInfo busy(_("Generating map"));
wxBusyCursor busyc;
wxString scriptName(settings["Script"]);
wxString scriptName = wxString::FromUTF8(settings["Script"]);
// Copy the old map settings, so we don't lose them if the map generation fails
AtObj oldSettings = settings;
@ -627,7 +623,7 @@ void MapSidebar::OnRandomGenerate(wxCommandEvent& WXUNUSED(evt))
if (qry.status < 0)
{
// Display error message and revert to old map settings
wxLogError(_("Random map script '%ls' failed"), scriptName.wc_str());
wxLogError(_("Random map script '%s' failed"), scriptName.c_str());
m_MapSettingsCtrl->SetMapSettings(oldSettings);
}

View File

@ -99,8 +99,8 @@ struct ObjectSidebarImpl
{
ObjectSidebarImpl(ScenarioEditor& scenarioEditor) :
m_ObjectListBox(NULL), m_ActorViewerActive(false),
m_ActorViewerEntity(_T("actor|structures/fndn_1x1.xml")),
m_ActorViewerAnimation(_T("idle")), m_ActorViewerSpeed(0.f),
m_ActorViewerEntity(L"actor|structures/fndn_1x1.xml"),
m_ActorViewerAnimation("idle"), m_ActorViewerSpeed(0.f),
m_ObjectSettings(scenarioEditor.GetObjectSettings())
{
}
@ -110,14 +110,14 @@ struct ObjectSidebarImpl
ObservableScopedConnection m_ToolConn;
bool m_ActorViewerActive;
wxString m_ActorViewerEntity;
wxString m_ActorViewerAnimation;
std::wstring m_ActorViewerEntity;
std::string m_ActorViewerAnimation;
float m_ActorViewerSpeed;
Observable<ObjectSettings>& m_ObjectSettings;
void ActorViewerPostToGame()
{
POST_MESSAGE(SetActorViewer, ((std::wstring)m_ActorViewerEntity.wc_str(), (std::wstring)m_ActorViewerAnimation.wc_str(), m_ObjectSettings.GetPlayerID(), m_ActorViewerSpeed, false));
POST_MESSAGE(SetActorViewer, (m_ActorViewerEntity.c_str(), m_ActorViewerAnimation.c_str(), m_ObjectSettings.GetPlayerID(), m_ActorViewerSpeed, false));
}
};
@ -545,7 +545,7 @@ void ObjectBottomBar::OnFirstDisplay()
AtObj playerData = AtlasObject::LoadFromJSON(*qryPlayers.defaults);
AtObj playerDefs = *playerData["PlayerData"];
for (AtIter iterator = playerDefs["item"]; iterator.defined(); ++iterator)
players.Add(wxString(iterator["Name"]));
players.Add(wxString::FromUTF8(iterator["Name"]));
wxDynamicCast(FindWindow(ID_PlayerSelect), PlayerComboBox)->SetPlayers(players);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games.
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -587,8 +587,8 @@ void PlayerSettingsControl::CreateWidgets()
for (size_t i = 0; i < civData.size(); ++i)
{
AtObj civ = AtlasObject::LoadFromJSON(civData[i]);
civNames.Add(wxString(civ["Name"]));
civCodes.Add(wxString(civ["Code"]));
civNames.Add(wxString::FromUTF8(civ["Name"]));
civCodes.Add(wxString::FromUTF8(civ["Code"]));
}
// Load AI data
@ -598,7 +598,7 @@ void PlayerSettingsControl::CreateWidgets()
AtObj aiData = AtlasObject::LoadFromJSON(*qryAI.data);
for (AtIter a = aiData["AIData"]["item"]; a.defined(); ++a)
{
ais.Add(new AIData(wxString(a["id"]), wxString(a["data"]["name"])));
ais.Add(new AIData(wxString::FromUTF8(a["id"]), wxString::FromUTF8(a["data"]["name"])));
}
// Create player pages
@ -695,21 +695,17 @@ void PlayerSettingsControl::ReadFromEngine()
wxString name(_("Unknown"));
bool defined = player["Name"].defined();
if (defined)
name = wxString(player["Name"]);
name = wxString::FromUTF8(player["Name"]);
else if (playerDefs["Name"].defined())
name = wxString(playerDefs["Name"]);
name = wxString::FromUTF8(playerDefs["Name"]);
controls.name->SetValue(name);
wxDynamicCast(FindWindowById(ID_DefaultName, controls.page), DefaultCheckbox)->SetValue(defined);
// civ
wxChoice* choice = controls.civ;
wxString civCode;
defined = player["Civ"].defined();
if (defined)
civCode = wxString(player["Civ"]);
else
civCode = wxString(playerDefs["Civ"]);
wxString civCode = wxString::FromUTF8(defined ? player["Civ"] : playerDefs["Civ"]);
for (size_t j = 0; j < choice->GetCount(); ++j)
{
@ -733,12 +729,8 @@ void PlayerSettingsControl::ReadFromEngine()
wxDynamicCast(FindWindowById(ID_DefaultColor, controls.page), DefaultCheckbox)->SetValue(defined);
// player type
wxString aiID;
defined = player["AI"].defined();
if (defined)
aiID = wxString(player["AI"]);
else
aiID = wxString(playerDefs["AI"]);
wxString aiID = wxString::FromUTF8(defined ? player["AI"] : playerDefs["AI"]);
choice = controls.ai;
if (!aiID.empty())
@ -762,28 +754,28 @@ void PlayerSettingsControl::ReadFromEngine()
AtObj resObj = *player["Resources"];
defined = resObj.defined() && resObj["food"].defined();
if (defined)
controls.food->SetValue(wxString(resObj["food"]));
controls.food->SetValue((*resObj["food"]).getInt());
else
controls.food->SetValue(0);
wxDynamicCast(FindWindowById(ID_DefaultFood, controls.page), DefaultCheckbox)->SetValue(defined);
defined = resObj.defined() && resObj["wood"].defined();
if (defined)
controls.wood->SetValue(wxString(resObj["wood"]));
controls.wood->SetValue((*resObj["wood"]).getInt());
else
controls.wood->SetValue(0);
wxDynamicCast(FindWindowById(ID_DefaultWood, controls.page), DefaultCheckbox)->SetValue(defined);
defined = resObj.defined() && resObj["metal"].defined();
if (defined)
controls.metal->SetValue(wxString(resObj["metal"]));
controls.metal->SetValue((*resObj["metal"]).getInt());
else
controls.metal->SetValue(0);
wxDynamicCast(FindWindowById(ID_DefaultMetal, controls.page), DefaultCheckbox)->SetValue(defined);
defined = resObj.defined() && resObj["stone"].defined();
if (defined)
controls.stone->SetValue(wxString(resObj["stone"]));
controls.stone->SetValue((*resObj["stone"]).getInt());
else
controls.stone->SetValue(0);
wxDynamicCast(FindWindowById(ID_DefaultStone, controls.page), DefaultCheckbox)->SetValue(defined);
@ -791,7 +783,7 @@ void PlayerSettingsControl::ReadFromEngine()
// population limit
defined = player["PopulationLimit"].defined();
if (defined)
controls.pop->SetValue(wxString(player["PopulationLimit"]));
controls.pop->SetValue((*player["PopulationLimit"]).getInt());
else
controls.pop->SetValue(0);
wxDynamicCast(FindWindowById(ID_DefaultPop, controls.page), DefaultCheckbox)->SetValue(defined);
@ -842,7 +834,7 @@ AtObj PlayerSettingsControl::UpdateSettingsObject()
{
// Update player data in the map settings
AtObj players;
players.set("@array", L"");
players.set("@array", "");
wxASSERT(m_NumPlayers <= MAX_NUM_PLAYERS);
@ -859,7 +851,7 @@ AtObj PlayerSettingsControl::UpdateSettingsObject()
// name
wxTextCtrl* text = controls.name;
if (text->IsEnabled())
player.set("Name", text->GetValue());
player.set("Name", text->GetValue().utf8_str());
// civ
wxChoice* choice = controls.civ;
@ -893,7 +885,7 @@ AtObj PlayerSettingsControl::UpdateSettingsObject()
player.set("AI", str->GetData());
}
else // human
player.set("AI", _T(""));
player.set("AI", _(""));
}
// resources

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games.
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -294,10 +294,8 @@ void TerrainSidebar::OnResizeMap(wxCommandEvent& WXUNUSED(evt))
AtObj sizes = AtlasObject::LoadFromJSON(*qrySizes.sizes);
for (AtIter s = sizes["Data"]["item"]; s.defined(); ++s)
{
long tiles = 0;
wxString(s["Tiles"]).ToLong(&tiles);
sizeNames.Add(wxString(s["Name"]));
sizeTiles.push_back((size_t)tiles);
sizeNames.Add(wxString::FromUTF8(s["Name"]));
sizeTiles.push_back((*s["Tiles"]).getLong());
}
// TODO: set default based on current map size

View File

@ -77,7 +77,7 @@ public:
entity_id_t Entity;
CStrW CurrentUnitID;
CStrW CurrentUnitAnim;
CStr CurrentUnitAnim;
float CurrentSpeed;
bool WalkEnabled;
bool GroundEnabled;
@ -328,7 +328,7 @@ void ActorViewer::UnloadObjects()
m.ObjectManager.UnloadObjects();
}
void ActorViewer::SetActor(const CStrW& name, const CStrW& animation, player_id_t playerID)
void ActorViewer::SetActor(const CStrW& name, const CStr& animation, player_id_t playerID)
{
bool needsAnimReload = false;
@ -376,7 +376,7 @@ void ActorViewer::SetActor(const CStrW& name, const CStrW& animation, player_id_
if (needsAnimReload)
{
CStr anim = animation.ToUTF8().LowerCase();
CStr anim = animation.LowerCase();
// Emulate the typical simulation animation behaviour
float speed;

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games.
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -35,7 +35,7 @@ public:
CSimulation2* GetSimulation2();
entity_id_t GetEntity();
void SetActor(const CStrW& id, const CStrW& animation, player_id_t playerID);
void SetActor(const CStrW& id, const CStr& animation, player_id_t playerID);
void SetEnabled(bool enabled);
void UnloadObjects();
void SetBackgroundColor(const SColor4ub& color);

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games.
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -162,7 +162,7 @@ MESSAGEHANDLER(SetActorViewer)
// alright.)
// Should replace this with proper actor hot-loading system, or something.
AtlasView::GetView_Actor()->GetActorViewer().SetActor(L"", L"", -1);
AtlasView::GetView_Actor()->GetActorViewer().SetActor(L"", "", -1);
AtlasView::GetView_Actor()->GetActorViewer().UnloadObjects();
// vfs_reload_changed_files();
}

View File

@ -33,6 +33,7 @@
#include "graphics/Terrain.h"
#include "graphics/Unit.h"
#include "lib/ogl.h"
#include "lib/utf8.h"
#include "maths/MathUtil.h"
#include "maths/Matrix3D.h"
#include "ps/CLogger.h"
@ -299,7 +300,7 @@ QUERYHANDLER(GetObjectMapSettings)
}
const CStr& data = exampleFile.GetOutput();
msg->xmldata = std::wstring(data.begin(), data.end());
msg->xmldata = data.FromUTF8();
}
@ -417,9 +418,8 @@ MESSAGEHANDLER(ObjectPreviewToEntity)
//I need to re create the objects finally delete preview objects
for (entity_id_t ent : g_PreviewEntitiesID)
{
//Get template
std::string templateName = cmpTemplateManager->GetCurrentTemplateName(ent);
std::wstring wTemplateName(templateName.begin() + 8, templateName.end());
//Get template name (without the "preview|" prefix)
std::wstring wTemplateName = wstring_from_utf8(cmpTemplateManager->GetCurrentTemplateName(ent).substr(8));
//Create new entity
entity_id_t new_ent = g_Game->GetSimulation2()->AddEntity(wTemplateName);
if (new_ent == INVALID_ENTITY)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2018 Wildfire Games.
/* Copyright (C) 2019 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -393,7 +393,7 @@ COMMAND(CreateObject, NOMERGE,
// (Use RenderEnable to make it visible.)
MESSAGE(SetActorViewer,
((std::wstring, id))
((std::wstring, animation))
((std::string, animation))
((int, playerID))
((float, speed))
((bool, flushcache)) // true => unload all actor files before starting the preview (because we don't have proper hotloading yet)