make otml simpler and easier to use, improve error handling/exceptions
This commit is contained in:
parent
f9e7d52ac0
commit
033f14780d
|
@ -110,15 +110,16 @@ SET(SOURCES
|
||||||
# framework otml
|
# framework otml
|
||||||
src/framework/otml/otmldocument.cpp
|
src/framework/otml/otmldocument.cpp
|
||||||
src/framework/otml/otmlemitter.cpp
|
src/framework/otml/otmlemitter.cpp
|
||||||
src/framework/otml/otmlexception.cpp
|
|
||||||
src/framework/otml/otmlnode.cpp
|
src/framework/otml/otmlnode.cpp
|
||||||
src/framework/otml/otmlparser.cpp
|
src/framework/otml/otmlparser.cpp
|
||||||
|
src/framework/otml/otmlexception.cpp
|
||||||
|
|
||||||
# framework luascript
|
# framework luascript
|
||||||
src/framework/luascript/luainterface.cpp
|
src/framework/luascript/luainterface.cpp
|
||||||
src/framework/luascript/luaobject.cpp
|
src/framework/luascript/luaobject.cpp
|
||||||
src/framework/luascript/luaexception.cpp
|
src/framework/luascript/luaexception.cpp
|
||||||
src/framework/luascript/luafunctions.cpp
|
src/framework/luascript/luafunctions.cpp
|
||||||
|
src/framework/luascript/luavaluecasts.cpp
|
||||||
|
|
||||||
# framework ui
|
# framework ui
|
||||||
src/framework/ui/uimanager.cpp
|
src/framework/ui/uimanager.cpp
|
||||||
|
|
|
@ -9,27 +9,23 @@ bool Configs::load(const std::string& fileName)
|
||||||
{
|
{
|
||||||
m_fileName = fileName;
|
m_fileName = fileName;
|
||||||
|
|
||||||
if(!g_resources.fileExists(fileName))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
OTMLDocumentPtr doc = OTMLDocument::parse(fileName);
|
OTMLDocumentPtr doc = OTMLDocument::parse(fileName);
|
||||||
for(const OTMLNodePtr& child : doc->childNodes())
|
for(const OTMLNodePtr& child : doc->children())
|
||||||
m_confsMap[child->tag()] = child->value();
|
m_confsMap[child->tag()] = child->value();
|
||||||
|
return true;
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
logError("ERROR: could not load configurations: ", e.what());
|
logError("ERROR: could not load configurations: ", e.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Configs::save()
|
bool Configs::save()
|
||||||
{
|
{
|
||||||
if(!m_fileName.empty()) {
|
|
||||||
OTMLDocumentPtr doc = OTMLDocument::create();
|
OTMLDocumentPtr doc = OTMLDocument::create();
|
||||||
doc->write(m_confsMap);
|
for(auto it : m_confsMap) {
|
||||||
return doc->save(m_fileName);
|
OTMLNodePtr node = OTMLNode::create(it.first, it.second);
|
||||||
|
doc->addChild(node);
|
||||||
}
|
}
|
||||||
return false;
|
return doc->save(m_fileName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,61 +6,57 @@
|
||||||
|
|
||||||
void Module::discover(const OTMLNodePtr& moduleNode)
|
void Module::discover(const OTMLNodePtr& moduleNode)
|
||||||
{
|
{
|
||||||
m_description = moduleNode->readAt<std::string>("description");
|
const static std::string none = "none";
|
||||||
m_author = moduleNode->readAt<std::string>("author");
|
m_description = moduleNode->valueAt("description", none);
|
||||||
m_website = moduleNode->readAt<std::string>("website");
|
m_author = moduleNode->valueAt("author", none);
|
||||||
m_version = moduleNode->readAt<std::string>("version");
|
m_website = moduleNode->valueAt("website", none);
|
||||||
|
m_version = moduleNode->valueAt("version", none);
|
||||||
|
m_autoLoad = moduleNode->valueAt<bool>("autoLoad", false);
|
||||||
|
|
||||||
if(OTMLNodePtr node = moduleNode->get("dependencies")) {
|
if(OTMLNodePtr node = moduleNode->get("dependencies")) {
|
||||||
for(const OTMLNodePtr& tmp : node->childNodes())
|
for(const OTMLNodePtr& tmp : node->children())
|
||||||
m_dependencies.push_back(tmp->value());
|
m_dependencies.push_back(tmp->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
// set onLoad callback
|
// set onLoad callback
|
||||||
if(OTMLNodePtr node = moduleNode->get("onLoad")) {
|
if(OTMLNodePtr node = moduleNode->get("onLoad")) {
|
||||||
g_lua.loadFunction(node->read<std::string>(), "@" + node->source() + "[" + node->tag() + "]");
|
g_lua.loadFunction(node->value<std::string>(), "@" + node->source() + "[" + node->tag() + "]");
|
||||||
g_lua.useValue();
|
g_lua.useValue();
|
||||||
m_loadCallback = g_lua.polymorphicPop<BooleanCallback>();
|
m_loadCallback = g_lua.polymorphicPop<BooleanCallback>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// set onUnload callback
|
// set onUnload callback
|
||||||
if(OTMLNodePtr node = moduleNode->get("onUnload")) {
|
if(OTMLNodePtr node = moduleNode->get("onUnload")) {
|
||||||
g_lua.loadFunction(node->read<std::string>(), "@" + node->source() + "[" + node->tag() + "]");
|
g_lua.loadFunction(node->value<std::string>(), "@" + node->source() + "[" + node->tag() + "]");
|
||||||
g_lua.useValue();
|
g_lua.useValue();
|
||||||
m_unloadCallback = g_lua.polymorphicPop<SimpleCallback>();
|
m_unloadCallback = g_lua.polymorphicPop<SimpleCallback>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// load if autoLoad is set
|
|
||||||
m_autoLoad = moduleNode->readAt<bool>("autoLoad", false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Module::load()
|
bool Module::load()
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
for(const std::string& depName : m_dependencies) {
|
for(const std::string& depName : m_dependencies) {
|
||||||
ModulePtr dep = g_modules.getModule(depName);
|
ModulePtr dep = g_modules.getModule(depName);
|
||||||
if(!dep) {
|
if(!dep)
|
||||||
logError("ERROR: failed to load module '",m_name,"': could not find module dependency '",depName,"'");
|
throw std::runtime_error(fw::mkstr("could not find module dependency '", depName ,"'"));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!dep->isLoaded()) {
|
if(!dep->isLoaded() && !dep->load())
|
||||||
if(!dep->load()) {
|
throw std::runtime_error(fw::mkstr("dependency '", depName, "' has failed to load"));
|
||||||
logError("ERROR: failed to load module '",m_name,"': a dependency has failed to load");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_loadCallback) {
|
if(m_loadCallback) {
|
||||||
m_loaded = m_loadCallback();
|
m_loaded = m_loadCallback();
|
||||||
if(!m_loaded) {
|
if(!m_loaded)
|
||||||
logError("ERROR: failed to load module '",m_name, "': onLoad returned false");
|
throw std::runtime_error("module onLoad event returned false");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logInfo("Loaded module '", m_name, "'");
|
logInfo("Loaded module '", m_name, "'");
|
||||||
return true;
|
return true;
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
logError("ERROR: failed to load module '", m_name, "': ", e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Module::unload()
|
void Module::unload()
|
||||||
|
|
|
@ -30,7 +30,7 @@ bool ModuleManager::discoverModule(const std::string& file)
|
||||||
OTMLDocumentPtr doc = OTMLDocument::parse(file);
|
OTMLDocumentPtr doc = OTMLDocument::parse(file);
|
||||||
OTMLNodePtr moduleNode = doc->at("Module");
|
OTMLNodePtr moduleNode = doc->at("Module");
|
||||||
|
|
||||||
std::string name = moduleNode->readAt<std::string>("name");
|
std::string name = moduleNode->valueAt("name");
|
||||||
if(getModule(name))
|
if(getModule(name))
|
||||||
throw OTMLException(moduleNode, "a module with the same name is already discovered, did you duplicate module names?");
|
throw OTMLException(moduleNode, "a module with the same name is already discovered, did you duplicate module names?");
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ bool ModuleManager::discoverModule(const std::string& file)
|
||||||
module->discover(moduleNode);
|
module->discover(moduleNode);
|
||||||
m_modules.push_back(module);
|
m_modules.push_back(module);
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
logError("ERROR: failed to load module from '", file, "':\n", e.what());
|
logError("ERROR: failed to load module from '", file, "': ", e.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -30,14 +30,14 @@ void ResourceManager::init(const char* argv0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!found)
|
if(!found)
|
||||||
throw std::runtime_error("could not find modules directory");
|
logFatal("FATAL ERROR: could not find modules directory");
|
||||||
|
|
||||||
// setup write directory
|
// setup write directory
|
||||||
std::string dir = g_platform.getAppUserDir();
|
std::string dir = g_platform.getAppUserDir();
|
||||||
if(g_resources.setWriteDir(dir))
|
if(g_resources.setWriteDir(dir))
|
||||||
g_resources.addToSearchPath(dir);
|
g_resources.addToSearchPath(dir);
|
||||||
else
|
else
|
||||||
throw std::runtime_error("could not setup write directory");
|
logError("ERROR: could not setup write directory");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResourceManager::terminate()
|
void ResourceManager::terminate()
|
||||||
|
@ -156,12 +156,11 @@ std::string ResourceManager::resolvePath(const std::string& path)
|
||||||
{
|
{
|
||||||
std::string fullPath;
|
std::string fullPath;
|
||||||
if(boost::starts_with(path, "/"))
|
if(boost::starts_with(path, "/"))
|
||||||
fullPath = path.substr(1);
|
fullPath = path;
|
||||||
else {
|
else {
|
||||||
std::string scriptPath = g_lua.currentSourcePath();
|
std::string scriptPath = "/" + g_lua.currentSourcePath();
|
||||||
if(!scriptPath.empty()) {
|
if(!scriptPath.empty())
|
||||||
fullPath += scriptPath + "/";
|
fullPath += scriptPath + "/";
|
||||||
}
|
|
||||||
fullPath += path;
|
fullPath += path;
|
||||||
}
|
}
|
||||||
return fullPath;
|
return fullPath;
|
||||||
|
|
|
@ -61,17 +61,17 @@ BorderImagePtr BorderImage::loadFromOTML(const OTMLNodePtr& borderImageNode)
|
||||||
|
|
||||||
// load basic border confs
|
// load basic border confs
|
||||||
size = texture->getSize();
|
size = texture->getSize();
|
||||||
size = borderImageNode->readAt("size", size);
|
size = borderImageNode->valueAt("size", size);
|
||||||
offset = borderImageNode->readAt("offset", offset);
|
offset = borderImageNode->valueAt("offset", offset);
|
||||||
border = borderImageNode->readAt("border", 0);
|
border = borderImageNode->valueAt("border", 0);
|
||||||
subRect = Rect(offset, size);
|
subRect = Rect(offset, size);
|
||||||
|
|
||||||
// load border margins
|
// load border margins
|
||||||
top = bottom = left = right = border;
|
top = bottom = left = right = border;
|
||||||
top = borderImageNode->readAt("border.top", top);
|
top = borderImageNode->valueAt("border.top", top);
|
||||||
bottom = borderImageNode->readAt("border.bottom", bottom);
|
bottom = borderImageNode->valueAt("border.bottom", bottom);
|
||||||
left = borderImageNode->readAt("border.left", left);
|
left = borderImageNode->valueAt("border.left", left);
|
||||||
right = borderImageNode->readAt("border.right", right);
|
right = borderImageNode->valueAt("border.right", right);
|
||||||
|
|
||||||
// calculates border coords
|
// calculates border coords
|
||||||
leftBorder = Rect(subRect.left(), subRect.top() + top, left, subRect.height() - top - bottom);
|
leftBorder = Rect(subRect.left(), subRect.top() + top, left, subRect.height() - top - bottom);
|
||||||
|
@ -86,15 +86,15 @@ BorderImagePtr BorderImage::loadFromOTML(const OTMLNodePtr& borderImageNode)
|
||||||
|
|
||||||
// load individual border conf if supplied
|
// load individual border conf if supplied
|
||||||
/*
|
/*
|
||||||
leftBorder = borderImageNode->readAt("left border", leftBorder);
|
leftBorder = borderImageNode->valueAt("left border", leftBorder);
|
||||||
rightBorder = borderImageNode->readAt("right border", rightBorder);
|
rightBorder = borderImageNode->valueAt("right border", rightBorder);
|
||||||
topBorder = borderImageNode->readAt("top border", topBorder);
|
topBorder = borderImageNode->valueAt("top border", topBorder);
|
||||||
bottomBorder = borderImageNode->readAt("bottom border", bottomBorder);
|
bottomBorder = borderImageNode->valueAt("bottom border", bottomBorder);
|
||||||
topLeftCorner = borderImageNode->readAt("top left corner", topLeftCorner);
|
topLeftCorner = borderImageNode->valueAt("top left corner", topLeftCorner);
|
||||||
topRightCorner = borderImageNode->readAt("top right corner", topRightCorner);
|
topRightCorner = borderImageNode->valueAt("top right corner", topRightCorner);
|
||||||
bottomLeftCorner = borderImageNode->readAt("bottom left corner", bottomLeftCorner);
|
bottomLeftCorner = borderImageNode->valueAt("bottom left corner", bottomLeftCorner);
|
||||||
bottomRightCorner = borderImageNode->readAt("bottom right corner", bottomRightCorner);
|
bottomRightCorner = borderImageNode->valueAt("bottom right corner", bottomRightCorner);
|
||||||
center = borderImageNode->readAt("center", center);
|
center = borderImageNode->valueAt("center", center);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return BorderImagePtr(new BorderImage(texture,
|
return BorderImagePtr(new BorderImage(texture,
|
||||||
|
|
|
@ -7,7 +7,6 @@ class Texture;
|
||||||
class Font;
|
class Font;
|
||||||
class Image;
|
class Image;
|
||||||
class BorderImage;
|
class BorderImage;
|
||||||
class TextArea;
|
|
||||||
class FrameBuffer;
|
class FrameBuffer;
|
||||||
|
|
||||||
typedef std::weak_ptr<Texture> TextureWeakPtr;
|
typedef std::weak_ptr<Texture> TextureWeakPtr;
|
||||||
|
@ -16,7 +15,6 @@ typedef std::shared_ptr<Texture> TexturePtr;
|
||||||
typedef std::shared_ptr<Font> FontPtr;
|
typedef std::shared_ptr<Font> FontPtr;
|
||||||
typedef std::shared_ptr<Image> ImagePtr;
|
typedef std::shared_ptr<Image> ImagePtr;
|
||||||
typedef std::shared_ptr<BorderImage> BorderImagePtr;
|
typedef std::shared_ptr<BorderImage> BorderImagePtr;
|
||||||
typedef std::shared_ptr<TextArea> TextAreaPtr;
|
|
||||||
typedef std::shared_ptr<FrameBuffer> FrameBufferPtr;
|
typedef std::shared_ptr<FrameBuffer> FrameBufferPtr;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,25 +6,25 @@
|
||||||
|
|
||||||
void Font::load(const OTMLNodePtr& fontNode)
|
void Font::load(const OTMLNodePtr& fontNode)
|
||||||
{
|
{
|
||||||
std::string textureName = fontNode->readAt<std::string>("texture");
|
std::string textureName = fontNode->valueAt("texture");
|
||||||
Size glyphSize = fontNode->readAt<Size>("glyph size");
|
Size glyphSize = fontNode->valueAt<Size>("glyph size");
|
||||||
m_glyphHeight = fontNode->readAt<int>("height");
|
m_glyphHeight = fontNode->valueAt<int>("height");
|
||||||
m_topMargin = fontNode->readAt("top margin", 0);
|
m_topMargin = fontNode->valueAt("top margin", 0);
|
||||||
m_firstGlyph = fontNode->readAt("first glyph", 32);
|
m_firstGlyph = fontNode->valueAt("first glyph", 32);
|
||||||
m_glyphSpacing = fontNode->readAt("spacing", Size(0,0));
|
m_glyphSpacing = fontNode->valueAt("spacing", Size(0,0));
|
||||||
|
|
||||||
// load font texture
|
// load font texture
|
||||||
m_texture = g_textures.getTexture(textureName);
|
m_texture = g_textures.getTexture(textureName);
|
||||||
if(!m_texture)
|
if(!m_texture)
|
||||||
throw OTMLException(fontNode, "failed to load texture for font");
|
throw std::runtime_error("failed to load texture for font");
|
||||||
|
|
||||||
// auto calculate widths
|
// auto calculate widths
|
||||||
calculateGlyphsWidthsAutomatically(glyphSize);
|
calculateGlyphsWidthsAutomatically(glyphSize);
|
||||||
|
|
||||||
// read custom widths
|
// read custom widths
|
||||||
if(OTMLNodePtr node = fontNode->get("glyph widths")) {
|
if(OTMLNodePtr node = fontNode->get("glyph widths")) {
|
||||||
for(const OTMLNodePtr& child : node->childNodes())
|
for(const OTMLNodePtr& child : node->children())
|
||||||
m_glyphsSize[fw::safe_cast<int>(child->tag())].setWidth(child->read<int>());
|
m_glyphsSize[fw::safe_cast<int>(child->tag())].setWidth(child->value<int>());
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate glyphs texture coords
|
// calculate glyphs texture coords
|
||||||
|
|
|
@ -20,9 +20,9 @@ bool FontManager::importFont(std::string fontFile)
|
||||||
OTMLDocumentPtr doc = OTMLDocument::parse(fontFile);
|
OTMLDocumentPtr doc = OTMLDocument::parse(fontFile);
|
||||||
OTMLNodePtr fontNode = doc->at("Font");
|
OTMLNodePtr fontNode = doc->at("Font");
|
||||||
|
|
||||||
std::string name = fontNode->readAt<std::string>("name");
|
std::string name = fontNode->valueAt("name");
|
||||||
if(fontExists(name))
|
if(fontExists(name))
|
||||||
throw OTMLException(fontNode, "a font with the same name is already imported, did you duplicate font names?");
|
throw std::runtime_error("a font with the same name is already imported, did you duplicate font names?");
|
||||||
|
|
||||||
FontPtr font(new Font(name));
|
FontPtr font(new Font(name));
|
||||||
font->load(fontNode);
|
font->load(fontNode);
|
||||||
|
@ -34,7 +34,7 @@ bool FontManager::importFont(std::string fontFile)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
logError("ERROR: could not load font '", fontFile, "': ", e.what());
|
logError("ERROR: could not load font from '", fontFile, "': ", e.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@ Image::Image(TexturePtr texture, Rect textureCoords)
|
||||||
ImagePtr Image::loadFromOTML(const OTMLNodePtr& imageNode)
|
ImagePtr Image::loadFromOTML(const OTMLNodePtr& imageNode)
|
||||||
{
|
{
|
||||||
// load configs from otml node
|
// load configs from otml node
|
||||||
std::string source = imageNode->hasValue() ? imageNode->read<std::string>() : imageNode->readAt<std::string>("source");
|
std::string source = imageNode->hasValue() ? imageNode->value() : imageNode->valueAt("source");
|
||||||
bool smooth = imageNode->readAt("smooth", false);
|
bool smooth = imageNode->valueAt("smooth", false);
|
||||||
Rect textureCoords = imageNode->readAt("coords", Rect());
|
Rect textureCoords = imageNode->valueAt("coords", Rect());
|
||||||
|
|
||||||
// load texture
|
// load texture
|
||||||
TexturePtr texture = g_textures.getTexture(source);
|
TexturePtr texture = g_textures.getTexture(source);
|
||||||
|
|
|
@ -24,7 +24,7 @@ TexturePtr TextureManager::getTexture(const std::string& textureFile)
|
||||||
try {
|
try {
|
||||||
// currently only png textures are supported
|
// currently only png textures are supported
|
||||||
if(!boost::ends_with(textureFile, ".png"))
|
if(!boost::ends_with(textureFile, ".png"))
|
||||||
throw std::logic_error("texture file format no supported");
|
throw std::runtime_error("texture file format no supported");
|
||||||
|
|
||||||
// load texture file data
|
// load texture file data
|
||||||
std::stringstream fin;
|
std::stringstream fin;
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace luabinder
|
||||||
/// C++ function caller that can push results to lua
|
/// C++ function caller that can push results to lua
|
||||||
template<typename Ret, typename F, typename... Args>
|
template<typename Ret, typename F, typename... Args>
|
||||||
typename std::enable_if<!std::is_void<Ret>::value, int>::type
|
typename std::enable_if<!std::is_void<Ret>::value, int>::type
|
||||||
call_fun_and_push_result(const F& f, LuaInterface* lua, Args... args) {
|
call_fun_and_push_result(const F& f, LuaInterface* lua, const Args&... args) {
|
||||||
Ret ret = f(args...);
|
Ret ret = f(args...);
|
||||||
lua->polymorphicPush(ret);
|
lua->polymorphicPush(ret);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -48,7 +48,7 @@ namespace luabinder
|
||||||
/// C++ void function caller
|
/// C++ void function caller
|
||||||
template<typename Ret, typename F, typename... Args>
|
template<typename Ret, typename F, typename... Args>
|
||||||
typename std::enable_if<std::is_void<Ret>::value, int>::type
|
typename std::enable_if<std::is_void<Ret>::value, int>::type
|
||||||
call_fun_and_push_result(const F& f, LuaInterface* lua, Args... args) {
|
call_fun_and_push_result(const F& f, LuaInterface* lua, const Args&... args) {
|
||||||
f(args...);
|
f(args...);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -57,14 +57,14 @@ namespace luabinder
|
||||||
template<int N, typename Ret>
|
template<int N, typename Ret>
|
||||||
struct expand_fun_arguments {
|
struct expand_fun_arguments {
|
||||||
template<typename Tuple, typename F, typename... Args>
|
template<typename Tuple, typename F, typename... Args>
|
||||||
static int call(const Tuple& tuple, const F& f, LuaInterface* lua, Args... args) {
|
static int call(const Tuple& tuple, const F& f, LuaInterface* lua, const Args&... args) {
|
||||||
return expand_fun_arguments<N-1,Ret>::call(tuple, f, lua, std::cref(std::get<N-1>(tuple)), args...);
|
return expand_fun_arguments<N-1,Ret>::call(tuple, f, lua, std::get<N-1>(tuple), args...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<typename Ret>
|
template<typename Ret>
|
||||||
struct expand_fun_arguments<0,Ret> {
|
struct expand_fun_arguments<0,Ret> {
|
||||||
template<typename Tuple, typename F, typename... Args>
|
template<typename Tuple, typename F, typename... Args>
|
||||||
static int call(const Tuple& tuple, const F& f, LuaInterface* lua, Args... args) {
|
static int call(const Tuple& tuple, const F& f, LuaInterface* lua, const Args&... args) {
|
||||||
return call_fun_and_push_result<Ret>(f, lua, args...);
|
return call_fun_and_push_result<Ret>(f, lua, args...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -178,7 +178,7 @@ namespace luabinder
|
||||||
template<typename Ret, typename Obj, typename... Args>
|
template<typename Ret, typename Obj, typename... Args>
|
||||||
LuaCppFunction bind_mem_fun(Ret (Obj::*f)(Args...)) {
|
LuaCppFunction bind_mem_fun(Ret (Obj::*f)(Args...)) {
|
||||||
auto mf = std::mem_fn(f);
|
auto mf = std::mem_fn(f);
|
||||||
typedef typename std::tuple<Obj*, typename remove_const_ref<Args>::type...> Tuple;
|
typedef typename std::tuple<std::shared_ptr<Obj>, typename remove_const_ref<Args>::type...> Tuple;
|
||||||
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
||||||
decltype(mf),
|
decltype(mf),
|
||||||
Tuple>(mf);
|
Tuple>(mf);
|
||||||
|
@ -186,7 +186,7 @@ namespace luabinder
|
||||||
template<typename Ret, typename Obj, typename... Args>
|
template<typename Ret, typename Obj, typename... Args>
|
||||||
LuaCppFunction bind_mem_fun(Ret (Obj::*f)(Args...) const) {
|
LuaCppFunction bind_mem_fun(Ret (Obj::*f)(Args...) const) {
|
||||||
auto mf = std::mem_fn(f);
|
auto mf = std::mem_fn(f);
|
||||||
typedef typename std::tuple<Obj*, typename remove_const_ref<Args>::type...> Tuple;
|
typedef typename std::tuple<std::shared_ptr<Obj>, typename remove_const_ref<Args>::type...> Tuple;
|
||||||
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
return bind_fun_specializer<typename remove_const_ref<Ret>::type,
|
||||||
decltype(mf),
|
decltype(mf),
|
||||||
Tuple>(mf);
|
Tuple>(mf);
|
||||||
|
@ -197,7 +197,7 @@ namespace luabinder
|
||||||
LuaCppFunction bind_mem_fun(int (Obj::*f)(LuaInterface*)) {
|
LuaCppFunction bind_mem_fun(int (Obj::*f)(LuaInterface*)) {
|
||||||
auto mf = std::mem_fn(f);
|
auto mf = std::mem_fn(f);
|
||||||
return [=](LuaInterface* lua) {
|
return [=](LuaInterface* lua) {
|
||||||
auto obj = lua->castValue<Obj*>(1);
|
auto obj = lua->castValue<std::shared_ptr<Obj>>(1);
|
||||||
lua->remove(1);
|
lua->remove(1);
|
||||||
return mf(obj, lua);
|
return mf(obj, lua);
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
#include "luavaluecasts.h"
|
||||||
|
#include "luainterface.h"
|
||||||
|
#include <framework/otml/otmlnode.h>
|
||||||
|
|
||||||
|
// bool
|
||||||
|
void push_luavalue(bool b)
|
||||||
|
{
|
||||||
|
g_lua.pushBoolean(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool luavalue_cast(int index, bool& b)
|
||||||
|
{
|
||||||
|
b = g_lua.toBoolean(index);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// int
|
||||||
|
void push_luavalue(int i)
|
||||||
|
{
|
||||||
|
g_lua.pushInteger(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool luavalue_cast(int index, int& i)
|
||||||
|
{
|
||||||
|
i = g_lua.toInteger(index);
|
||||||
|
if(i == 0 && !g_lua.isNumber(index))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// double
|
||||||
|
void push_luavalue(double d)
|
||||||
|
{
|
||||||
|
g_lua.pushNumber(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool luavalue_cast(int index, double& d)
|
||||||
|
{
|
||||||
|
d = g_lua.toNumber(index);
|
||||||
|
if(d == 0 && !g_lua.isNumber(index))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// string
|
||||||
|
void push_luavalue(const char* cstr)
|
||||||
|
{
|
||||||
|
g_lua.pushCString(cstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_luavalue(const std::string& str)
|
||||||
|
{
|
||||||
|
g_lua.pushString(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool luavalue_cast(int index, std::string& str)
|
||||||
|
{
|
||||||
|
str = g_lua.toString(index);
|
||||||
|
if(str.empty() && !g_lua.isString(index))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lua cpp function
|
||||||
|
void push_luavalue(const LuaCppFunction& func)
|
||||||
|
{
|
||||||
|
g_lua.pushCppFunction(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
// color
|
||||||
|
void push_luavalue(const Color& color)
|
||||||
|
{
|
||||||
|
g_lua.newTable();
|
||||||
|
g_lua.pushInteger(color.r());
|
||||||
|
g_lua.setField("r");
|
||||||
|
g_lua.pushInteger(color.g());
|
||||||
|
g_lua.setField("g");
|
||||||
|
g_lua.pushInteger(color.b());
|
||||||
|
g_lua.setField("b");
|
||||||
|
g_lua.pushInteger(color.a());
|
||||||
|
g_lua.setField("a");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool luavalue_cast(int index, Color& color)
|
||||||
|
{
|
||||||
|
if(g_lua.isTable(index)) {
|
||||||
|
g_lua.getField("r", index);
|
||||||
|
color.setRed(g_lua.popInteger());
|
||||||
|
g_lua.getField("g", index);
|
||||||
|
color.setGreen(g_lua.popInteger());
|
||||||
|
g_lua.getField("b", index);
|
||||||
|
color.setBlue(g_lua.popInteger());
|
||||||
|
g_lua.getField("a", index);
|
||||||
|
color.setAlpha(g_lua.popInteger());
|
||||||
|
return true;
|
||||||
|
} else if(g_lua.isString()) {
|
||||||
|
return fw::cast(g_lua.toString(index), color);
|
||||||
|
} else if(g_lua.isNil()) {
|
||||||
|
color = Color::white;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rect
|
||||||
|
void push_luavalue(const Rect& rect)
|
||||||
|
{
|
||||||
|
g_lua.newTable();
|
||||||
|
g_lua.pushInteger(rect.x());
|
||||||
|
g_lua.setField("x");
|
||||||
|
g_lua.pushInteger(rect.y());
|
||||||
|
g_lua.setField("y");
|
||||||
|
g_lua.pushInteger(rect.width());
|
||||||
|
g_lua.setField("width");
|
||||||
|
g_lua.pushInteger(rect.height());
|
||||||
|
g_lua.setField("height");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool luavalue_cast(int index, Rect& rect)
|
||||||
|
{
|
||||||
|
if(g_lua.isTable(index)) {
|
||||||
|
g_lua.getField("x", index);
|
||||||
|
rect.setX(g_lua.popInteger());
|
||||||
|
g_lua.getField("y", index);
|
||||||
|
rect.setY(g_lua.popInteger());
|
||||||
|
g_lua.getField("width", index);
|
||||||
|
rect.setWidth(g_lua.popInteger());
|
||||||
|
g_lua.getField("height", index);
|
||||||
|
rect.setHeight(g_lua.popInteger());
|
||||||
|
} else if(g_lua.isString()) {
|
||||||
|
return fw::cast(g_lua.toString(index), rect);
|
||||||
|
} else if(g_lua.isNil()) {
|
||||||
|
rect = Rect();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// point
|
||||||
|
void push_luavalue(const Point& point)
|
||||||
|
{
|
||||||
|
g_lua.newTable();
|
||||||
|
g_lua.pushInteger(point.x);
|
||||||
|
g_lua.setField("x");
|
||||||
|
g_lua.pushInteger(point.y);
|
||||||
|
g_lua.setField("y");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool luavalue_cast(int index, Point& point)
|
||||||
|
{
|
||||||
|
if(g_lua.isTable(index)) {
|
||||||
|
g_lua.getField("x", index);
|
||||||
|
point.x = g_lua.popInteger();
|
||||||
|
g_lua.getField("y", index);
|
||||||
|
point.y = g_lua.popInteger();
|
||||||
|
return true;
|
||||||
|
} else if(g_lua.isString()) {
|
||||||
|
return fw::cast(g_lua.toString(index), point);
|
||||||
|
} else if(g_lua.isNil()) {
|
||||||
|
point = Point();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otml nodes
|
||||||
|
void push_luavalue(const OTMLNodePtr& node)
|
||||||
|
{
|
||||||
|
if(node->hasValue()) {
|
||||||
|
g_lua.pushString(node->value());
|
||||||
|
} else if(node->hasChildren()) {
|
||||||
|
g_lua.newTable();
|
||||||
|
bool pushedChild = false;
|
||||||
|
for(const OTMLNodePtr& cnode : node->children()) {
|
||||||
|
if(cnode->isUnique()) {
|
||||||
|
push_luavalue(cnode);
|
||||||
|
if(!g_lua.isNil()) {
|
||||||
|
g_lua.setField(cnode->tag());
|
||||||
|
pushedChild = true;
|
||||||
|
} else
|
||||||
|
g_lua.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!pushedChild) {
|
||||||
|
g_lua.pop();
|
||||||
|
g_lua.pushNil();
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
g_lua.pushNil();
|
||||||
|
}
|
||||||
|
|
||||||
|
// object ptr
|
||||||
|
bool luavalue_cast(int index, LuaObjectPtr& obj) {
|
||||||
|
if(g_lua.isUserdata(index)) {
|
||||||
|
obj = g_lua.toObject(index);
|
||||||
|
return true;
|
||||||
|
} else if(g_lua.isNil(index)) {
|
||||||
|
obj = nullptr;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -2,137 +2,123 @@
|
||||||
#define LUAVALUECASTS_H
|
#define LUAVALUECASTS_H
|
||||||
|
|
||||||
// this file is and must be included only from luainterface.h
|
// this file is and must be included only from luainterface.h
|
||||||
#include "luainterface.h"
|
|
||||||
#include "luaexception.h"
|
|
||||||
|
|
||||||
/// Pushes bool
|
#include "declarations.h"
|
||||||
inline void push_luavalue(bool v) {
|
#include <framework/otml/declarations.h>
|
||||||
g_lua.pushBoolean(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Pushes int
|
// bool
|
||||||
inline void push_luavalue(int v) {
|
void push_luavalue(bool b);
|
||||||
g_lua.pushInteger(v);
|
bool luavalue_cast(int index, bool& b);
|
||||||
}
|
|
||||||
|
|
||||||
/// Pushes double
|
// int
|
||||||
inline void push_luavalue(double v) {
|
void push_luavalue(int i);
|
||||||
g_lua.pushNumber(v);
|
bool luavalue_cast(int index, int& i);
|
||||||
}
|
|
||||||
|
|
||||||
/// Pushes std::string
|
// double
|
||||||
inline void push_luavalue(const std::string& v) {
|
void push_luavalue(double d);
|
||||||
g_lua.pushString(v);
|
bool luavalue_cast(int index, double& d);
|
||||||
}
|
|
||||||
|
|
||||||
/// Pushes const char*
|
// string
|
||||||
inline void push_luavalue(const char* v) {
|
void push_luavalue(const char* cstr);
|
||||||
g_lua.pushCString(v);
|
void push_luavalue(const std::string& str);
|
||||||
}
|
bool luavalue_cast(int index, std::string& str);
|
||||||
|
|
||||||
/// Pushes LuaCppFunction
|
// lua cpp function
|
||||||
inline void push_luavalue(const LuaCppFunction& v) {
|
void push_luavalue(const LuaCppFunction& func);
|
||||||
g_lua.pushCppFunction(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Pushes LuaObjectPtr
|
// color
|
||||||
|
void push_luavalue(const Color& color);
|
||||||
|
bool luavalue_cast(int index, Color& color);
|
||||||
|
|
||||||
|
// rect
|
||||||
|
void push_luavalue(const Rect& rect);
|
||||||
|
bool luavalue_cast(int index, Rect& rect);
|
||||||
|
|
||||||
|
// point
|
||||||
|
void push_luavalue(const Point& point);
|
||||||
|
bool luavalue_cast(int index, Point& point);
|
||||||
|
|
||||||
|
// size
|
||||||
|
void push_luavalue(const Size& size);
|
||||||
|
bool luavalue_cast(int index, Size& size);
|
||||||
|
|
||||||
|
// otml nodes
|
||||||
|
void push_luavalue(const OTMLNodePtr& node);
|
||||||
|
|
||||||
|
// enum
|
||||||
|
template<class T>
|
||||||
|
typename std::enable_if<std::is_enum<T>::value, bool>::type
|
||||||
|
luavalue_cast(int index, T& myenum);
|
||||||
|
|
||||||
|
// LuaObject pointers
|
||||||
template<class T>
|
template<class T>
|
||||||
typename std::enable_if<std::is_base_of<LuaObject, typename T::element_type>::value, void>::type
|
typename std::enable_if<std::is_base_of<LuaObject, typename T::element_type>::value, void>::type
|
||||||
push_luavalue(const T& v) {
|
push_luavalue(const T& obj);
|
||||||
if(v)
|
|
||||||
return g_lua.pushObject(v);
|
bool luavalue_cast(int index, LuaObjectPtr& obj);
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
typename std::enable_if<std::is_base_of<LuaObject, T>::value, bool>::type
|
||||||
|
luavalue_cast(int index, std::shared_ptr<T>& ptr);
|
||||||
|
|
||||||
|
// std::function
|
||||||
|
template<typename Ret, typename... Args>
|
||||||
|
void push_luavalue(const std::function<Ret(Args...)>& func);
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
bool luavalue_cast(int index, std::function<void(Args...)>& func);
|
||||||
|
|
||||||
|
template<typename Ret, typename... Args>
|
||||||
|
typename std::enable_if<!std::is_void<Ret>::value, bool>::type
|
||||||
|
luavalue_cast(int index, std::function<Ret(Args...)>& func);
|
||||||
|
|
||||||
|
|
||||||
|
// start definitions
|
||||||
|
|
||||||
|
#include "luaexception.h"
|
||||||
|
#include "luainterface.h"
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
typename std::enable_if<std::is_enum<T>::value, bool>::type
|
||||||
|
luavalue_cast(int index, T& myenum) {
|
||||||
|
return luavalue_cast(index, (int&)myenum);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
typename std::enable_if<std::is_base_of<LuaObject, typename T::element_type>::value, void>::type
|
||||||
|
push_luavalue(const T& obj) {
|
||||||
|
if(obj)
|
||||||
|
return g_lua.pushObject(obj);
|
||||||
return g_lua.pushNil();
|
return g_lua.pushNil();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push std::function types
|
template<class T>
|
||||||
|
typename std::enable_if<std::is_base_of<LuaObject, T>::value, bool>::type
|
||||||
|
luavalue_cast(int index, std::shared_ptr<T>& ptr) {
|
||||||
|
LuaObjectPtr obj;
|
||||||
|
if(!luavalue_cast(index, obj))
|
||||||
|
return false;
|
||||||
|
ptr = std::dynamic_pointer_cast<T>(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Ret, typename... Args>
|
template<typename Ret, typename... Args>
|
||||||
void push_luavalue(const std::function<Ret(Args...)>& v) {
|
void push_luavalue(const std::function<Ret(Args...)>& func) {
|
||||||
if(v) {
|
if(func) {
|
||||||
LuaCppFunction f = luabinder::bind_fun(v);
|
LuaCppFunction f = luabinder::bind_fun(func);
|
||||||
g_lua.pushCppFunction(f);
|
g_lua.pushCppFunction(f);
|
||||||
} else
|
} else
|
||||||
g_lua.pushNil();
|
g_lua.pushNil();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Casts lua value to bool
|
|
||||||
inline bool luavalue_cast(int index, bool& o) {
|
|
||||||
o = g_lua.toBoolean(index);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Casts lua value to int
|
|
||||||
inline bool luavalue_cast(int index, int& o) {
|
|
||||||
o = g_lua.toInteger(index);
|
|
||||||
if(o == 0 && !g_lua.isNumber(index))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Casts lua value to double
|
|
||||||
inline bool luavalue_cast(int index, double& o) {
|
|
||||||
o = g_lua.toNumber(index);
|
|
||||||
if(o == 0 && !g_lua.isNumber(index))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Casts lua value to std::string
|
|
||||||
inline bool luavalue_cast(int index, std::string& o) {
|
|
||||||
o = g_lua.toString(index);
|
|
||||||
if(o.empty() && !g_lua.isString(index))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Casts lua value to LuaObjectPtr
|
|
||||||
inline bool luavalue_cast(int index, LuaObjectPtr& o) {
|
|
||||||
if(g_lua.isUserdata(index)) {
|
|
||||||
o = g_lua.toObject(index);
|
|
||||||
return true;
|
|
||||||
} else if(g_lua.isNil(index)) {
|
|
||||||
o = nullptr;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Casts lua value to enum
|
|
||||||
template<class T>
|
|
||||||
typename std::enable_if<std::is_enum<T>::value, bool>::type
|
|
||||||
luavalue_cast(int index, T& o) {
|
|
||||||
return luavalue_cast(index, (int&)o);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Cast lua userdata to a class pointer
|
|
||||||
template<class T>
|
|
||||||
typename std::enable_if<std::is_base_of<LuaObject, T>::value, bool>::type
|
|
||||||
luavalue_cast(int index, T*& o) {
|
|
||||||
LuaObjectPtr obj;
|
|
||||||
if(!luavalue_cast(index, obj))
|
|
||||||
return false;
|
|
||||||
o = std::dynamic_pointer_cast<T>(obj).get();
|
|
||||||
return !!o;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Cast lua userdata to a class shared pointer
|
|
||||||
template<class T>
|
|
||||||
bool luavalue_cast(int index, std::shared_ptr<T>& o) {
|
|
||||||
LuaObjectPtr obj;
|
|
||||||
if(!luavalue_cast(index, obj))
|
|
||||||
return false;
|
|
||||||
o = std::dynamic_pointer_cast<T>(obj);
|
|
||||||
return !!o;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Cast a lua function to a std::function
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
bool luavalue_cast(int index, std::function<void(Args...)>& o) {
|
bool luavalue_cast(int index, std::function<void(Args...)>& func) {
|
||||||
if(g_lua.isFunction(index)) {
|
if(g_lua.isFunction(index)) {
|
||||||
g_lua.pushValue(index);
|
g_lua.pushValue(index);
|
||||||
// weak references are used here, this means that the script must hold another reference
|
// weak references are used here, this means that the script must hold another reference
|
||||||
// to this function, otherwise it will expire
|
// to this function, otherwise it will expire
|
||||||
int funcWeakRef = g_lua.weakRef();
|
int funcWeakRef = g_lua.weakRef();
|
||||||
o = [=](Args... args...) {
|
func = [=](Args... args...) {
|
||||||
// note that we must catch exceptions, because this lambda can be called from anywhere
|
// note that we must catch exceptions, because this lambda can be called from anywhere
|
||||||
// and most of them won't catch exceptions (e.g. dispatcher)
|
// and most of them won't catch exceptions (e.g. dispatcher)
|
||||||
g_lua.getWeakRef(funcWeakRef);
|
g_lua.getWeakRef(funcWeakRef);
|
||||||
|
@ -150,22 +136,21 @@ bool luavalue_cast(int index, std::function<void(Args...)>& o) {
|
||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
} else if(g_lua.isNil(index)) {
|
} else if(g_lua.isNil(index)) {
|
||||||
o = std::function<void(Args...)>();
|
func = std::function<void(Args...)>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cast a lua function to a std::function that can return
|
|
||||||
template<typename Ret, typename... Args>
|
template<typename Ret, typename... Args>
|
||||||
typename std::enable_if<!std::is_void<Ret>::value, bool>::type
|
typename std::enable_if<!std::is_void<Ret>::value, bool>::type
|
||||||
luavalue_cast(int index, std::function<Ret(Args...)>& o) {
|
luavalue_cast(int index, std::function<Ret(Args...)>& func) {
|
||||||
if(g_lua.isFunction(index)) {
|
if(g_lua.isFunction(index)) {
|
||||||
g_lua.pushValue(index);
|
g_lua.pushValue(index);
|
||||||
// weak references are used here, this means that the script must hold another reference
|
// weak references are used here, this means that the script must hold another reference
|
||||||
// to this function, otherwise it will expire
|
// to this function, otherwise it will expire
|
||||||
int funcWeakRef = g_lua.weakRef();
|
int funcWeakRef = g_lua.weakRef();
|
||||||
o = [=](Args... args...) -> Ret {
|
func = [=](Args... args...) -> Ret {
|
||||||
// note that we must catch exceptions, because this lambda can be called from anywhere
|
// note that we must catch exceptions, because this lambda can be called from anywhere
|
||||||
// and most of them won't catch exceptions (e.g. dispatcher)
|
// and most of them won't catch exceptions (e.g. dispatcher)
|
||||||
try {
|
try {
|
||||||
|
@ -186,40 +171,10 @@ luavalue_cast(int index, std::function<Ret(Args...)>& o) {
|
||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
} else if(g_lua.isNil(index)) {
|
} else if(g_lua.isNil(index)) {
|
||||||
o = std::function<Ret(Args...)>();
|
func = std::function<Ret(Args...)>();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// additional casts
|
|
||||||
|
|
||||||
|
|
||||||
inline void push_luavalue(const Color& v) {
|
|
||||||
g_lua.newTable();
|
|
||||||
g_lua.pushInteger(v.r());
|
|
||||||
g_lua.setField("r");
|
|
||||||
g_lua.pushInteger(v.g());
|
|
||||||
g_lua.setField("g");
|
|
||||||
g_lua.pushInteger(v.b());
|
|
||||||
g_lua.setField("b");
|
|
||||||
g_lua.pushInteger(v.a());
|
|
||||||
g_lua.setField("a");
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool luavalue_cast(int index, Color& o) {
|
|
||||||
if(!g_lua.isTable(index))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
g_lua.getField("r", index);
|
|
||||||
o.setRed(g_lua.popInteger());
|
|
||||||
g_lua.getField("g", index);
|
|
||||||
o.setGreen(g_lua.popInteger());
|
|
||||||
g_lua.getField("b", index);
|
|
||||||
o.setBlue(g_lua.popInteger());
|
|
||||||
g_lua.getField("a", index);
|
|
||||||
o.setAlpha(g_lua.popInteger());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,6 +3,5 @@
|
||||||
|
|
||||||
#include "otmldocument.h"
|
#include "otmldocument.h"
|
||||||
#include "otmlnode.h"
|
#include "otmlnode.h"
|
||||||
#include "otmlnodeext.h"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -15,7 +15,7 @@ OTMLDocumentPtr OTMLDocument::parse(const std::string& fileName)
|
||||||
{
|
{
|
||||||
std::stringstream fin;
|
std::stringstream fin;
|
||||||
g_resources.loadFile(fileName, fin);
|
g_resources.loadFile(fileName, fin);
|
||||||
return parse(fin, fileName);
|
return parse(fin, g_resources.resolvePath(fileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
OTMLDocumentPtr OTMLDocument::parse(std::istream& in, const std::string& source)
|
OTMLDocumentPtr OTMLDocument::parse(std::istream& in, const std::string& source)
|
||||||
|
@ -34,8 +34,7 @@ std::string OTMLDocument::emit()
|
||||||
|
|
||||||
bool OTMLDocument::save(const std::string& fileName)
|
bool OTMLDocument::save(const std::string& fileName)
|
||||||
{
|
{
|
||||||
setSource(fileName);
|
m_source = fileName;
|
||||||
|
|
||||||
return g_resources.saveFile(fileName, emit());
|
return g_resources.saveFile(fileName, emit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,13 +16,15 @@ std::string OTMLEmitter::emitNode(const OTMLNodePtr& node, int currentDepth)
|
||||||
ss << node->tag();
|
ss << node->tag();
|
||||||
|
|
||||||
// add ':' to if the node is unique or has value
|
// add ':' to if the node is unique or has value
|
||||||
if(node->hasValue() || node->isUnique())
|
if(node->hasValue() || node->isUnique() || node->isNull())
|
||||||
ss << ":";
|
ss << ":";
|
||||||
} else
|
} else
|
||||||
ss << "-";
|
ss << "-";
|
||||||
|
|
||||||
// emit node value
|
// emit node value
|
||||||
if(node->hasValue()) {
|
if(node->isNull())
|
||||||
|
ss << " ~";
|
||||||
|
else if(node->hasValue()) {
|
||||||
ss << " ";
|
ss << " ";
|
||||||
|
|
||||||
std::string value = node->value();
|
std::string value = node->value();
|
||||||
|
@ -61,7 +63,7 @@ std::string OTMLEmitter::emitNode(const OTMLNodePtr& node, int currentDepth)
|
||||||
for(int i=0;i<node->size();++i) {
|
for(int i=0;i<node->size();++i) {
|
||||||
if(currentDepth >= 0 || i != 0)
|
if(currentDepth >= 0 || i != 0)
|
||||||
ss << "\n";
|
ss << "\n";
|
||||||
ss << emitNode(node->at(i), currentDepth+1);
|
ss << emitNode(node->atIndex(i), currentDepth+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
|
|
@ -14,9 +14,6 @@ public:
|
||||||
virtual const char* what() const throw() { return m_what.c_str(); }
|
virtual const char* what() const throw() { return m_what.c_str(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
OTMLException() { }
|
|
||||||
void generateErrorMessage(const OTMLDocumentPtr& doc, const std::string& error, int line);
|
|
||||||
void generateErrorMessage(const OTMLNodePtr& node, const std::string& error);
|
|
||||||
std::string m_what;
|
std::string m_what;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,157 +2,86 @@
|
||||||
#include "otmlemitter.h"
|
#include "otmlemitter.h"
|
||||||
#include "otmldocument.h"
|
#include "otmldocument.h"
|
||||||
|
|
||||||
OTMLNode::OTMLNode()
|
OTMLNodePtr OTMLNode::create(std::string tag, bool unique)
|
||||||
{
|
{
|
||||||
m_unique = false;
|
OTMLNodePtr node(new OTMLNode);
|
||||||
|
node->setTag(tag);
|
||||||
|
node->setUnique(unique);
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string OTMLNode::tag() const
|
OTMLNodePtr OTMLNode::create(std::string tag, std::string value)
|
||||||
{
|
{
|
||||||
return m_tag;
|
OTMLNodePtr node(new OTMLNode);
|
||||||
|
node->setTag(tag);
|
||||||
|
node->setValue(value);
|
||||||
|
node->setUnique(true);
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string OTMLNode::value() const
|
bool OTMLNode::hasChildren() const
|
||||||
{
|
{
|
||||||
// ~ is an alias for no value
|
int count = 0;
|
||||||
if(m_value == "~")
|
for(const OTMLNodePtr& child : m_children) {
|
||||||
return fw::empty_string;
|
if(!child->isNull())
|
||||||
return m_value;
|
count++;
|
||||||
}
|
|
||||||
|
|
||||||
int OTMLNode::size() const
|
|
||||||
{
|
|
||||||
return m_childNodes.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
OTMLNodePtr OTMLNode::parent() const
|
|
||||||
{
|
|
||||||
return m_parent.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
const OTMLNodeList& OTMLNode::childNodes() const
|
|
||||||
{
|
|
||||||
return m_childNodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string OTMLNode::source() const
|
|
||||||
{
|
|
||||||
return m_source;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OTMLNode::hasTag() const
|
|
||||||
{
|
|
||||||
return !m_tag.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OTMLNode::hasValue() const
|
|
||||||
{
|
|
||||||
return (!m_value.empty() && m_value != "~");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OTMLNode::hasChildNodes() const
|
|
||||||
{
|
|
||||||
return size() > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OTMLNode::hasChild(const std::string& childTag) const
|
|
||||||
{
|
|
||||||
return !!get(childTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OTMLNode::hasChild(int index) const
|
|
||||||
{
|
|
||||||
return !!get(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OTMLNode::isUnique() const
|
|
||||||
{
|
|
||||||
return m_unique;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OTMLNode::setTag(std::string tag)
|
|
||||||
{
|
|
||||||
m_tag = tag;
|
|
||||||
|
|
||||||
// valued nodes that has tags are always unique
|
|
||||||
if(!m_value.empty() && hasTag())
|
|
||||||
setUnique();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OTMLNode::setValue(const std::string& value)
|
|
||||||
{
|
|
||||||
m_value = value;
|
|
||||||
|
|
||||||
// valued nodes that has tags are always unique
|
|
||||||
if(!m_value.empty() && hasTag())
|
|
||||||
setUnique();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OTMLNode::setParent(const OTMLNodePtr& parent)
|
|
||||||
{
|
|
||||||
m_parent = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OTMLNode::setUnique(bool unique)
|
|
||||||
{
|
|
||||||
m_unique = unique;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OTMLNode::setSource(const std::string& source)
|
|
||||||
{
|
|
||||||
m_source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
OTMLNodePtr OTMLNode::at(const std::string& childTag)
|
|
||||||
{
|
|
||||||
for(const OTMLNodePtr& child : m_childNodes) {
|
|
||||||
if(child->tag() == childTag)
|
|
||||||
return child;
|
|
||||||
}
|
}
|
||||||
throw OTMLException(shared_from_this(), fw::mkstr("child node with tag '", childTag, "' not found"));
|
return count > 0;
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
OTMLNodePtr OTMLNode::at(int childIndex)
|
|
||||||
{
|
|
||||||
if(childIndex < size() && childIndex >= 0)
|
|
||||||
return m_childNodes[childIndex];
|
|
||||||
throw OTMLException(shared_from_this(), fw::mkstr("child node at index '", childIndex, "' not found"));
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OTMLNodePtr OTMLNode::get(const std::string& childTag) const
|
OTMLNodePtr OTMLNode::get(const std::string& childTag) const
|
||||||
{
|
{
|
||||||
for(const OTMLNodePtr& child : m_childNodes) {
|
for(const OTMLNodePtr& child : m_children) {
|
||||||
if(child->tag() == childTag)
|
if(child->tag() == childTag && !child->isNull())
|
||||||
return child;
|
return child;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
OTMLNodePtr OTMLNode::get(int childIndex) const
|
OTMLNodePtr OTMLNode::getIndex(int childIndex) const
|
||||||
{
|
{
|
||||||
if(childIndex < size() && childIndex >= 0)
|
if(childIndex < size() && childIndex >= 0)
|
||||||
return m_childNodes[childIndex];
|
return m_children[childIndex];
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OTMLNodePtr OTMLNode::at(const std::string& childTag)
|
||||||
|
{
|
||||||
|
OTMLNodePtr res;
|
||||||
|
for(const OTMLNodePtr& child : m_children) {
|
||||||
|
if(child->tag() == childTag && !child->isNull()) {
|
||||||
|
res = child;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!res)
|
||||||
|
throw OTMLException(shared_from_this(), fw::mkstr("child node with tag '", childTag, "' not found"));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
OTMLNodePtr OTMLNode::atIndex(int childIndex)
|
||||||
|
{
|
||||||
|
if(childIndex >= size() || childIndex < 0)
|
||||||
|
throw OTMLException(shared_from_this(), fw::mkstr("child node with index '", childIndex, "' not found"));
|
||||||
|
return m_children[childIndex];
|
||||||
|
}
|
||||||
|
|
||||||
void OTMLNode::addChild(const OTMLNodePtr& newChild)
|
void OTMLNode::addChild(const OTMLNodePtr& newChild)
|
||||||
{
|
{
|
||||||
// replace is needed when the tag is marked as unique
|
// replace is needed when the tag is marked as unique
|
||||||
if(newChild->hasTag()) {
|
if(newChild->hasTag()) {
|
||||||
for(OTMLNodePtr node : m_childNodes) {
|
for(const OTMLNodePtr& node : m_children) {
|
||||||
if(node->tag() == newChild->tag() && (node->isUnique() || newChild->isUnique())) {
|
if(node->tag() == newChild->tag() && (node->isUnique() || newChild->isUnique())) {
|
||||||
newChild->setUnique();
|
newChild->setUnique(true);
|
||||||
replaceChild(node, newChild);
|
replaceChild(node, newChild);
|
||||||
|
|
||||||
// remove any other child with the same tag
|
// remove any other child with the same tag
|
||||||
auto it = m_childNodes.begin();
|
auto it = m_children.begin();
|
||||||
while(it != m_childNodes.end()) {
|
while(it != m_children.end()) {
|
||||||
OTMLNodePtr node = (*it);
|
OTMLNodePtr node = (*it);
|
||||||
if(node != newChild && node->tag() == newChild->tag()) {
|
if(node != newChild && node->tag() == newChild->tag()) {
|
||||||
node->setParent(nullptr);
|
node->setParent(nullptr);
|
||||||
it = m_childNodes.erase(it);
|
it = m_children.erase(it);
|
||||||
} else
|
} else
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
@ -161,60 +90,67 @@ void OTMLNode::addChild(const OTMLNodePtr& newChild)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_childNodes.push_back(newChild);
|
m_children.push_back(newChild);
|
||||||
newChild->setParent(shared_from_this());
|
newChild->setParent(shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OTMLNode::removeChild(const OTMLNodePtr& oldChild)
|
bool OTMLNode::removeChild(const OTMLNodePtr& oldChild)
|
||||||
{
|
{
|
||||||
for(auto it = m_childNodes.begin(); it != m_childNodes.end(); ++it) {
|
auto it = std::find(m_children.begin(), m_children.end(), oldChild);
|
||||||
if((*it) == oldChild) {
|
if(it != m_children.end()) {
|
||||||
m_childNodes.erase(it);
|
m_children.erase(it);
|
||||||
oldChild->setParent(nullptr);
|
oldChild->setParent(nullptr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OTMLNode::replaceChild(const OTMLNodePtr& oldChild, const OTMLNodePtr& newChild)
|
bool OTMLNode::replaceChild(const OTMLNodePtr& oldChild, const OTMLNodePtr& newChild)
|
||||||
{
|
{
|
||||||
for(auto it = m_childNodes.begin(); it != m_childNodes.end(); ++it) {
|
auto it = std::find(m_children.begin(), m_children.end(), oldChild);
|
||||||
if((*it) == oldChild) {
|
if(it != m_children.end()) {
|
||||||
oldChild->setParent(nullptr);
|
oldChild->setParent(nullptr);
|
||||||
newChild->setParent(shared_from_this());
|
newChild->setParent(shared_from_this());
|
||||||
it = m_childNodes.erase(it);
|
it = m_children.erase(it);
|
||||||
m_childNodes.insert(it, newChild);
|
m_children.insert(it, newChild);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OTMLNode::clear()
|
|
||||||
{
|
|
||||||
m_childNodes.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void OTMLNode::merge(const OTMLNodePtr& node)
|
void OTMLNode::merge(const OTMLNodePtr& node)
|
||||||
{
|
{
|
||||||
for(const OTMLNodePtr& child : node->childNodes()) {
|
for(const OTMLNodePtr& child : node->m_children)
|
||||||
OTMLNodePtr newNode(new OTMLNode);
|
addChild(child->clone());
|
||||||
newNode->setUnique(child->isUnique());
|
setTag(node->tag());
|
||||||
newNode->setTag(child->tag());
|
setSource(node->source());
|
||||||
newNode->setValue(child->value());
|
}
|
||||||
addChild(newNode);
|
|
||||||
newNode->merge(child);
|
void OTMLNode::clear()
|
||||||
}
|
{
|
||||||
|
for(const OTMLNodePtr& child : m_children)
|
||||||
|
child->setParent(nullptr);
|
||||||
|
m_children.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
OTMLNodeList OTMLNode::children() const
|
||||||
|
{
|
||||||
|
OTMLNodeList children;
|
||||||
|
for(const OTMLNodePtr& child : m_children)
|
||||||
|
if(!child->isNull())
|
||||||
|
children.push_back(child);
|
||||||
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
OTMLNodePtr OTMLNode::clone() const
|
OTMLNodePtr OTMLNode::clone() const
|
||||||
{
|
{
|
||||||
OTMLNodePtr myClone(new OTMLNode);
|
OTMLNodePtr myClone(new OTMLNode);
|
||||||
myClone->setTag(tag());
|
myClone->setTag(m_tag);
|
||||||
myClone->setValue(value());
|
myClone->setValue(m_value);
|
||||||
myClone->setUnique(isUnique());
|
myClone->setUnique(m_unique);
|
||||||
for(OTMLNodePtr child : childNodes())
|
myClone->setNull(m_null);
|
||||||
|
myClone->setSource(m_source);
|
||||||
|
for(const OTMLNodePtr& child : m_children)
|
||||||
myClone->addChild(child->clone());
|
myClone->addChild(child->clone());
|
||||||
return myClone;
|
return myClone;
|
||||||
}
|
}
|
||||||
|
@ -223,3 +159,4 @@ std::string OTMLNode::emit()
|
||||||
{
|
{
|
||||||
return OTMLEmitter::emitNode(shared_from_this(), 0);
|
return OTMLEmitter::emitNode(shared_from_this(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,214 +2,138 @@
|
||||||
#define OTMLNODE_H
|
#define OTMLNODE_H
|
||||||
|
|
||||||
#include "declarations.h"
|
#include "declarations.h"
|
||||||
#include "otmlexception.h"
|
|
||||||
|
|
||||||
class OTMLNode : public std::enable_shared_from_this<OTMLNode>
|
class OTMLNode : public std::enable_shared_from_this<OTMLNode>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
OTMLNode();
|
|
||||||
virtual ~OTMLNode() { }
|
virtual ~OTMLNode() { }
|
||||||
|
|
||||||
std::string value() const;
|
static OTMLNodePtr create(std::string tag = fw::empty_string, bool unique = false);
|
||||||
std::string tag() const;
|
static OTMLNodePtr create(std::string tag, std::string value);
|
||||||
int size() const;
|
|
||||||
OTMLNodePtr parent() const;
|
|
||||||
const OTMLNodeList& childNodes() const;
|
|
||||||
std::string source() const;
|
|
||||||
|
|
||||||
bool hasTag() const;
|
std::string tag() const { return m_tag; }
|
||||||
bool hasValue() const;
|
int size() const { return m_children.size(); }
|
||||||
bool hasChildNodes() const;
|
OTMLNodePtr parent() const { return m_parent.lock(); }
|
||||||
bool hasChild(const std::string& childTag) const;
|
std::string source() const { return m_source; }
|
||||||
bool hasChild(int index) const;
|
|
||||||
bool isUnique() const;
|
|
||||||
|
|
||||||
void setTag(std::string tag);
|
bool isUnique() const { return m_unique; }
|
||||||
void setValue(const std::string& value);
|
bool isNull() const { return m_null; }
|
||||||
void setParent(const OTMLNodePtr& parent);
|
|
||||||
void setUnique(bool unique = true);
|
|
||||||
void setSource(const std::string& source);
|
|
||||||
|
|
||||||
/// Same as get but if the child node doesn't exist throws an OTMLException
|
bool hasTag() const { return !m_tag.empty(); }
|
||||||
OTMLNodePtr at(const std::string& childTag);
|
bool hasValue() const { return !m_value.empty(); }
|
||||||
OTMLNodePtr at(int childIndex);
|
bool hasChildren() const;
|
||||||
|
bool hasChildAt(const std::string& childTag) { return !!get(childTag); }
|
||||||
|
bool hasChildAtIndex(int childIndex) { return !!getIndex(childIndex); }
|
||||||
|
|
||||||
|
void setTag(std::string tag) { m_tag = tag; }
|
||||||
|
void setValue(const std::string& value) { m_value = value; }
|
||||||
|
void setNull(bool null) { m_null = null; }
|
||||||
|
void setUnique(bool unique) { m_unique = unique; }
|
||||||
|
void setParent(const OTMLNodePtr& parent) { m_parent = parent; }
|
||||||
|
void setSource(const std::string& source) { m_source = source; }
|
||||||
|
|
||||||
/// Get a child node, if doesn't exists returns nullptr
|
|
||||||
OTMLNodePtr get(const std::string& childTag) const;
|
OTMLNodePtr get(const std::string& childTag) const;
|
||||||
OTMLNodePtr get(int childIndex) const;
|
OTMLNodePtr getIndex(int childIndex) const;
|
||||||
|
|
||||||
|
OTMLNodePtr at(const std::string& childTag);
|
||||||
|
OTMLNodePtr atIndex(int childIndex);
|
||||||
|
|
||||||
void addChild(const OTMLNodePtr& newChild);
|
void addChild(const OTMLNodePtr& newChild);
|
||||||
bool removeChild(const OTMLNodePtr& oldChild);
|
bool removeChild(const OTMLNodePtr& oldChild);
|
||||||
bool replaceChild(const OTMLNodePtr& oldChild, const OTMLNodePtr& newChild);
|
bool replaceChild(const OTMLNodePtr& oldChild, const OTMLNodePtr& newChild);
|
||||||
|
void merge(const OTMLNodePtr& node);
|
||||||
/// Remove all children
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
/// Recursively copy children from another node to this node
|
OTMLNodeList children() const;
|
||||||
void merge(const OTMLNodePtr& node);
|
|
||||||
|
|
||||||
/// Recursively clone this node into a new one
|
|
||||||
OTMLNodePtr clone() const;
|
OTMLNodePtr clone() const;
|
||||||
|
|
||||||
/// Emits this node to a std::string
|
template<typename T = std::string>
|
||||||
virtual std::string emit();
|
T value();
|
||||||
|
template<typename T = std::string>
|
||||||
template<typename T>
|
T valueAt(const std::string& childTag);
|
||||||
T read();
|
template<typename T = std::string>
|
||||||
|
T valueAtIndex(int childIndex);
|
||||||
template<typename T>
|
template<typename T = std::string>
|
||||||
T read(const T& def);
|
T valueAt(const std::string& childTag, const T& def);
|
||||||
|
template<typename T = std::string>
|
||||||
template<typename T, typename U>
|
T valueAtIndex(int childIndex, const T& def);
|
||||||
T readAt(const U& childIdentifier);
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
T readAt(const U& childIdentifier, const T& def);
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void write(const T& v);
|
void write(const T& v);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void writeAt(const std::string& childTag, const T& v);
|
void writeAt(const std::string& childTag, const T& v);
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void writeIn(const T& v);
|
void writeIn(const T& v);
|
||||||
|
|
||||||
private:
|
virtual std::string emit();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
OTMLNode() : m_unique(false), m_null(false) { }
|
||||||
|
|
||||||
|
OTMLNodeList m_children;
|
||||||
|
OTMLNodeWeakPtr m_parent;
|
||||||
std::string m_tag;
|
std::string m_tag;
|
||||||
std::string m_value;
|
std::string m_value;
|
||||||
std::string m_source;
|
std::string m_source;
|
||||||
bool m_unique;
|
bool m_unique;
|
||||||
OTMLNodeList m_childNodes;
|
bool m_null;
|
||||||
OTMLNodeWeakPtr m_parent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// templates for reading values
|
#include "otmlexception.h"
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T OTMLNode::read() {
|
T OTMLNode::value() {
|
||||||
T v;
|
T ret;
|
||||||
if(!from_otmlnode(shared_from_this(), v))
|
if(!fw::cast(m_value, ret))
|
||||||
throw OTMLException(shared_from_this(),
|
throw OTMLException(shared_from_this(), fw::mkstr("failed to cast node value to type '", fw::demangle_type<T>(), "'"));
|
||||||
fw::mkstr("failed to cast node value to type '", fw::demangle_type<T>(), "'"));
|
return ret;
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T OTMLNode::read(const T& def) {
|
T OTMLNode::valueAt(const std::string& childTag) {
|
||||||
if(hasValue())
|
OTMLNodePtr node = at(childTag);
|
||||||
return read<T>();
|
return node->value<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T OTMLNode::valueAtIndex(int childIndex) {
|
||||||
|
OTMLNodePtr node = atIndex(childIndex);
|
||||||
|
return node->value<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T OTMLNode::valueAt(const std::string& childTag, const T& def) {
|
||||||
|
if(OTMLNodePtr node = get(childTag))
|
||||||
|
if(!node->isNull())
|
||||||
|
return node->value<T>();
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename U>
|
template<typename T>
|
||||||
T OTMLNode::readAt(const U& childIdentifier) {
|
T OTMLNode::valueAtIndex(int childIndex, const T& def) {
|
||||||
OTMLNodePtr child = at(childIdentifier);
|
if(OTMLNodePtr node = getIndex(childIndex))
|
||||||
return child->read<T>();
|
return node->value<T>();
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename U>
|
|
||||||
T OTMLNode::readAt(const U& childIdentifier, const T& def) {
|
|
||||||
OTMLNodePtr child = get(childIdentifier);
|
|
||||||
if(!child)
|
|
||||||
return def;
|
return def;
|
||||||
return child->read<T>(def);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// templates for writing values
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void OTMLNode::write(const T& v) {
|
void OTMLNode::write(const T& v) {
|
||||||
to_otmlnode(shared_from_this(), v);
|
m_value = fw::safe_cast<std::string>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void OTMLNode::writeAt(const std::string& childTag, const T& v) {
|
void OTMLNode::writeAt(const std::string& childTag, const T& v) {
|
||||||
OTMLNodePtr child = get(childTag);
|
OTMLNodePtr child = OTMLNode::create(childTag);
|
||||||
bool created = false;
|
|
||||||
if(!child) {
|
|
||||||
child = OTMLNodePtr(new OTMLNode);
|
|
||||||
child->setTag(childTag);
|
|
||||||
child->setUnique();
|
|
||||||
created = true;
|
|
||||||
}
|
|
||||||
child->write<T>(v);
|
child->write<T>(v);
|
||||||
if(created)
|
|
||||||
addChild(child);
|
addChild(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void OTMLNode::writeIn(const T& v) {
|
void OTMLNode::writeIn(const T& v) {
|
||||||
OTMLNodePtr child = OTMLNodePtr(new OTMLNode);
|
OTMLNodePtr child = OTMLNode::create();
|
||||||
child->write<T>(v);
|
child->write<T>(v);
|
||||||
addChild(child);
|
addChild(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
// templates for casting a node to another type
|
|
||||||
template<typename T>
|
|
||||||
bool from_otmlnode(OTMLNodePtr node, T& v) {
|
|
||||||
return fw::cast(node->value(), v);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool from_otmlnode(OTMLNodePtr node, std::vector<T>& v) {
|
|
||||||
v.resize(node->size());
|
|
||||||
for(unsigned i=0;i<node->size();++i)
|
|
||||||
v[i] = node->readAt<T>(i);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool from_otmlnode(OTMLNodePtr node, std::list<T>& v) {
|
|
||||||
for(unsigned i=0;i<node->size();++i)
|
|
||||||
v.push_back(node->readAt<T>(i));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename K, typename T>
|
|
||||||
bool from_otmlnode(OTMLNodePtr node, std::map<K, T>& m) {
|
|
||||||
for(int i=0;i<node->size();++i) {
|
|
||||||
K k;
|
|
||||||
if(!fw::cast(node->at(i)->tag(), k))
|
|
||||||
return false;
|
|
||||||
m[k] = node->at(i)->read<T>();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// templates for casting a type to a node
|
|
||||||
template<typename T>
|
|
||||||
void to_otmlnode(OTMLNodePtr node, const T& v) {
|
|
||||||
node->setValue(fw::unsafe_cast<std::string>(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void to_otmlnode(OTMLNodePtr node, const std::vector<T>& v) {
|
|
||||||
for(unsigned i=0;i<v.size();++i) {
|
|
||||||
OTMLNodePtr newNode(new OTMLNode);
|
|
||||||
newNode->write(v[i]);
|
|
||||||
node->addChild(newNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void to_otmlnode(OTMLNodePtr node, const std::list<T>& v) {
|
|
||||||
for(unsigned i=0;i<v.size();++i) {
|
|
||||||
OTMLNodePtr newNode(new OTMLNode);
|
|
||||||
newNode->write(v[i]);
|
|
||||||
node->addChild(newNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename K, typename T>
|
|
||||||
void to_otmlnode(OTMLNodePtr node, const std::map<K, T>& m) {
|
|
||||||
for(auto it = m.begin(); it != m.end(); ++it) {
|
|
||||||
std::string k = fw::unsafe_cast<std::string>(it->first);
|
|
||||||
OTMLNodePtr newNode(new OTMLNode);
|
|
||||||
newNode->setTag(k);
|
|
||||||
newNode->setUnique();
|
|
||||||
newNode->write(it->second);
|
|
||||||
node->addChild(newNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "otmlparser.h"
|
#include "otmlparser.h"
|
||||||
#include "otmldocument.h"
|
#include "otmldocument.h"
|
||||||
|
#include "otmlexception.h"
|
||||||
|
|
||||||
OTMLParser::OTMLParser(OTMLDocumentPtr doc, std::istream& in) :
|
OTMLParser::OTMLParser(OTMLDocumentPtr doc, std::istream& in) :
|
||||||
currentDepth(0), currentLine(0),
|
currentDepth(0), currentLine(0),
|
||||||
|
@ -52,6 +53,9 @@ void OTMLParser::parseLine(std::string line)
|
||||||
{
|
{
|
||||||
int depth = getLineDepth(line);
|
int depth = getLineDepth(line);
|
||||||
|
|
||||||
|
if(depth == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
// remove line sides spaces
|
// remove line sides spaces
|
||||||
boost::trim(line);
|
boost::trim(line);
|
||||||
|
|
||||||
|
@ -87,6 +91,7 @@ void OTMLParser::parseNode(const std::string& data)
|
||||||
std::string tag;
|
std::string tag;
|
||||||
std::string value;
|
std::string value;
|
||||||
std::size_t dotsPos = data.find_first_of(':');
|
std::size_t dotsPos = data.find_first_of(':');
|
||||||
|
int nodeLine = currentLine;
|
||||||
|
|
||||||
// node that has no tag and may have a value
|
// node that has no tag and may have a value
|
||||||
if(!data.empty() && data[0] == '-') {
|
if(!data.empty() && data[0] == '-') {
|
||||||
|
@ -150,11 +155,18 @@ void OTMLParser::parseNode(const std::string& data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the node
|
// create the node
|
||||||
OTMLNodePtr node(new OTMLNode);
|
OTMLNodePtr node = OTMLNode::create(tag);
|
||||||
|
|
||||||
node->setUnique(dotsPos != std::string::npos);
|
node->setUnique(dotsPos != std::string::npos);
|
||||||
node->setTag(tag);
|
node->setTag(tag);
|
||||||
|
node->setSource(doc->source() + ":" + fw::unsafe_cast<std::string>(nodeLine));
|
||||||
|
|
||||||
|
// ~ is considered the null value
|
||||||
|
if(value == "~")
|
||||||
|
node->setNull(true);
|
||||||
|
else
|
||||||
node->setValue(value);
|
node->setValue(value);
|
||||||
node->setSource(doc->source() + ":" + fw::safe_cast<std::string>(currentLine));
|
|
||||||
currentParent->addChild(node);
|
currentParent->addChild(node);
|
||||||
previousNode = node;
|
previousNode = node;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,10 +37,10 @@ void UIButton::loadStyleFromOTML(const OTMLNodePtr& styleNode)
|
||||||
if(OTMLNodePtr node = styleNode->get("state.down"))
|
if(OTMLNodePtr node = styleNode->get("state.down"))
|
||||||
loadStateStyle(m_statesStyle[ButtonDown], node);
|
loadStateStyle(m_statesStyle[ButtonDown], node);
|
||||||
|
|
||||||
m_text = styleNode->readAt("text", fw::empty_string);
|
m_text = styleNode->valueAt("text", fw::empty_string);
|
||||||
|
|
||||||
if(OTMLNodePtr node = styleNode->get("onClick")) {
|
if(OTMLNodePtr node = styleNode->get("onClick")) {
|
||||||
g_lua.loadFunction(node->read<std::string>(), "@" + node->source() + "[" + node->tag() + "]");
|
g_lua.loadFunction(node->value<std::string>(), "@" + node->source() + "[" + node->tag() + "]");
|
||||||
luaSetField("onClick");
|
luaSetField("onClick");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,9 +51,9 @@ void UIButton::loadStateStyle(ButtonStateStyle& stateStyle, const OTMLNodePtr& s
|
||||||
stateStyle.image = BorderImage::loadFromOTML(node);
|
stateStyle.image = BorderImage::loadFromOTML(node);
|
||||||
if(OTMLNodePtr node = stateStyleNode->get("image"))
|
if(OTMLNodePtr node = stateStyleNode->get("image"))
|
||||||
stateStyle.image = Image::loadFromOTML(node);
|
stateStyle.image = Image::loadFromOTML(node);
|
||||||
stateStyle.textTranslate = stateStyleNode->readAt("text-translate", Point());
|
stateStyle.textTranslate = stateStyleNode->valueAt("text-translate", Point());
|
||||||
stateStyle.color = stateStyleNode->readAt("font-color", m_fontColor);
|
stateStyle.color = stateStyleNode->valueAt("font-color", m_fontColor);
|
||||||
stateStyle.color = stateStyleNode->readAt("color", m_color);
|
stateStyle.color = stateStyleNode->valueAt("color", m_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIButton::render()
|
void UIButton::render()
|
||||||
|
|
|
@ -18,10 +18,10 @@ void UILabel::loadStyleFromOTML(const OTMLNodePtr& styleNode)
|
||||||
{
|
{
|
||||||
UIWidget::loadStyleFromOTML(styleNode);
|
UIWidget::loadStyleFromOTML(styleNode);
|
||||||
|
|
||||||
m_text = styleNode->readAt("text", m_text);
|
m_text = styleNode->valueAt("text", m_text);
|
||||||
|
|
||||||
if(styleNode->hasChild("align"))
|
if(styleNode->hasChildAt("align"))
|
||||||
m_align = fw::translateAlignment(styleNode->readAt<std::string>("align"));
|
m_align = fw::translateAlignment(styleNode->valueAt("align"));
|
||||||
|
|
||||||
// auto resize if no size supplied
|
// auto resize if no size supplied
|
||||||
if(!m_text.empty() && !getGeometry().isValid())
|
if(!m_text.empty() && !getGeometry().isValid())
|
||||||
|
|
|
@ -25,7 +25,7 @@ void UILineEdit::loadStyleFromOTML(const OTMLNodePtr& styleNode)
|
||||||
{
|
{
|
||||||
UIWidget::loadStyleFromOTML(styleNode);
|
UIWidget::loadStyleFromOTML(styleNode);
|
||||||
|
|
||||||
setText(styleNode->readAt("text", getText()));
|
setText(styleNode->valueAt("text", getText()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void UILineEdit::render()
|
void UILineEdit::render()
|
||||||
|
|
|
@ -93,7 +93,7 @@ bool UIManager::importStyles(const std::string& file)
|
||||||
try {
|
try {
|
||||||
OTMLDocumentPtr doc = OTMLDocument::parse(file);
|
OTMLDocumentPtr doc = OTMLDocument::parse(file);
|
||||||
|
|
||||||
for(const OTMLNodePtr& styleNode : doc->childNodes())
|
for(const OTMLNodePtr& styleNode : doc->children())
|
||||||
importStyleFromOTML(styleNode);
|
importStyleFromOTML(styleNode);
|
||||||
return true;
|
return true;
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
|
@ -129,14 +129,14 @@ void UIManager::importStyleFromOTML(const OTMLNodePtr& styleNode)
|
||||||
OTMLNodePtr UIManager::getStyle(const std::string& styleName)
|
OTMLNodePtr UIManager::getStyle(const std::string& styleName)
|
||||||
{
|
{
|
||||||
if(boost::starts_with(styleName, "UI")) {
|
if(boost::starts_with(styleName, "UI")) {
|
||||||
OTMLNodePtr node(new OTMLNode());
|
OTMLNodePtr node = OTMLNode::create();
|
||||||
node->writeAt("__widgetType", styleName);
|
node->writeAt("__widgetType", styleName);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = m_styles.find(styleName);
|
auto it = m_styles.find(styleName);
|
||||||
if(it == m_styles.end())
|
if(it == m_styles.end())
|
||||||
throw std::logic_error(fw::mkstr("style '", styleName, "' is not a defined style"));
|
throw std::runtime_error(fw::mkstr("style '", styleName, "' is not a defined style"));
|
||||||
return m_styles[styleName];
|
return m_styles[styleName];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ UIWidgetPtr UIManager::loadUI(const std::string& file)
|
||||||
try {
|
try {
|
||||||
OTMLDocumentPtr doc = OTMLDocument::parse(file);
|
OTMLDocumentPtr doc = OTMLDocument::parse(file);
|
||||||
UIWidgetPtr widget;
|
UIWidgetPtr widget;
|
||||||
for(const OTMLNodePtr& node : doc->childNodes()) {
|
for(const OTMLNodePtr& node : doc->children()) {
|
||||||
std::string tag = node->tag();
|
std::string tag = node->tag();
|
||||||
|
|
||||||
// import styles in these files too
|
// import styles in these files too
|
||||||
|
@ -153,7 +153,7 @@ UIWidgetPtr UIManager::loadUI(const std::string& file)
|
||||||
importStyleFromOTML(node);
|
importStyleFromOTML(node);
|
||||||
else {
|
else {
|
||||||
if(widget)
|
if(widget)
|
||||||
throw OTMLException(node, "cannot have multiple main widgets in .otui files");
|
throw std::runtime_error("cannot have multiple main widgets in .otui files");
|
||||||
widget = loadWidgetFromOTML(node);
|
widget = loadWidgetFromOTML(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ UIWidgetPtr UIManager::loadWidgetFromOTML(const OTMLNodePtr& widgetNode)
|
||||||
OTMLNodePtr styleNode = getStyle(widgetNode->tag())->clone();
|
OTMLNodePtr styleNode = getStyle(widgetNode->tag())->clone();
|
||||||
styleNode->merge(widgetNode);
|
styleNode->merge(widgetNode);
|
||||||
|
|
||||||
std::string widgetType = styleNode->readAt<std::string>("__widgetType");
|
std::string widgetType = styleNode->valueAt("__widgetType");
|
||||||
|
|
||||||
UIWidgetPtr widget;
|
UIWidgetPtr widget;
|
||||||
if(widgetType == "UIWidget")
|
if(widgetType == "UIWidget")
|
||||||
|
@ -191,7 +191,7 @@ UIWidgetPtr UIManager::loadWidgetFromOTML(const OTMLNodePtr& widgetNode)
|
||||||
widget->loadStyleFromOTML(styleNode);
|
widget->loadStyleFromOTML(styleNode);
|
||||||
widget->updateGeometry();
|
widget->updateGeometry();
|
||||||
|
|
||||||
for(const OTMLNodePtr& childNode : widgetNode->childNodes()) {
|
for(const OTMLNodePtr& childNode : widgetNode->children()) {
|
||||||
if(!childNode->isUnique())
|
if(!childNode->isUnique())
|
||||||
widget->addChild(loadWidgetFromOTML(childNode));
|
widget->addChild(loadWidgetFromOTML(childNode));
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ void UIWidget::loadStyleFromOTML(const OTMLNodePtr& styleNode)
|
||||||
assert(!m_destroyed);
|
assert(!m_destroyed);
|
||||||
|
|
||||||
// load styles used by all widgets
|
// load styles used by all widgets
|
||||||
for(const OTMLNodePtr& node : styleNode->childNodes()) {
|
for(const OTMLNodePtr& node : styleNode->children()) {
|
||||||
// id
|
// id
|
||||||
if(node->tag() == "id") {
|
if(node->tag() == "id") {
|
||||||
setId(node->value());
|
setId(node->value());
|
||||||
|
@ -121,48 +121,48 @@ void UIWidget::loadStyleFromOTML(const OTMLNodePtr& styleNode)
|
||||||
}
|
}
|
||||||
// font color
|
// font color
|
||||||
else if(node->tag() == "font-color") {
|
else if(node->tag() == "font-color") {
|
||||||
setFontColor(node->read<Color>());
|
setFontColor(node->value<Color>());
|
||||||
}
|
}
|
||||||
// color
|
// color
|
||||||
else if(node->tag() == "color") {
|
else if(node->tag() == "color") {
|
||||||
setColor(node->read<Color>());
|
setColor(node->value<Color>());
|
||||||
}
|
}
|
||||||
// opacity
|
// opacity
|
||||||
else if(node->tag() == "opacity") {
|
else if(node->tag() == "opacity") {
|
||||||
setOpacity(node->read<int>());
|
setOpacity(node->value<int>());
|
||||||
}
|
}
|
||||||
// size
|
// size
|
||||||
else if(node->tag() == "size") {
|
else if(node->tag() == "size") {
|
||||||
resize(node->read<Size>());
|
resize(node->value<Size>());
|
||||||
}
|
}
|
||||||
else if(node->tag() == "width") {
|
else if(node->tag() == "width") {
|
||||||
setWidth(node->read<int>());
|
setWidth(node->value<int>());
|
||||||
}
|
}
|
||||||
else if(node->tag() == "height") {
|
else if(node->tag() == "height") {
|
||||||
setHeight(node->read<int>());
|
setHeight(node->value<int>());
|
||||||
}
|
}
|
||||||
// position
|
// position
|
||||||
else if(node->tag() == "position") {
|
else if(node->tag() == "position") {
|
||||||
move(node->read<Point>());
|
move(node->value<Point>());
|
||||||
}
|
}
|
||||||
else if(node->tag() == "x") {
|
else if(node->tag() == "x") {
|
||||||
setX(node->read<int>());
|
setX(node->value<int>());
|
||||||
}
|
}
|
||||||
else if(node->tag() == "y") {
|
else if(node->tag() == "y") {
|
||||||
setY(node->read<int>());
|
setY(node->value<int>());
|
||||||
}
|
}
|
||||||
// margins
|
// margins
|
||||||
else if(node->tag() == "margin.left") {
|
else if(node->tag() == "margin.left") {
|
||||||
setMarginLeft(node->read<int>());
|
setMarginLeft(node->value<int>());
|
||||||
}
|
}
|
||||||
else if(node->tag() == "margin.right") {
|
else if(node->tag() == "margin.right") {
|
||||||
setMarginRight(node->read<int>());
|
setMarginRight(node->value<int>());
|
||||||
}
|
}
|
||||||
else if(node->tag() == "margin.top") {
|
else if(node->tag() == "margin.top") {
|
||||||
setMarginTop(node->read<int>());
|
setMarginTop(node->value<int>());
|
||||||
}
|
}
|
||||||
else if(node->tag() == "margin.bottom") {
|
else if(node->tag() == "margin.bottom") {
|
||||||
setMarginBottom(node->read<int>());
|
setMarginBottom(node->value<int>());
|
||||||
}
|
}
|
||||||
// anchors
|
// anchors
|
||||||
else if(boost::starts_with(node->tag(), "anchors.")) {
|
else if(boost::starts_with(node->tag(), "anchors.")) {
|
||||||
|
@ -193,7 +193,7 @@ void UIWidget::loadStyleFromOTML(const OTMLNodePtr& styleNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(node->tag() == "onLoad") {
|
else if(node->tag() == "onLoad") {
|
||||||
g_lua.loadFunction(node->read<std::string>(), "@" + node->source() + "[" + node->tag() + "]");
|
g_lua.loadFunction(node->value<std::string>(), "@" + node->source() + "[" + node->tag() + "]");
|
||||||
luaSetField("onLoad");
|
luaSetField("onLoad");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,8 +437,12 @@ UIWidgetPtr UIWidget::recursiveGetChildById(const std::string& childId)
|
||||||
for(const UIWidgetPtr& child : m_children) {
|
for(const UIWidgetPtr& child : m_children) {
|
||||||
if(child->getId() == childId)
|
if(child->getId() == childId)
|
||||||
return child;
|
return child;
|
||||||
else
|
}
|
||||||
return child->recursiveGetChildById(childId);
|
for(const UIWidgetPtr& child : m_children) {
|
||||||
|
if(UIWidgetPtr subChild = child->recursiveGetChildById(childId)) {
|
||||||
|
if(subChild->getId() == childId)
|
||||||
|
return subChild;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -522,6 +526,9 @@ void UIWidget::addChild(const UIWidgetPtr& childToAdd)
|
||||||
{
|
{
|
||||||
assert(!m_destroyed);
|
assert(!m_destroyed);
|
||||||
|
|
||||||
|
if(!childToAdd)
|
||||||
|
return;
|
||||||
|
|
||||||
assert(!hasChild(childToAdd));
|
assert(!hasChild(childToAdd));
|
||||||
m_children.push_back(childToAdd);
|
m_children.push_back(childToAdd);
|
||||||
childToAdd->setParent(asUIWidget());
|
childToAdd->setParent(asUIWidget());
|
||||||
|
@ -538,6 +545,9 @@ void UIWidget::removeChild(const UIWidgetPtr& childToRemove)
|
||||||
{
|
{
|
||||||
assert(!m_destroyed);
|
assert(!m_destroyed);
|
||||||
|
|
||||||
|
if(!childToRemove)
|
||||||
|
return;
|
||||||
|
|
||||||
// defocus if needed
|
// defocus if needed
|
||||||
if(m_focusedChild == childToRemove)
|
if(m_focusedChild == childToRemove)
|
||||||
focusChild(nullptr, ActiveFocusReason);
|
focusChild(nullptr, ActiveFocusReason);
|
||||||
|
|
|
@ -23,9 +23,9 @@ void UIWindow::loadStyleFromOTML(const OTMLNodePtr& styleNode)
|
||||||
if(OTMLNodePtr headNode = styleNode->get("head")) {
|
if(OTMLNodePtr headNode = styleNode->get("head")) {
|
||||||
if(OTMLNodePtr node = headNode->get("border-image"))
|
if(OTMLNodePtr node = headNode->get("border-image"))
|
||||||
m_headImage = BorderImage::loadFromOTML(node);
|
m_headImage = BorderImage::loadFromOTML(node);
|
||||||
m_headHeight = headNode->readAt("height", m_headImage->getDefaultSize().height());
|
m_headHeight = headNode->valueAt("height", m_headImage->getDefaultSize().height());
|
||||||
m_headMargin = headNode->readAt("margin", 0);
|
m_headMargin = headNode->valueAt("margin", 0);
|
||||||
m_titleAlign = fw::translateAlignment(headNode->readAt("text align", std::string("center")));
|
m_titleAlign = fw::translateAlignment(headNode->valueAt("text align", std::string("center")));
|
||||||
} else {
|
} else {
|
||||||
m_headHeight = 0;
|
m_headHeight = 0;
|
||||||
m_headMargin = 0;
|
m_headMargin = 0;
|
||||||
|
@ -37,7 +37,7 @@ void UIWindow::loadStyleFromOTML(const OTMLNodePtr& styleNode)
|
||||||
m_bodyImage = BorderImage::loadFromOTML(node);
|
m_bodyImage = BorderImage::loadFromOTML(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_title = styleNode->readAt("title", fw::empty_string);
|
m_title = styleNode->valueAt("title", fw::empty_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIWindow::render()
|
void UIWindow::render()
|
||||||
|
|
|
@ -9,7 +9,7 @@ typedef uint32 RGBA;
|
||||||
class Color
|
class Color
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Color() : color(0) { }
|
Color() : color(0xFFFFFFFF) { }
|
||||||
Color(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) : color(((a & 0xff)<<24) | ((b & 0xff)<<16) | ((g & 0xff)<<8) | (r & 0xff)) { }
|
Color(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) : color(((a & 0xff)<<24) | ((b & 0xff)<<16) | ((g & 0xff)<<8) | (r & 0xff)) { }
|
||||||
Color(const Color& other) : color(other.color) { }
|
Color(const Color& other) : color(other.color) { }
|
||||||
Color(RGBA rgba) : color(rgba) { }
|
Color(RGBA rgba) : color(rgba) { }
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
|
|
||||||
DatManager g_dat;
|
DatManager g_dat;
|
||||||
|
|
||||||
bool DatManager::load(const std::string& filename)
|
bool DatManager::load(const std::string& file)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
std::stringstream fin;
|
std::stringstream fin;
|
||||||
g_resources.loadFile(filename, fin);
|
g_resources.loadFile(file, fin);
|
||||||
|
|
||||||
m_signature = fw::getu32(fin);
|
m_signature = fw::getu32(fin);
|
||||||
int numItems = fw::getu16(fin);
|
int numItems = fw::getu16(fin);
|
||||||
|
@ -34,7 +34,7 @@ bool DatManager::load(const std::string& filename)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch(std::exception& e) {
|
} catch(std::exception& e) {
|
||||||
logError(e.what());
|
logError("ERROR: failed to load dat from '", file, "': ", e.what());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,11 +87,9 @@ void DatManager::parseThingAttributes(std::stringstream& fin, ThingAttributes& t
|
||||||
|
|
||||||
void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes& thingAttributes, uint8 opt)
|
void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes& thingAttributes, uint8 opt)
|
||||||
{
|
{
|
||||||
uint8 read_byte;
|
|
||||||
uint16 read_short;
|
|
||||||
switch(opt) {
|
switch(opt) {
|
||||||
case 0x00: // Ground tile
|
case 0x00: // Ground tile
|
||||||
fin.read((char*)&thingAttributes.speed, 2);
|
thingAttributes.speed = fw::getu16(fin);
|
||||||
thingAttributes.group = THING_GROUP_GROUND;
|
thingAttributes.group = THING_GROUP_GROUND;
|
||||||
break;
|
break;
|
||||||
case 0x01: // All OnTop
|
case 0x01: // All OnTop
|
||||||
|
@ -120,16 +118,16 @@ void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes
|
||||||
case 0x08: // Writtable
|
case 0x08: // Writtable
|
||||||
thingAttributes.group = THING_GROUP_WRITEABLE;
|
thingAttributes.group = THING_GROUP_WRITEABLE;
|
||||||
thingAttributes.readable = true;
|
thingAttributes.readable = true;
|
||||||
fin.read((char*)&thingAttributes.subParam07, 2);
|
thingAttributes.subParam08 = fw::getu16(fin);
|
||||||
break;
|
break;
|
||||||
case 0x09: // Writtable once
|
case 0x09: // Writtable once
|
||||||
// Writtable objects that can't be edited by players
|
// Writtable objects that can't be edited by players
|
||||||
thingAttributes.readable = true;
|
thingAttributes.readable = true;
|
||||||
fin.read((char*)&thingAttributes.subParam08, 2);
|
thingAttributes.subParam08 = fw::getu16(fin);
|
||||||
break;
|
break;
|
||||||
case 0x0A: // Fluid containers
|
case 0x0A: // Fluid containers
|
||||||
fin.read((char*)&read_byte, 1);
|
|
||||||
thingAttributes.group = THING_GROUP_FLUID;
|
thingAttributes.group = THING_GROUP_FLUID;
|
||||||
|
fw::getu8(fin);
|
||||||
break;
|
break;
|
||||||
case 0x0B: // Splashes
|
case 0x0B: // Splashes
|
||||||
thingAttributes.group = THING_GROUP_SPLASH;
|
thingAttributes.group = THING_GROUP_SPLASH;
|
||||||
|
@ -162,8 +160,8 @@ void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes
|
||||||
thingAttributes.rotable = true;
|
thingAttributes.rotable = true;
|
||||||
break;
|
break;
|
||||||
case 0x15: // Light info
|
case 0x15: // Light info
|
||||||
fin.read((char*)&thingAttributes.lightLevel, 2);
|
thingAttributes.lightLevel = fw::getu16(fin);
|
||||||
fin.read((char*)&thingAttributes.lightColor, 2);
|
thingAttributes.lightColor = fw::getu16(fin);
|
||||||
break;
|
break;
|
||||||
case 0x16:
|
case 0x16:
|
||||||
break;
|
break;
|
||||||
|
@ -171,17 +169,12 @@ void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes
|
||||||
break;
|
break;
|
||||||
case 0x18: // Thing must be drawed with offset
|
case 0x18: // Thing must be drawed with offset
|
||||||
thingAttributes.hasHeight = true;
|
thingAttributes.hasHeight = true;
|
||||||
fin.read((char*)&thingAttributes.xOffset, 1);
|
thingAttributes.xOffset = fw::getu8(fin);
|
||||||
fin.read((char*)&thingAttributes.yOffset, 1);
|
thingAttributes.yOffset = fw::getu8(fin);
|
||||||
|
fw::getu16(fin);
|
||||||
fin.read((char*)&read_short, 2);
|
|
||||||
break;
|
break;
|
||||||
case 0x19: // pixels characters height
|
case 0x19: // pixels characters height
|
||||||
|
fw::getu16(fin);
|
||||||
//fin.read((char*)&thingAttributes.xOffset, 1);
|
|
||||||
//fin.read((char*)&thingAttributes.yOffset, 1);
|
|
||||||
fin.read((char*)&read_short, 2);
|
|
||||||
//logDebug((int)thingAttributes.xOffset, " ", (int)thingAttributes.yOffset);
|
|
||||||
break;
|
break;
|
||||||
case 0x1A:
|
case 0x1A:
|
||||||
//thingAttributes.hasHeight = true;
|
//thingAttributes.hasHeight = true;
|
||||||
|
@ -189,12 +182,11 @@ void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes
|
||||||
case 0x1B:
|
case 0x1B:
|
||||||
break;
|
break;
|
||||||
case 0x1C: // Minimap color
|
case 0x1C: // Minimap color
|
||||||
fin.read((char*)&thingAttributes.miniMapColor, 2);
|
thingAttributes.miniMapColor = fw::getu16(fin);
|
||||||
thingAttributes.hasMiniMapColor = true;
|
thingAttributes.hasMiniMapColor = true;
|
||||||
break;
|
break;
|
||||||
case 0x1D: // Unknown
|
case 0x1D: // Unknown
|
||||||
fin.read((char*)&read_short, 2);
|
if(fw::getu16(fin) == 1112)
|
||||||
if(read_short == 1112)
|
|
||||||
thingAttributes.readable = true;
|
thingAttributes.readable = true;
|
||||||
break;
|
break;
|
||||||
case 0x1E:
|
case 0x1E:
|
||||||
|
@ -205,6 +197,6 @@ void DatManager::parseThingAttributesOpt(std::stringstream& fin, ThingAttributes
|
||||||
case 0x20:
|
case 0x20:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::logic_error(fw::mkstr("ERROR: unknown .dat byte code: 0x", std::hex, (int)opt));
|
throw std::runtime_error(fw::mkstr("unknown .dat byte code: 0x", std::hex, (int)opt));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
class DatManager
|
class DatManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool load(const std::string& filename);
|
bool load(const std::string& file);
|
||||||
void unload();
|
void unload();
|
||||||
|
|
||||||
void parseThingAttributes(std::stringstream& fin, ThingAttributes& thingAttributes);
|
void parseThingAttributes(std::stringstream& fin, ThingAttributes& thingAttributes);
|
||||||
|
|
|
@ -12,11 +12,16 @@ SpriteManager::SpriteManager()
|
||||||
|
|
||||||
bool SpriteManager::load(const std::string &filename)
|
bool SpriteManager::load(const std::string &filename)
|
||||||
{
|
{
|
||||||
|
try {
|
||||||
g_resources.loadFile(filename, m_fin);
|
g_resources.loadFile(filename, m_fin);
|
||||||
m_signature = fw::getu32(m_fin);
|
m_signature = fw::getu32(m_fin);
|
||||||
m_spritesCount = fw::getu16(m_fin);
|
m_spritesCount = fw::getu16(m_fin);
|
||||||
m_sprites.resize(m_spritesCount);
|
m_sprites.resize(m_spritesCount);
|
||||||
return true;
|
return true;
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
logError(e.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteManager::unload()
|
void SpriteManager::unload()
|
||||||
|
|
Loading…
Reference in New Issue