Browse Source

Merge pull request #887 from ablake/next

Next
Sean Paul Taylor 13 years ago
parent
commit
6566aa07ee

+ 2 - 0
gameplay/gameplay.vcxproj

@@ -91,6 +91,7 @@
     <ClCompile Include="src\gameplay-main-windows.cpp" />
     <ClCompile Include="src\HeightField.cpp" />
     <ClCompile Include="src\Image.cpp" />
+    <ClCompile Include="src\ImageControl.cpp" />
     <ClCompile Include="src\Joint.cpp" />
     <ClCompile Include="src\Joystick.cpp" />
     <ClCompile Include="src\Label.cpp" />
@@ -367,6 +368,7 @@
     <ClInclude Include="src\Gesture.h" />
     <ClInclude Include="src\HeightField.h" />
     <ClInclude Include="src\Image.h" />
+    <ClInclude Include="src\ImageControl.h" />
     <ClInclude Include="src\Joint.h" />
     <ClInclude Include="src\Joystick.h" />
     <ClInclude Include="src\Keyboard.h" />

+ 6 - 0
gameplay/gameplay.vcxproj.filters

@@ -843,6 +843,9 @@
     <ClCompile Include="src\Platform.cpp">
       <Filter>src</Filter>
     </ClCompile>
+    <ClCompile Include="src\ImageControl.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\Animation.h">
@@ -1670,6 +1673,9 @@
     <ClInclude Include="src\lua\lua_HeightField.h">
       <Filter>src\lua</Filter>
     </ClInclude>
+    <ClInclude Include="src\ImageControl.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <None Include="src\Game.inl">

+ 5 - 0
gameplay/src/Container.cpp

@@ -10,6 +10,7 @@
 #include "RadioButton.h"
 #include "Slider.h"
 #include "TextBox.h"
+#include "ImageControl.h"
 #include "Joystick.h"
 #include "Game.h"
 
@@ -165,6 +166,10 @@ void Container::addControls(Theme* theme, Properties* properties)
         {
             control = Joystick::create(controlStyle, controlSpace);
         }
+        else if (controlName == "IMAGE")
+        {
+            control = ImageControl::create(controlStyle, controlSpace);
+        }
         else
         {
             // Ignore - not a valid control name.

+ 34 - 1
gameplay/src/Form.cpp

@@ -586,6 +586,21 @@ const char* Form::getType() const
     return "form";
 }
 
+void Form::updateInternal(float elapsedTime)
+{
+    size_t size = __forms.size();
+    for (size_t i = 0; i < size; ++i)
+    {
+        Form* form = __forms[i];
+        GP_ASSERT(form);
+
+        if (form->isEnabled() && form->isVisible())
+        {
+            form->update(elapsedTime);
+        }
+    }
+}
+
 bool Form::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
 {
     // Check for a collision with each Form in __forms.
@@ -643,7 +658,7 @@ bool Form::keyEventInternal(Keyboard::KeyEvent evt, int key)
     {
         Form* form = __forms[i];
         GP_ASSERT(form);
-        if (form->isEnabled() && form->isVisible())
+        if (form->isEnabled() && form->isVisible() && form->getState() == Control::FOCUS)
         {
             if (form->keyEvent(evt, key))
                 return true;
@@ -706,6 +721,24 @@ bool Form::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelt
     return eventConsumed;
 }
 
+bool Form::gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex)
+{
+    bool eventConsumed = false;
+
+    for (size_t i = 0; i < __forms.size(); ++i)
+    {
+        Form* form = __forms[i];
+        GP_ASSERT(form);
+
+        if (form->isEnabled() && form->isVisible())
+        {
+            eventConsumed |= form->gamepadEvent(evt, gamepad, analogIndex);
+        }
+    }
+
+    return eventConsumed;
+}
+
 bool Form::projectPoint(int x, int y, Vector3* point)
 {
     Scene* scene = _node->getScene();

+ 9 - 0
gameplay/src/Form.h

@@ -48,6 +48,8 @@ class Theme;
 class Form : public Container
 {
     friend class Platform;
+    friend class Game;
+    friend class Gamepad;
 
 public:
 
@@ -188,6 +190,11 @@ private:
      */
     void updateBounds();
 
+    /**
+     * Updates all visible, enabled forms.
+     */
+    static void updateInternal(float elapsedTime);
+
     /**
      * Propagate touch events to enabled forms.
      *
@@ -211,6 +218,8 @@ private:
      */
     static bool mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelta);
 
+    static bool gamepadEventInternal(Gamepad::GamepadEvent evt, Gamepad* gamepad, unsigned int analogIndex);
+
     /**
      * Get the next highest power of two of an integer.  Used when creating framebuffers.
      *

+ 12 - 0
gameplay/src/Game.cpp

@@ -322,6 +322,12 @@ void Game::frame()
         // Update AI.
         _aiController->update(elapsedTime);
 
+        // Update gamepads.
+        Gamepad::updateInternal(elapsedTime);
+
+        // Update forms.
+        Form::updateInternal(elapsedTime);
+
         // Application Update.
         update(elapsedTime);
 
@@ -348,6 +354,12 @@ void Game::frame()
     }
 	else if (_state == Game::PAUSED)
     {
+        // Update gamepads.
+        Gamepad::updateInternal(0);
+
+        // Update forms.
+        Form::updateInternal(0);
+
         // Application Update.
         update(0);
 

+ 57 - 7
gameplay/src/Gamepad.cpp

@@ -3,6 +3,8 @@
 #include "Game.h"
 #include "Button.h"
 #include "Platform.h"
+#include "Form.h"
+#include "Joystick.h"
 
 namespace gameplay
 {
@@ -23,6 +25,7 @@ Gamepad::Gamepad(const char* formPath)
     for (int i = 0; i < 2; ++i)
     {
         _uiJoysticks[i] = NULL;
+        _triggers[i] = 0.0f;
     }
 
     for (int i = 0; i < 20; ++i)
@@ -47,6 +50,11 @@ Gamepad::Gamepad(GamepadHandle handle, unsigned int buttonCount, unsigned int jo
     {
         _productString = productString;
     }
+
+    for (int i = 0; i < 2; ++i)
+    {
+        _triggers[i] = 0.0f;
+    }
 }
 
 Gamepad::~Gamepad()
@@ -181,6 +189,19 @@ Gamepad* Gamepad::getGamepad(unsigned int index, bool preferPhysical)
     return backupVirtual;
 }
 
+Gamepad* Gamepad::getGamepad(GamepadHandle handle)
+{
+    unsigned int count = __gamepads.size();
+    for (unsigned int i = 0; i < count; ++i)
+    {
+        if (__gamepads[i]->_handle == handle)
+        {
+            return __gamepads[i];
+        }
+    }
+    return NULL;
+}
+
 Gamepad::ButtonMapping Gamepad::getButtonMappingFromString(const char* string)
 {
     if (strcmp(string, "A") == 0 || strcmp(string, "BUTTON_A") == 0)
@@ -250,16 +271,18 @@ const char* Gamepad::getProductString() const
 
 void Gamepad::update(float elapsedTime)
 {
-    if (_form)
+    if (!_form)
     {
-        if (_form->isEnabled())
-        {
-            _form->update(elapsedTime);
-        }
+        Platform::pollGamepadState(this);
     }
-    else
+}
+
+void Gamepad::updateInternal(float elapsedTime)
+{
+    unsigned int size = __gamepads.size();
+    for (unsigned int i = 0; i < size; ++i)
     {
-        Platform::pollGamepadState(this);
+        __gamepads[i]->update(elapsedTime);
     }
 }
 
@@ -356,4 +379,31 @@ Form* Gamepad::getForm() const
     return _form;
 }
 
+void Gamepad::setButtons(unsigned int buttons)
+{
+    if (buttons != _buttons)
+    {
+        _buttons = buttons;
+        Form::gamepadEventInternal(BUTTONS_EVENT, this, 0);
+    }
+}
+
+void Gamepad::setJoystickValue(unsigned int index, float x, float y)
+{
+    if (_joysticks[index].x != x || _joysticks[index].y != y)
+    {
+        _joysticks[index].set(x, y);
+        Form::gamepadEventInternal(JOYSTICK_EVENT, this, index);
+    }
+}
+
+void Gamepad::setTriggerValue(unsigned int index, float value)
+{
+    if (_triggers[index] != value)
+    {
+        _triggers[index] = value;
+        Form::gamepadEventInternal(TRIGGER_EVENT, this, index);
+    }
+}
+
 }

+ 21 - 7
gameplay/src/Gamepad.h

@@ -1,14 +1,16 @@
 #ifndef GAMEPAD_H_
 #define GAMEPAD_H_
 
-#include "Form.h"
-#include "Joystick.h"
+#include "Vector2.h"
 
 namespace gameplay
 {
 
-class Platform;
 class Button;
+class Container;
+class Form;
+class Joystick;
+class Platform;
 
 /**
  * Defines an interface for handling gamepad input.
@@ -17,7 +19,6 @@ class Gamepad
 {
     friend class Platform;
     friend class Game;
-    friend class Control;
     friend class Button;
 
 public:
@@ -28,7 +29,10 @@ public:
     enum GamepadEvent
     {
         CONNECTED_EVENT,
-        DISCONNECTED_EVENT
+        DISCONNECTED_EVENT,
+        BUTTONS_EVENT,
+        JOYSTICK_EVENT,
+        TRIGGER_EVENT
     };
 
     /**
@@ -196,6 +200,8 @@ private:
      */
     Gamepad(const Gamepad& copy);
 
+    static void updateInternal(float elapsedTime);
+
     static Gamepad* add(GamepadHandle handle, 
                         unsigned int buttonCount, unsigned int joystickCount, unsigned int triggerCount,
                         unsigned int vendorId, unsigned int productId, 
@@ -211,8 +217,18 @@ private:
 
     static Gamepad* getGamepad(unsigned int index, bool preferPhysical = true);
 
+    static Gamepad* getGamepad(GamepadHandle handle);
+
     static ButtonMapping getButtonMappingFromString(const char* string);
 
+    // The following setters are used by platforms when polling or handling gamepad events at the platform layer.
+    // They trigger gamepad state-changed events on forms as necessary.
+    void setButtons(unsigned int buttons);
+
+    void setJoystickValue(unsigned int index, float x, float y);
+
+    void setTriggerValue(unsigned int index, float value);
+
     /** 
      * Destructor.
      */
@@ -223,8 +239,6 @@ private:
      */
     void bindGamepadControls(Container* container);
 
-    static unsigned int getIndexFromMapping(Gamepad::ButtonMapping mapping);
-
     GamepadHandle _handle;        // The handle of the Gamepad.
     unsigned int _buttonCount;    // Number of buttons.
     unsigned int _joystickCount;  // Number of joysticks.

+ 88 - 0
gameplay/src/ImageControl.cpp

@@ -0,0 +1,88 @@
+#include "Base.h"
+#include "ImageControl.h"
+
+namespace gameplay
+{
+
+ImageControl::ImageControl() : _image(NULL), _texture(NULL), _batch(NULL)
+{
+}
+
+ImageControl::~ImageControl()
+{
+    SAFE_RELEASE(_image);
+    SAFE_RELEASE(_texture);
+    SAFE_DELETE(_batch);
+}
+
+ImageControl* ImageControl::create(const char* id, Theme::Style* style)
+{
+    GP_ASSERT(style);
+
+    ImageControl* imageControl = new ImageControl();
+    if (id)
+        imageControl->_id = id;
+    imageControl->setStyle(style);
+
+    return imageControl;
+}
+
+ImageControl* ImageControl::create(Theme::Style* style, Properties* properties)
+{
+    ImageControl* imageControl = new ImageControl();
+    imageControl->initialize(style, properties);
+    return imageControl;
+}
+
+void ImageControl::initialize(Theme::Style* style, Properties* properties)
+{
+    GP_ASSERT(properties);
+
+    Control::initialize(style, properties);
+
+    const char* path = properties->getString("path");
+    if (path)
+    {
+        setImage(path);
+    }
+}
+
+void ImageControl::setImage(const char* path)
+{
+    SAFE_RELEASE(_image);
+    SAFE_RELEASE(_texture);
+    SAFE_DELETE(_batch);
+
+    _image = Image::create(path);
+    _texture = Texture::create(_image);
+    _batch = SpriteBatch::create(_texture);
+}
+
+void ImageControl::setImage(Image* image)
+{
+    SAFE_RELEASE(_image);
+    SAFE_RELEASE(_texture);
+    SAFE_DELETE(_batch);
+
+    image->addRef();
+    _image = image;
+    _texture = Texture::create(_image);
+    _batch = SpriteBatch::create(_texture);
+}
+
+void ImageControl::drawImages(SpriteBatch* spriteBatch, const Rectangle& clip)
+{
+    spriteBatch->finish();
+
+    // An ImageControl is not part of the texture atlas but should use the same projection matrix.
+    _batch->setProjectionMatrix(spriteBatch->getProjectionMatrix());
+
+    _batch->start();
+    _batch->draw(_viewportBounds.x, _viewportBounds.y, _viewportBounds.width, _viewportBounds.height,
+        0.0f, 0.0f, 1.0f, 1.0f, Vector4::one(), _viewportClipBounds);
+    _batch->finish();
+
+    spriteBatch->start();
+}
+
+}

+ 52 - 0
gameplay/src/ImageControl.h

@@ -0,0 +1,52 @@
+#ifndef IMAGECONTROL_H_
+#define IMAGECONTROL_H_
+
+#include "Control.h"
+#include "Theme.h"
+#include "Image.h"
+#include "SpriteBatch.h"
+
+namespace gameplay
+{
+
+class ImageControl : public Control
+{
+    friend class Container;
+
+public:
+
+    static ImageControl* create(const char* id, Theme::Style* style);
+
+    void setImage(const char* path);
+    void setImage(Image* image);
+    //void setImageData(const char* data);
+
+    Image* getImage() const;
+
+protected:
+
+    ImageControl();
+    
+    virtual ~ImageControl();
+
+    static ImageControl* create(Theme::Style* style, Properties* properties);
+
+    virtual void initialize(Theme::Style* style, Properties* properties);
+
+    //void update(const Control* container, const Vector2& offset);
+
+    //void draw(SpriteBatch* spriteBatch, const Rectangle& clip, bool needsClear, bool cleared, float targetHeight);
+    void drawImages(SpriteBatch* spriteBatch, const Rectangle& clip);
+
+    Image* _image;
+    Texture* _texture;
+    SpriteBatch* _batch;
+
+private:
+
+    ImageControl(const ImageControl& copy);
+};
+
+}
+
+#endif

+ 1 - 0
gameplay/src/SpriteBatch.cpp

@@ -1,6 +1,7 @@
 #include "Base.h"
 #include "SpriteBatch.h"
 #include "Game.h"
+#include "Material.h"
 
 // Default size of a newly created sprite batch
 #define SPRITE_BATCH_DEFAULT_SIZE 128

+ 2 - 0
gameplay/src/lua/lua_Gamepad.cpp

@@ -3,8 +3,10 @@
 #include "lua_Gamepad.h"
 #include "Base.h"
 #include "Button.h"
+#include "Form.h"
 #include "Game.h"
 #include "Gamepad.h"
+#include "Joystick.h"
 #include "Platform.h"
 #include "lua_GamepadButtonMapping.h"
 

+ 15 - 0
gameplay/src/lua/lua_GamepadGamepadEvent.cpp

@@ -8,6 +8,9 @@ static const char* enumStringEmpty = "";
 
 static const char* luaEnumString_GamepadGamepadEvent_CONNECTED_EVENT = "CONNECTED_EVENT";
 static const char* luaEnumString_GamepadGamepadEvent_DISCONNECTED_EVENT = "DISCONNECTED_EVENT";
+static const char* luaEnumString_GamepadGamepadEvent_BUTTONS_EVENT = "BUTTONS_EVENT";
+static const char* luaEnumString_GamepadGamepadEvent_JOYSTICK_EVENT = "JOYSTICK_EVENT";
+static const char* luaEnumString_GamepadGamepadEvent_TRIGGER_EVENT = "TRIGGER_EVENT";
 
 Gamepad::GamepadEvent lua_enumFromString_GamepadGamepadEvent(const char* s)
 {
@@ -15,6 +18,12 @@ Gamepad::GamepadEvent lua_enumFromString_GamepadGamepadEvent(const char* s)
         return Gamepad::CONNECTED_EVENT;
     if (strcmp(s, luaEnumString_GamepadGamepadEvent_DISCONNECTED_EVENT) == 0)
         return Gamepad::DISCONNECTED_EVENT;
+    if (strcmp(s, luaEnumString_GamepadGamepadEvent_BUTTONS_EVENT) == 0)
+        return Gamepad::BUTTONS_EVENT;
+    if (strcmp(s, luaEnumString_GamepadGamepadEvent_JOYSTICK_EVENT) == 0)
+        return Gamepad::JOYSTICK_EVENT;
+    if (strcmp(s, luaEnumString_GamepadGamepadEvent_TRIGGER_EVENT) == 0)
+        return Gamepad::TRIGGER_EVENT;
     GP_ERROR("Invalid enumeration value '%s' for enumeration Gamepad::GamepadEvent.", s);
     return Gamepad::CONNECTED_EVENT;
 }
@@ -25,6 +34,12 @@ const char* lua_stringFromEnum_GamepadGamepadEvent(Gamepad::GamepadEvent e)
         return luaEnumString_GamepadGamepadEvent_CONNECTED_EVENT;
     if (e == Gamepad::DISCONNECTED_EVENT)
         return luaEnumString_GamepadGamepadEvent_DISCONNECTED_EVENT;
+    if (e == Gamepad::BUTTONS_EVENT)
+        return luaEnumString_GamepadGamepadEvent_BUTTONS_EVENT;
+    if (e == Gamepad::JOYSTICK_EVENT)
+        return luaEnumString_GamepadGamepadEvent_JOYSTICK_EVENT;
+    if (e == Gamepad::TRIGGER_EVENT)
+        return luaEnumString_GamepadGamepadEvent_TRIGGER_EVENT;
     GP_ERROR("Invalid enumeration value '%d' for enumeration Gamepad::GamepadEvent.", e);
     return enumStringEmpty;
 }

+ 3 - 0
gameplay/src/lua/lua_Global.cpp

@@ -377,6 +377,9 @@ void luaRegister_lua_Global()
         scopePath.push_back("Gamepad");
         gameplay::ScriptUtil::registerConstantString("CONNECTED_EVENT", "CONNECTED_EVENT", scopePath);
         gameplay::ScriptUtil::registerConstantString("DISCONNECTED_EVENT", "DISCONNECTED_EVENT", scopePath);
+        ScriptUtil::registerConstantString("BUTTONS_EVENT", "BUTTONS_EVENT", scopePath);
+        ScriptUtil::registerConstantString("JOYSTICK_EVENT", "JOYSTICK_EVENT", scopePath);
+        ScriptUtil::registerConstantString("TRIGGER_EVENT", "TRIGGER_EVENT", scopePath);
     }
 
     // Register enumeration Gesture::GestureEvent.