ソースを参照

Added ability to override themed properties on a control within a .form file.

Adam Blake 13 年 前
コミット
56a86250ac

+ 2 - 0
gameplay/gameplay.vcxproj

@@ -37,6 +37,7 @@
     <ClCompile Include="src\DepthStencilTarget.cpp" />
     <ClCompile Include="src\Effect.cpp" />
     <ClCompile Include="src\FileSystem.cpp" />
+    <ClCompile Include="src\FlowLayout.cpp" />
     <ClCompile Include="src\Font.cpp" />
     <ClCompile Include="src\Form.cpp" />
     <ClCompile Include="src\FrameBuffer.cpp" />
@@ -128,6 +129,7 @@
     <ClInclude Include="src\DepthStencilTarget.h" />
     <ClInclude Include="src\Effect.h" />
     <ClInclude Include="src\FileSystem.h" />
+    <ClInclude Include="src\FlowLayout.h" />
     <ClInclude Include="src\Font.h" />
     <ClInclude Include="src\Form.h" />
     <ClInclude Include="src\FrameBuffer.h" />

+ 6 - 0
gameplay/gameplay.vcxproj.filters

@@ -279,6 +279,9 @@
     <ClCompile Include="src\Layout.cpp">
       <Filter>src</Filter>
     </ClCompile>
+    <ClCompile Include="src\FlowLayout.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Animation.h">
@@ -551,6 +554,9 @@
     <ClInclude Include="src\ThemeStyle.h">
       <Filter>src</Filter>
     </ClInclude>
+    <ClInclude Include="src\FlowLayout.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="res\shaders\bumped-specular.vsh">

+ 1 - 1
gameplay/src/AbsoluteLayout.h

@@ -29,7 +29,7 @@ protected:
     /**
      * Create an AbsoluteLayout.
      *
-     * @return an AbsoluteLayout object.
+     * @return An AbsoluteLayout object.
      */
     static AbsoluteLayout* create();
 

+ 1 - 0
gameplay/src/Container.cpp

@@ -76,6 +76,7 @@ namespace gameplay
             {
                  controlStyle = theme->getStyle(controlStyleName);
             }
+            assert(controlStyle);
 
             std::string controlName(controlSpace->getNamespace());
             std::transform(controlName.begin(), controlName.end(), controlName.begin(), (int(*)(int))toupper);

+ 129 - 0
gameplay/src/Control.cpp

@@ -36,6 +36,7 @@ namespace gameplay
     {
         _style = style;
 
+        // Properties not defined by the style.
         _alignment = getAlignment(properties->getString("alignment"));
         _autoWidth = properties->getBool("autoWidth");
         _autoHeight = properties->getBool("autoHeight");
@@ -68,6 +69,35 @@ namespace gameplay
         const char* id = properties->getId();
         if (id)
             _id = id;
+
+        // Potentially override themed properties for all states.
+        overrideThemedProperties(properties, STATE_ALL);
+
+        // Override themed properties on specific states.
+        Properties* stateSpace = properties->getNextNamespace();
+        while (stateSpace != NULL)
+        {
+            std::string stateName(stateSpace->getNamespace());
+            std::transform(stateName.begin(), stateName.end(), stateName.begin(), (int(*)(int))toupper);
+            if (stateName == "STATENORMAL")
+            {
+                overrideThemedProperties(stateSpace, NORMAL);
+            }
+            else if (stateName == "STATEFOCUS")
+            {
+                overrideThemedProperties(stateSpace, FOCUS);
+            }
+            else if (stateName == "STATEACTIVE")
+            {
+                overrideThemedProperties(stateSpace, ACTIVE);
+            }
+            else if (stateName == "STATEDISABLED")
+            {
+                overrideThemedProperties(stateSpace, DISABLED);
+            }
+
+            stateSpace = properties->getNextNamespace();
+        }
     }
 
     const char* Control::getID() const
@@ -963,6 +993,105 @@ namespace gameplay
         _styleOverridden = true;
     }
 
+    void Control::overrideThemedProperties(Properties* properties, unsigned char states)
+    {
+        Theme::ImageList* imageList = NULL;
+        Theme::Image* cursor = NULL;
+        Theme::Skin* skin = NULL;
+        _style->_theme->lookUpSprites(properties, &imageList, &cursor, &skin);
+
+        if (imageList)
+        {
+            setImageList(imageList, states);
+        }
+
+        if (cursor)
+        {
+            setCursor(cursor, states);
+        }
+
+        if (skin)
+        {
+            setSkin(skin, states);
+        }
+
+        if (properties->exists("font"))
+        {
+            Font* font = Font::create(properties->getString("font"));
+            setFont(font, states);
+            font->release();
+        }
+
+        if (properties->exists("fontSize"))
+        {
+            setFontSize(properties->getInt("fontSize"), states);
+        }
+
+        if (properties->exists("textColor"))
+        {
+            Vector4 textColor(0, 0, 0, 1);
+            properties->getColor("textColor", &textColor);
+            setTextColor(textColor, states);
+        }
+
+        if (properties->exists("textAlignment"))
+        {
+            setTextAlignment(Font::getJustify(properties->getString("textAlignment")), states);
+        }
+
+        if (properties->exists("rightToLeft"))
+        {
+            setTextRightToLeft(properties->getBool("rightToLeft"), states);
+        }
+
+        if (properties->exists("opacity"))
+        {
+            setOpacity(properties->getFloat("opacity"), states);
+        }
+    }
+
+    void Control::setImageList(Theme::ImageList* imageList, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setImageList(imageList);
+        }
+
+        _dirty = true;
+    }
+
+    void Control::setCursor(Theme::Image* cursor, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setCursor(cursor);
+        }
+
+        _dirty = true;
+    }
+
+    void Control::setSkin(Theme::Skin* skin, unsigned char states)
+    {
+        overrideStyle();
+        Theme::Style::Overlay* overlays[Theme::Style::OVERLAY_MAX] = { 0 };
+        getOverlays(states, overlays);
+
+        for (int i = 0; i < Theme::Style::OVERLAY_MAX - 1 && overlays[i]; ++i)
+        {
+            overlays[i]->setSkin(skin);
+        }
+
+        _dirty = true;
+    }
+
     Control::Alignment Control::getAlignment(const char* alignment)
     {
         if (!alignment)

+ 9 - 0
gameplay/src/Control.h

@@ -23,6 +23,7 @@ class Control : public Ref, public AnimationTarget
     friend class Layout;
     friend class AbsoluteLayout;
     friend class VerticalLayout;
+    friend class FlowLayout;
 
 public:
 
@@ -827,6 +828,14 @@ private:
     Theme::Style::Overlay* getOverlay(Control::State state) const;
 
     void overrideStyle();
+
+    void overrideThemedProperties(Properties* properties, unsigned char states);
+
+    void setImageList(Theme::ImageList* imageList, unsigned char states = STATE_ALL);
+
+    void setCursor(Theme::Image* cursor, unsigned char states = STATE_ALL);
+
+    void setSkin(Theme::Skin* skin, unsigned char states = STATE_ALL);
     
     void addSpecificListener(Control::Listener* listener, Listener::EventType eventType);
     

+ 67 - 70
gameplay/src/Properties.h

@@ -22,48 +22,45 @@ namespace gameplay
  * Here's an example of a simple
  * file that uses all the available features of the markup language:
  
-\verbatim
---- File Start: example.properties ---
+@verbatim
+    // This is a comment.
  
-// This is a comment.
+    // This property is in the default namespace:
+    integerProperty = 5
  
-// This property is in the default namespace:
-integerProperty = 5
- 
-// This line defines a namespace of type "mynamespace" without an ID:
-mynamespace
-{
-    // This namespace can be retrieved by searching for its ID, "spriteTexture":
-    texture spriteTexture 
+    // This line defines a namespace of type "mynamespace" without an ID:
+    mynamespace
     {
-        fileName = sprite.png
-        width = 64
-        height = 64
-    }
+        // This namespace can be retrieved by searching for its ID, "spriteTexture":
+        texture spriteTexture 
+        {
+            fileName = sprite.png
+            width = 64
+            height = 64
+        }
  
-    // This property is in the "space" namespace:
-    booleanProperty = true
+        // This property is in the "space" namespace:
+        booleanProperty = true
  
-    // It's legal to have a name without a value if you leave out the '=' character:
-    foo
+        // It's legal to have a name without a value if you leave out the '=' character:
+        foo
  
-    // In fact, the '=' character is optional if you'd rather write:
-    bar 23
+        // In fact, the '=' character is optional if you'd rather write:
+        bar 23
  
-    // But don't write this or you'll get an error:
-    // illegalProperty =
+        // But don't write this or you'll get an error:
+        // illegalProperty =
  
-    // Or this:
-    // = 15
+        // Or this:
+        // = 15
  
-    // Properties objects let you retrieve values as various types.
-    floatProperty = 3.333
-    stringProperty = This is a string.
-    vector3Property = 1.0, 5.0, 3.55
-    colorProperty = 1.0, 0.4, 0.0, 1.0
-}
---- File End ---
-\endverbatim
+        // Properties objects let you retrieve values as various types.
+        floatProperty = 3.333
+        stringProperty = This is a string.
+        vector3Property = 1.0, 5.0, 3.55
+        colorProperty = 1.0, 0.4, 0.0, 1.0
+    }
+@endverbatim
  
  * Retrieving information out of a file like this could be done in two ways.  If the
  * available namespaces and name/value pairs are known in advance they can be queried by ID or name.
@@ -72,54 +69,54 @@ mynamespace
  * A namespace is stored and retrieved as a Properties object.
  * Reading the spriteTexture properties out of the file above in this way could be done with the following code:
  
-\verbatim
-// Create the top-level Properties object.
-Properties* properties = Properties::create("example.properties");
-// Retrieve the "spriteTexture" namespace.
-Properties* spriteTexture = properties->getNamespace("spriteTexture");
+@verbatim
+    // Create the top-level Properties object.
+    Properties* properties = Properties::create("example.properties");
+    // Retrieve the "spriteTexture" namespace.
+    Properties* spriteTexture = properties->getNamespace("spriteTexture");
  
-// Get the values of known texture properties out of the namespace.
-const char* fileName = spriteTexture->getString("fileName");
-int width = spriteTexture->getInt("width");
-int height = spriteTexture->getInt("height");
+    // Get the values of known texture properties out of the namespace.
+    const char* fileName = spriteTexture->getString("fileName");
+    int width = spriteTexture->getInt("width");
+    int height = spriteTexture->getInt("height");
  
-// Deleting the top-level Properties object will clean up all nested namespaces.
-SAFE_DELETE(properties);
-\endverbatim
+    // Deleting the top-level Properties object will clean up all nested namespaces.
+    SAFE_DELETE(properties);
+@endverbatim
 
  * On the other hand, if the structure of the file is not known in advance its 
  * namespaces and name/value pairs can be retrieved one by one using the getNextNamespace()
  * and getNextProperty() methods.  The following method prints the contents of any properties file
  * to the console:
  
-\verbatim
-void printProperties(Properties* properties)
-{
-    // Print the name and ID of the current namespace.
-    const char* spacename = properties->getNamespace();
-    const char* id = properties->getId();
-    WARN_VARG("Namespace: %s  ID: %s\n{", spacename, id);
- 
-    // Print all properties in this namespace.
-    const char* name = properties->getNextProperty();
-    const char* value = NULL;
-    while (name != NULL)
+@verbatim
+    void printProperties(Properties* properties)
     {
-        value = properties->getString(name);
-        WARN_VARG("%s = %s", name, value);
-        name = properties->getNextProperty();
-    }
-    WARN("}\n");
+        // Print the name and ID of the current namespace.
+        const char* spacename = properties->getNamespace();
+        const char* id = properties->getId();
+        WARN_VARG("Namespace: %s  ID: %s\n{", spacename, id);
  
-    // Print the properties of every namespace within this one.
-    Properties* space = properties->getNextNamespace();
-    while (space != NULL)
-    {
-        printProperties(space);
-        space = properties->getNextNamespace();
+        // Print all properties in this namespace.
+        const char* name = properties->getNextProperty();
+        const char* value = NULL;
+        while (name != NULL)
+        {
+            value = properties->getString(name);
+            WARN_VARG("%s = %s", name, value);
+            name = properties->getNextProperty();
+        }
+        WARN("}\n");
+ 
+        // Print the properties of every namespace within this one.
+        Properties* space = properties->getNextNamespace();
+        while (space != NULL)
+        {
+            printProperties(space);
+            space = properties->getNextNamespace();
+        }
     }
-}
-\endverbatim
+@endverbatim
 
  * Note that this method does not keep track of the namespace hierarchy, but could be
  * modified to do so.  Also note that nothing in a properties file indicates the type

+ 1 - 1
gameplay/src/Theme.cpp

@@ -394,7 +394,7 @@ namespace gameplay
                     disabled->addRef();
                 }
 
-                Theme::Style* s = new Theme::Style(space->getId(), tw, th, margin, padding, normal, focus, active, disabled);
+                Theme::Style* s = new Theme::Style(theme, space->getId(), tw, th, margin, padding, normal, focus, active, disabled);
                 theme->_styles.push_back(s);
             }
 

+ 4 - 4
gameplay/src/ThemeStyle.cpp

@@ -6,10 +6,10 @@ namespace gameplay
 /****************
  * Theme::Style *
  ****************/
-Theme::Style::Style(const char* id, float tw, float th,
+Theme::Style::Style(Theme* theme, const char* id, float tw, float th,
         const Theme::Margin& margin, const Theme::Padding& padding,
         Theme::Style::Overlay* normal, Theme::Style::Overlay* focus, Theme::Style::Overlay* active, Theme::Style::Overlay* disabled)
-    : _id(id), _tw(tw), _th(th), _margin(margin), _padding(padding)
+    : _theme(theme), _id(id), _tw(tw), _th(th), _margin(margin), _padding(padding)
 {
     _overlays[OVERLAY_NORMAL] = normal;
     _overlays[OVERLAY_FOCUS] = focus;
@@ -76,8 +76,8 @@ const Theme::Padding& Theme::Style::getPadding() const
 }
     
 /*************************
-    * Theme::Style::Overlay *
-    *************************/
+ * Theme::Style::Overlay *
+ *************************/
 Theme::Style::Overlay* Theme::Style::Overlay::create()
 {
     Overlay* overlay = new Overlay();

+ 3 - 2
gameplay/src/ThemeStyle.h

@@ -162,7 +162,7 @@ private:
     /**
      * Constructor.
      */
-    Style(const char* id, float tw, float th,
+    Style(Theme* theme, const char* id, float tw, float th,
           const Theme::Margin& margin, const Theme::Padding& padding,
           Overlay* normal, Overlay* focus, Overlay* active, Overlay* disabled);
 
@@ -209,7 +209,8 @@ private:
      * The margin is used by Layouts other than AbsoluteLayout to put space between Controls.
      */
     void setMargin(float top, float bottom, float left, float right);
-        
+    
+    Theme* _theme;
     std::string _id;
     float _tw;
     float _th;