static int lua_Theme_addRef(lua_State* state) { // Get the number of parameters. int paramCount = lua_gettop(state); // Attempt to match the parameters to a valid binding. switch (paramCount) { case 1: { if ((lua_type(state, 1) == LUA_TUSERDATA)) { Theme* instance = getInstance(state); instance->addRef(); return 0; } lua_pushstring(state, "lua_Theme_addRef - Failed to match the given parameters to a valid function signature."); lua_error(state); break; } default: { lua_pushstring(state, "Invalid number of parameters (expected 1)."); lua_error(state); break; } } return 0; }
Theme* Theme::create(const char* url) { GP_ASSERT(url); // Search theme cache first. for (size_t i = 0, count = __themeCache.size(); i < count; ++i) { Theme* t = __themeCache[i]; if (t->_url == url) { // Found a match. t->addRef(); return t; } } // Load theme properties from file path. Properties* properties = Properties::create(url); GP_ASSERT(properties); if (properties == NULL) { return NULL; } // Check if the Properties is valid and has a valid namespace. Properties* themeProperties = (strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace(); GP_ASSERT(themeProperties); if (!themeProperties || !(strcmp(themeProperties->getNamespace(), "theme") == 0)) { SAFE_DELETE(properties); return NULL; } // Create a new theme. Theme* theme = new Theme(); theme->_url = url; // Parse the Properties object and set up the theme. const char* textureFile = themeProperties->getString("texture"); theme->_texture = Texture::create(textureFile, false); GP_ASSERT(theme->_texture); theme->_spriteBatch = SpriteBatch::create(theme->_texture); GP_ASSERT(theme->_spriteBatch); theme->_spriteBatch->getSampler()->setFilterMode(Texture::NEAREST, Texture::NEAREST); float tw = 1.0f / theme->_texture->getWidth(); float th = 1.0f / theme->_texture->getHeight(); Properties* space = themeProperties->getNextNamespace(); while (space != NULL) { // First load all cursors, checkboxes etc. that can be referred to by styles. const char* spacename = space->getNamespace(); if (strcmp(spacename, "image") == 0) { theme->_images.push_back(ThemeImage::create(tw, th, space, Vector4::one())); } else if (strcmp(spacename, "imageList") == 0) { theme->_imageLists.push_back(ImageList::create(tw, th, space)); } else if (strcmp(spacename, "skin") == 0) { Theme::Border border; Properties* innerSpace = space->getNextNamespace(); if (innerSpace) { const char* innerSpacename = innerSpace->getNamespace(); if (strcmp(innerSpacename, "border") == 0) { border.top = innerSpace->getFloat("top"); border.bottom = innerSpace->getFloat("bottom"); border.left = innerSpace->getFloat("left"); border.right = innerSpace->getFloat("right"); } } Vector4 regionVector; space->getVector4("region", ®ionVector); const Rectangle region(regionVector.x, regionVector.y, regionVector.z, regionVector.w); Vector4 color(1, 1, 1, 1); if (space->exists("color")) { space->getColor("color", &color); } Skin* skin = Skin::create(space->getId(), tw, th, region, border, color); GP_ASSERT(skin); theme->_skins.push_back(skin); } space = themeProperties->getNextNamespace(); } themeProperties->rewind(); space = themeProperties->getNextNamespace(); while (space != NULL) { const char* spacename = space->getNamespace(); if (strcmp(spacename, "style") == 0) { // Each style contains up to MAX_OVERLAYS overlays, // as well as Border and Padding namespaces. Theme::Margin margin; Theme::Padding padding; Theme::Style::Overlay* normal = NULL; Theme::Style::Overlay* focus = NULL; Theme::Style::Overlay* active = NULL; Theme::Style::Overlay* disabled = NULL; Theme::Style::Overlay* hover = NULL; // Need to load OVERLAY_NORMAL first so that the other overlays can inherit from it. Properties* innerSpace = space->getNextNamespace(); while (innerSpace != NULL) { const char* innerSpacename = innerSpace->getNamespace(); if (strcmp(innerSpacename, "stateNormal") == 0) { Vector4 textColor(0, 0, 0, 1); if (innerSpace->exists("textColor")) { innerSpace->getColor("textColor", &textColor); } const char* fontPath = innerSpace->getString("font"); Font* font = NULL; if (fontPath) { font = Font::create(fontPath); } unsigned int fontSize = innerSpace->getInt("fontSize"); const char* textAlignmentString = innerSpace->getString("textAlignment"); Font::Justify textAlignment = Font::ALIGN_TOP_LEFT; if (textAlignmentString) { textAlignment = Font::getJustify(textAlignmentString); } bool rightToLeft = innerSpace->getBool("rightToLeft"); float opacity = 1.0f; if (innerSpace->exists("opacity")) { opacity = innerSpace->getFloat("opacity"); } ImageList* imageList = NULL; ThemeImage* cursor = NULL; Skin* skin = NULL; theme->lookUpSprites(innerSpace, &imageList, &cursor, &skin); normal = Theme::Style::Overlay::create(); GP_ASSERT(normal); normal->setSkin(skin); normal->setCursor(cursor); normal->setImageList(imageList); normal->setTextColor(textColor); normal->setFont(font); normal->setFontSize(fontSize); normal->setTextAlignment(textAlignment); normal->setTextRightToLeft(rightToLeft); normal->setOpacity(opacity); if (font) { theme->_fonts.insert(font); font->release(); } // Done with this pass. break; } innerSpace = space->getNextNamespace(); } // At least the OVERLAY_NORMAL is required. if (!normal) GP_ERROR("All themes require the normal state overlay to be defined."); space->rewind(); innerSpace = space->getNextNamespace(); while (innerSpace != NULL) { const char* innerSpacename = innerSpace->getNamespace(); if (strcmp(innerSpacename, "margin") == 0) { margin.top = innerSpace->getFloat("top"); margin.bottom = innerSpace->getFloat("bottom"); margin.left = innerSpace->getFloat("left"); margin.right = innerSpace->getFloat("right"); } else if (strcmp(innerSpacename, "padding") == 0) { padding.top = innerSpace->getFloat("top"); padding.bottom = innerSpace->getFloat("bottom"); padding.left = innerSpace->getFloat("left"); padding.right = innerSpace->getFloat("right"); } else if (strcmp(innerSpacename, "stateNormal") != 0) { // Either OVERLAY_FOCUS or OVERLAY_ACTIVE. // If a property isn't specified, it inherits from OVERLAY_NORMAL. Vector4 textColor; if (!innerSpace->getColor("textColor", &textColor)) { textColor.set(normal->getTextColor()); } const char* fontPath = innerSpace->getString("font"); Font* font = NULL; if (fontPath) { font = Font::create(fontPath); } if (!font) { font = normal->getFont(); if (font) font->addRef(); } unsigned int fontSize; if (innerSpace->exists("fontSize")) { fontSize = innerSpace->getInt("fontSize"); } else { fontSize = normal->getFontSize(); } const char* textAlignmentString = innerSpace->getString("textAlignment"); Font::Justify textAlignment; if (textAlignmentString) { textAlignment = Font::getJustify(textAlignmentString); } else { textAlignment = normal->getTextAlignment(); } bool rightToLeft; if (innerSpace->exists("rightToLeft")) { rightToLeft = innerSpace->getBool("rightToLeft"); } else { rightToLeft = normal->getTextRightToLeft(); } float opacity; if (innerSpace->exists("opacity")) { opacity = innerSpace->getFloat("opacity"); } else { opacity = normal->getOpacity(); } ImageList* imageList = NULL; ThemeImage* cursor = NULL; Skin* skin = NULL; theme->lookUpSprites(innerSpace, &imageList, &cursor, &skin); if (!imageList) { imageList = normal->getImageList(); } if (!cursor) { cursor = normal->getCursor(); } if (!skin) { skin = normal->getSkin(); } if (strcmp(innerSpacename, "stateFocus") == 0) { focus = Theme::Style::Overlay::create(); GP_ASSERT(focus); focus->setSkin(skin); focus->setCursor(cursor); focus->setImageList(imageList); focus->setTextColor(textColor); focus->setFont(font); focus->setFontSize(fontSize); focus->setTextAlignment(textAlignment); focus->setTextRightToLeft(rightToLeft); focus->setOpacity(opacity); if (font) { theme->_fonts.insert(font); font->release(); } } else if (strcmp(innerSpacename, "stateActive") == 0) { active = Theme::Style::Overlay::create(); GP_ASSERT(active); active->setSkin(skin); active->setCursor(cursor); active->setImageList(imageList); active->setTextColor(textColor); active->setFont(font); active->setFontSize(fontSize); active->setTextAlignment(textAlignment); active->setTextRightToLeft(rightToLeft); active->setOpacity(opacity); if (font) { theme->_fonts.insert(font); font->release(); } } else if (strcmp(innerSpacename, "stateDisabled") == 0) { disabled = Theme::Style::Overlay::create(); GP_ASSERT(disabled); disabled->setSkin(skin); disabled->setCursor(cursor); disabled->setImageList(imageList); disabled->setTextColor(textColor); disabled->setFont(font); disabled->setFontSize(fontSize); disabled->setTextAlignment(textAlignment); disabled->setTextRightToLeft(rightToLeft); disabled->setOpacity(opacity); if (font) { theme->_fonts.insert(font); font->release(); } } else if (strcmp(innerSpacename, "stateHover") == 0) { hover = Theme::Style::Overlay::create(); GP_ASSERT(hover); hover->setSkin(skin); hover->setCursor(cursor); hover->setImageList(imageList); hover->setTextColor(textColor); hover->setFont(font); hover->setFontSize(fontSize); hover->setTextAlignment(textAlignment); hover->setTextRightToLeft(rightToLeft); hover->setOpacity(opacity); if (font) { theme->_fonts.insert(font); font->release(); } } } innerSpace = space->getNextNamespace(); } if (!focus) { focus = normal; focus->addRef(); } if (!disabled) { disabled = normal; disabled->addRef(); } // Note: The hover and active states have their overlay left NULL if unspecified. // Events will still be triggered, but a control's overlay will not be changed. Theme::Style* s = new Theme::Style(theme, space->getId(), tw, th, margin, padding, normal, focus, active, disabled, hover); GP_ASSERT(s); theme->_styles.push_back(s); } space = themeProperties->getNextNamespace(); } // Add this theme to the cache. __themeCache.push_back(theme); SAFE_DELETE(properties); return theme; }