Exemplo n.º 1
0
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;
}
Exemplo n.º 2
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", &regionVector);
            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;
}