void Module::discover(const OTMLNodePtr& moduleNode) { 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); m_reloadable = moduleNode->valueAt<bool>("reloadable", true); m_autoLoadPriority = moduleNode->valueAt<int>("autoload-priority", 9999); if(OTMLNodePtr node = moduleNode->get("dependencies")) { 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->value(), "@" + node->source() + "[" + node->tag() + "]"); g_lua.useValue(); m_loadCallback = g_lua.polymorphicPop<std::function<void()>>(); } // set onUnload callback if(OTMLNodePtr node = moduleNode->get("@onUnload")) { g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]"); g_lua.useValue(); m_unloadCallback = g_lua.polymorphicPop<std::function<void()>>(); } if(OTMLNodePtr node = moduleNode->get("load-later")) { for(const OTMLNodePtr& tmp : node->children()) m_loadLaterModules.push_back(tmp->value()); } }
void BitmapFont::load(const OTMLNodePtr& fontNode) { OTMLNodePtr textureNode = fontNode->at("texture"); std::string textureFile = stdext::resolve_path(textureNode->value(), textureNode->source()); Size glyphSize = fontNode->valueAt<Size>("glyph-size"); m_glyphHeight = fontNode->valueAt<int>("height"); m_yOffset = fontNode->valueAt("y-offset", 0); m_firstGlyph = fontNode->valueAt("first-glyph", 32); m_glyphSpacing = fontNode->valueAt("spacing", Size(0,0)); int spaceWidth = fontNode->valueAt("space-width", glyphSize.width()); // load font texture m_texture = g_textures.getTexture(textureFile); if(OTMLNodePtr node = fontNode->get("fixed-glyph-width")) { for(int glyph = m_firstGlyph; glyph < 256; ++glyph) m_glyphsSize[glyph] = Size(node->value<int>(), m_glyphHeight); } else { calculateGlyphsWidthsAutomatically(Image::load(textureFile), glyphSize); } // 32 and 160 are spaces ( ) m_glyphsSize[32].setWidth(spaceWidth); m_glyphsSize[160].setWidth(spaceWidth); // use 127 as spacer [Width: 1], Important for the current NPC highlighting system m_glyphsSize[127].setWidth(1); // new line actually has a size that will be useful in multiline algorithm m_glyphsSize[(uchar)'\n'] = Size(1, m_glyphHeight); // read custom widths /* if(OTMLNodePtr node = fontNode->get("glyph-widths")) { for(const OTMLNodePtr& child : node->children()) m_glyphsSize[stdext::safe_cast<int>(child->tag())].setWidth(child->value<int>()); } */ // calculate glyphs texture coords int numHorizontalGlyphs = m_texture->getSize().width() / glyphSize.width(); for(int glyph = m_firstGlyph; glyph < 256; ++glyph) { m_glyphsTextureCoords[glyph].setRect(((glyph - m_firstGlyph) % numHorizontalGlyphs) * glyphSize.width(), ((glyph - m_firstGlyph) / numHorizontalGlyphs) * glyphSize.height(), m_glyphsSize[glyph].width(), m_glyphHeight); } }
UIWidgetPtr UIManager::createWidgetFromOTML(const OTMLNodePtr& widgetNode, const UIWidgetPtr& parent) { OTMLNodePtr originalStyleNode = getStyle(widgetNode->tag()); if(!originalStyleNode) stdext::throw_exception(stdext::format("'%s' is not a defined style", widgetNode->tag())); OTMLNodePtr styleNode = originalStyleNode->clone(); styleNode->merge(widgetNode); std::string widgetType = styleNode->valueAt("__class"); // call widget creation from lua UIWidgetPtr widget = g_lua.callGlobalField<UIWidgetPtr>(widgetType, "create"); if(parent) parent->addChild(widget); if(widget) { widget->callLuaField("onCreate"); widget->setStyleFromNode(styleNode); for(const OTMLNodePtr& childNode : styleNode->children()) { if(!childNode->isUnique()) { createWidgetFromOTML(childNode, widget); styleNode->removeChild(childNode); } } } else stdext::throw_exception(stdext::format("unable to create widget of type '%s'", widgetType)); widget->callLuaField("onSetup"); return widget; }
std::string UIManager::getStyleClass(const std::string& styleName) { OTMLNodePtr style = getStyle(styleName); if(style && style->get("__class")) return style->valueAt("__class"); return ""; }
ModulePtr ModuleManager::discoverModule(const std::string& moduleFile) { ModulePtr module; try { OTMLDocumentPtr doc = OTMLDocument::parse(moduleFile); OTMLNodePtr moduleNode = doc->at("Module"); std::string name = moduleNode->valueAt("name"); bool push = false; module = getModule(name); if(!module) { module = ModulePtr(new Module(name)); push = true; } module->discover(moduleNode); // not loaded modules are always in back if(push) m_modules.push_back(module); } catch(stdext::exception& e) { g_logger.error(stdext::format("Unable to discover module from file '%s': %s", moduleFile, e.what())); } return module; }
void Font::load(const OTMLNodePtr& fontNode) { OTMLNodePtr textureNode = fontNode->at("texture"); std::string textureFile = Fw::resolvePath(textureNode->value(), textureNode->source()); Size glyphSize = fontNode->valueAt<Size>("glyph-size"); m_glyphHeight = fontNode->valueAt<int>("height"); m_yOffset = fontNode->valueAt("y-offset", 0); m_firstGlyph = fontNode->valueAt("first-glyph", 32); m_glyphSpacing = fontNode->valueAt("spacing", Size(0,0)); // load font texture m_texture = g_textures.getTexture(textureFile); if(OTMLNodePtr node = fontNode->get("fixed-glyph-width")) { for(int glyph = m_firstGlyph; glyph < 256; ++glyph) m_glyphsSize[glyph] = Size(node->value<int>(), m_glyphHeight); } else { calculateGlyphsWidthsAutomatically(Image::load(textureFile), glyphSize); } // new line actually has a size that will be useful in multiline algorithm m_glyphsSize[(uchar)'\n'] = Size(1, m_glyphHeight); // read custom widths if(OTMLNodePtr node = fontNode->get("glyph-widths")) { for(const OTMLNodePtr& child : node->children()) m_glyphsSize[Fw::safeCast<int>(child->tag())].setWidth(child->value<int>()); } // calculate glyphs texture coords int numHorizontalGlyphs = m_texture->getSize().width() / glyphSize.width(); for(int glyph = m_firstGlyph; glyph < 256; ++glyph) { m_glyphsTextureCoords[glyph].setRect(((glyph - m_firstGlyph) % numHorizontalGlyphs) * glyphSize.width(), ((glyph - m_firstGlyph) / numHorizontalGlyphs) * glyphSize.height(), m_glyphsSize[glyph].width(), m_glyphHeight); } }
void UIManager::importStyleFromOTML(const OTMLNodePtr& styleNode) { std::string tag = styleNode->tag(); std::vector<std::string> split = stdext::split(tag, "<"); if(split.size() != 2) throw OTMLException(styleNode, "not a valid style declaration"); std::string name = split[0]; std::string base = split[1]; bool unique = false; stdext::trim(name); stdext::trim(base); if(name[0] == '#') { name = name.substr(1); unique = true; styleNode->setTag(name); styleNode->writeAt("__unique", true); } OTMLNodePtr oldStyle = m_styles[name]; // Warn about redefined styles /* if(!g_app.isRunning() && (oldStyle && !oldStyle->valueAt("__unique", false))) { auto it = m_styles.find(name); if(it != m_styles.end()) g_logger.warning(stdext::format("style '%s' is being redefined", name)); } */ if(!oldStyle || !oldStyle->valueAt("__unique", false) || unique) { OTMLNodePtr originalStyle = getStyle(base); if(!originalStyle) stdext::throw_exception(stdext::format("base style '%s', is not defined", base)); OTMLNodePtr style = originalStyle->clone(); style->merge(styleNode); style->setTag(name); m_styles[name] = style; } }
ModulePtr ModuleManager::discoverModule(const std::string& moduleFile) { ModulePtr module; try { OTMLDocumentPtr doc = OTMLDocument::parse(moduleFile); OTMLNodePtr moduleNode = doc->at("Module"); std::string name = moduleNode->valueAt("name"); if(getModule(name)) Fw::throwException("module '", name, "' already exists, cannot have duplicate module names"); module = ModulePtr(new Module(name)); module->discover(moduleNode); m_modules.push_back(module); } catch(Exception& e) { logError("Unable to discover module from file '", moduleFile, "': ", e.what()); } return module; }
BorderImagePtr BorderImage::loadFromOTML(const OTMLNodePtr& borderImageNode) { Rect leftBorder; Rect rightBorder; Rect topBorder; Rect bottomBorder; Rect topLeftCorner; Rect topRightCorner; Rect bottomLeftCorner; Rect bottomRightCorner; Rect center; Rect subRect; int top, bottom, left, right, border; Size size; Point offset; // load texture std::string source = borderImageNode->at("source")->value(); TexturePtr texture = g_textures.getTexture(source); // load basic border confs size = texture->getSize(); 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->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); rightBorder = Rect(subRect.right() - right + 1, subRect.top() + top, right, subRect.height() - top - bottom); topBorder = Rect(subRect.left() + left, subRect.top(), subRect.width() - right - left, top); bottomBorder = Rect(subRect.left() + left, subRect.bottom() - bottom + 1, subRect.width() - right - left, bottom); topLeftCorner = Rect(subRect.left(), subRect.top(), left, top); topRightCorner = Rect(subRect.right() - right + 1, subRect.top(), right, top); bottomLeftCorner = Rect(subRect.left(), subRect.bottom() - bottom + 1, left, bottom); bottomRightCorner = Rect(subRect.right() - right + 1, subRect.bottom() - bottom + 1, right, bottom); center = Rect(subRect.left() + left, subRect.top() + top, subRect.width() - right - left, subRect.height() - top - bottom); // load individual border conf if supplied /* 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, leftBorder, rightBorder, topBorder, bottomBorder, topLeftCorner, topRightCorner, bottomLeftCorner, bottomRightCorner, center)); }