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