Browse Source

Added CheckBox UI element.

Lasse Öörni 15 years ago
parent
commit
7d27a44d19

BIN
Bin/Data/Textures/UI.png


+ 11 - 1
Bin/Data/UI/UI.xml

@@ -1,11 +1,12 @@
 <elements>
     <element name="Cursor">
+        <size value="16 24" />
         <texture name="Textures/UI.png" />
         <imagerect value="0 0 16 24" />
         <hotspot value="0 0" />
-        <size value="16 24" />
     </element>
     <element name="Button">
+        <size value="16 16" />
         <texture name="Textures/UI.png" />
         <color value="0.85 0.85 0.85" />
         <hovercolor value="0.15 0.15 0.15" />
@@ -25,4 +26,13 @@
     <element name="Text">
         <font name="Cour.ttf" size="10" />
     </element>
+    <element name="CheckBox">
+        <size value="16 16" />
+        <texture name="Textures/UI.png" />
+        <color value="0.85 0.85 0.85" />
+        <hovercolor value="0.15 0.15 0.15" />
+        <uncheckedrect value="64 0 80 16" />
+        <checkedrect value="80 0 96 16" />
+        <border value="4 4 4 4" />
+    </element>
 </elements>

+ 1 - 1
Engine/Engine/Engine.cpp

@@ -98,7 +98,7 @@ Engine::Engine(const std::string& logFileName, bool headless) :
         "ControlsUpdate", "ControlsPlayback", "MouseButtonDown", "MouseButtonUp", "MouseMove", "KeyDown", "KeyUp", "Char",
         "PeerConnected", "NetworkPacket", "PeerDisconnected", "PhysicsPreStep", "PhysicsPostStep", "PhysicsCollision",
         "EntityCollision", "WindowMessage", "WindowResized", "BeginFrame", "EndFrame", "SceneUpdate", "ScenePostUpdate",
-        "AsyncLoadProgress", "AsyncLoadFinished", "Focused", "Defocused", "Pressed", "Changed", ""
+        "AsyncLoadProgress", "AsyncLoadFinished", "Focused", "Defocused", "Pressed", "Toggled", ""
     };
     
     for (unsigned i = 0; inbuiltEvents[i].length(); ++i)

+ 18 - 1
Engine/Engine/RegisterUI.cpp

@@ -23,6 +23,7 @@
 
 #include "Precompiled.h"
 #include "Button.h"
+#include "CheckBox.h"
 #include "Cursor.h"
 #include "Engine.h"
 #include "Font.h"
@@ -129,6 +130,21 @@ static void registerButton(asIScriptEngine* engine)
     registerRefCasts<UIElement, Button>(engine, "UIElement", "Button");
 }
 
+static void registerCheckBox(asIScriptEngine* engine)
+{
+    registerBorderImage<CheckBox>(engine, "CheckBox");
+    engine->RegisterObjectMethod("CheckBox", "void loadParameters(XMLFile@+, const string& in)", asFUNCTION(UIElementLoadParameters), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("CheckBox", "void setChecked(bool)", asMETHOD(CheckBox, setChecked), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CheckBox", "void setUncheckedRect(const IntRect& in)", asMETHODPR(CheckBox, setUncheckedRect, (const IntRect&), void), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CheckBox", "void setUncheckedRect(int, int, int, int)", asMETHODPR(CheckBox, setUncheckedRect, (int, int, int, int), void), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CheckBox", "void setCheckedRect(const IntRect& in)", asMETHODPR(CheckBox, setCheckedRect, (const IntRect&), void), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CheckBox", "void setCheckedRect(int, int, int, int)", asMETHODPR(CheckBox, setCheckedRect, (int, int, int, int), void), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CheckBox", "bool isChecked() const", asMETHOD(CheckBox, isChecked), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CheckBox", "const IntRect& getUncheckedRect() const", asMETHOD(CheckBox, getUncheckedRect), asCALL_THISCALL);
+    engine->RegisterObjectMethod("CheckBox", "const IntRect& getCheckedRect() const", asMETHOD(CheckBox, getCheckedRect), asCALL_THISCALL);
+    registerRefCasts<UIElement, CheckBox>(engine, "UIElement", "CheckBox");
+}
+
 static void registerWindow(asIScriptEngine* engine)
 {
     registerBorderImage<Window>(engine, "Window");
@@ -193,8 +209,9 @@ void registerUILibrary(asIScriptEngine* engine)
     registerUIElement(engine);
     registerText(engine);
     registerBorderImage(engine);
-    registerCursor(engine);
     registerButton(engine);
+    registerCheckBox(engine);
+    registerCursor(engine);
     registerWindow(engine);
     registerUI(engine);
 }

+ 15 - 23
Engine/UI/Button.cpp

@@ -35,7 +35,7 @@ Button::Button(const std::string& name) :
     mInactiveRect(0, 0, 0, 0),
     mPressedRect(0, 0, 0, 0),
     mLabelOffset(0, 0),
-    mState(BUTTON_INACTIVE)
+    mPressed(false)
 {
     mClipChildren = true;
     mEnabled = true;
@@ -64,23 +64,21 @@ XMLElement Button::loadParameters(XMLFile* file, const std::string& elementName,
 void Button::update(float timeStep)
 {
     if (!mHovering)
-        setState(BUTTON_INACTIVE);
+        setPressed(false);
+    
     if (mLabelContainer->getSize() != getSize())
         mLabelContainer->setSize(getSize());
 }
 
 void Button::getBatches(std::vector<UIBatch>& batches, std::vector<UIQuad>& quads, const IntRect& currentScissor)
 {
-    switch (mState)
-    {
-    default:
-        mImageRect = mInactiveRect;
-        break;
-        
-    case BUTTON_PRESSED:
+    if (mLabelContainer->getSize() != getSize())
+        mLabelContainer->setSize(getSize());
+    
+    if (mPressed)
         mImageRect = mPressedRect;
-        break;
-    }
+    else
+        mImageRect = mInactiveRect;
     
     BorderImage::getBatches(batches, quads, currentScissor);
     mHovering = false;
@@ -88,10 +86,7 @@ void Button::getBatches(std::vector<UIBatch>& batches, std::vector<UIQuad>& quad
 
 void Button::onHover(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons)
 {
-    if (buttons & MOUSEB_LEFT)
-        setState(BUTTON_PRESSED);
-    else
-        setState(BUTTON_INACTIVE);
+    setPressed((buttons & MOUSEB_LEFT) != 0);
     mHovering = true;
 }
 
@@ -99,7 +94,7 @@ void Button::onClick(const IntVector2& position, const IntVector2& screenPositio
 {
     if (buttons & MOUSEB_LEFT)
     {
-        setState(BUTTON_PRESSED);
+        setPressed(true);
         mHovering = true;
         
         using namespace Pressed;
@@ -153,19 +148,16 @@ void Button::setLabelOffset(int x, int y)
     mLabelOffset = IntVector2(x, y);
 }
 
-void Button::setState(ButtonState state)
+void Button::setPressed(bool enable)
 {
-    if (state != mState)
+    if (enable != mPressed)
     {
-        mState = state;
+        mPressed = enable;
         updateLabelOffset();
     }
 }
 
 void Button::updateLabelOffset()
 {
-    if (mState == BUTTON_PRESSED)
-        mLabelContainer->setPosition(mLabelOffset);
-    else
-        mLabelContainer->setPosition(IntVector2::sZero);
+    mLabelContainer->setPosition(mPressed ? mLabelOffset : IntVector2::sZero);
 }

+ 4 - 11
Engine/UI/Button.h

@@ -26,13 +26,6 @@
 
 #include "BorderImage.h"
 
-//! Button UI element states
-enum ButtonState
-{
-    BUTTON_INACTIVE = 0,
-    BUTTON_PRESSED
-};
-
 //! An image that reacts to mouse presses
 class Button : public BorderImage
 {
@@ -78,8 +71,8 @@ public:
     const IntVector2& getLabelOffset() const { return mLabelOffset; }
     
 protected:
-    //! Set new state
-    void setState(ButtonState state);
+    //! Set new pressed state
+    void setPressed(bool enable);
     //! Set offset of label depending on button press state
     void updateLabelOffset();
     
@@ -93,8 +86,8 @@ protected:
     IntRect mPressedRect;
     //! Label offset on press
     IntVector2 mLabelOffset;
-    //! Current state
-    ButtonState mState;
+    //! Current pressed state
+    bool mPressed;
 };
 
 #endif // UI_BUTTON_H

+ 108 - 0
Engine/UI/CheckBox.cpp

@@ -0,0 +1,108 @@
+//
+// Urho3D Engine
+// Copyright (c) 2008-2011 Lasse Öörni
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#include "Precompiled.h"
+#include "CheckBox.h"
+#include "InputEvents.h"
+#include "ResourceCache.h"
+#include "Texture.h"
+#include "UIEvents.h"
+
+#include "DebugNew.h"
+
+CheckBox::CheckBox(const std::string& name) :
+    BorderImage(name),
+    mUncheckedRect(0, 0, 0, 0),
+    mCheckedRect(0, 0, 0, 0),
+    mChecked(false)
+{
+    mEnabled = true;
+}
+
+CheckBox::~CheckBox()
+{
+}
+
+XMLElement CheckBox::loadParameters(XMLFile* file, const std::string& elementName, ResourceCache* cache)
+{
+    XMLElement paramElem = BorderImage::loadParameters(file, elementName, cache);
+    
+    if (paramElem.hasChildElement("uncheckedrect"))
+        setUncheckedRect(paramElem.getChildElement("uncheckedrect").getIntRect("value"));
+    if (paramElem.hasChildElement("checkedrect"))
+        setCheckedRect(paramElem.getChildElement("checkedrect").getIntRect("value"));
+    
+    return paramElem;
+}
+
+void CheckBox::getBatches(std::vector<UIBatch>& batches, std::vector<UIQuad>& quads, const IntRect& currentScissor)
+{
+    if (mChecked)
+        mImageRect = mCheckedRect;
+    else
+        mImageRect = mUncheckedRect;
+    
+    BorderImage::getBatches(batches, quads, currentScissor);
+    mHovering = false;
+}
+
+void CheckBox::onClick(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons)
+{
+    if (buttons & MOUSEB_LEFT)
+    {
+        mChecked = !mChecked;
+        
+        using namespace Toggled;
+        
+        VariantMap eventData;
+        eventData[P_ELEMENT] = (void*)this;
+        eventData[P_STATE] = mChecked;
+        sendEvent(EVENT_TOGGLED, eventData);
+    }
+}
+
+void CheckBox::setChecked(bool enable)
+{
+    // Note: event is intentionally not sent when manually set
+    mChecked = enable;
+}
+
+void CheckBox::setUncheckedRect(const IntRect& rect)
+{
+    mUncheckedRect = rect;
+}
+
+void CheckBox::setUncheckedRect(int left, int top, int right, int bottom)
+{
+    mUncheckedRect = IntRect(left, top, right, bottom);
+}
+
+void CheckBox::setCheckedRect(const IntRect& rect)
+{
+    mCheckedRect = rect;
+}
+
+void CheckBox::setCheckedRect(int left, int top, int right, int bottom)
+{
+    mCheckedRect = IntRect(left, top, right, bottom);
+}

+ 71 - 0
Engine/UI/CheckBox.h

@@ -0,0 +1,71 @@
+//
+// Urho3D Engine
+// Copyright (c) 2008-2011 Lasse Öörni
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+#ifndef UI_CHECKBOX_H
+#define UI_CHECKBOX_H
+
+#include "BorderImage.h"
+
+class CheckBox : public BorderImage
+{
+public:
+    //! Construct with name
+    CheckBox(const std::string& name = std::string());
+    //! Destruct
+    virtual ~CheckBox();
+    
+    //! Load parameters from an XML file
+    virtual XMLElement loadParameters(XMLFile* file, const std::string& elementName, ResourceCache* cache);
+    //! Return UI rendering batches
+    virtual void getBatches(std::vector<UIBatch>& batches, std::vector<UIQuad>& quads, const IntRect& currentScissor);
+    //! React to mouse click
+    virtual void onClick(const IntVector2& position, const IntVector2& screenPosition, unsigned buttons);
+    
+    //! Set checked state
+    void setChecked(bool enable);
+    //! Set unchecked image rectangle
+    void setUncheckedRect(const IntRect& rect);
+    //! Set unchecked image rectangle
+    void setUncheckedRect(int left, int top, int right, int bottom);
+    //! Set checked image rectangle
+    void setCheckedRect(const IntRect& rect);
+    //! Set checked image rectangle
+    void setCheckedRect(int left, int top, int right, int bottom);
+    
+    //! Return whether is checked
+    bool isChecked() const { return mChecked; }
+    //! Return unchecked image rectangle
+    const IntRect& getUncheckedRect() const { return mUncheckedRect; }
+    //! Return checked image rectangle
+    const IntRect& getCheckedRect() const { return mCheckedRect; }
+    
+protected:
+    //! Unchecked image rectangle
+    IntRect mUncheckedRect;
+    //! Checked image rectangle
+    IntRect mCheckedRect;
+    //! Current checked state
+    bool mChecked;
+};
+
+#endif // UI_CHECKBOX_H

+ 3 - 2
Engine/UI/UIEvents.h

@@ -44,10 +44,11 @@ DEFINE_EVENT(EVENT_PRESSED, Pressed)
     EVENT_PARAM(P_ELEMENT, Element);            // UIElement pointer
 }
 
-//! UI element has changed in some way
-DEFINE_EVENT(EVENT_CHANGED, Changed)
+//! UI checkbox toggled
+DEFINE_EVENT(EVENT_TOGGLED, Toggled)
 {
     EVENT_PARAM(P_ELEMENT, Element);            // UIElement pointer
+    EVENT_PARAM(P_STATE, State);                // bool
 }
 
 #endif // UI_UIEVENTS_H

+ 10 - 1
Examples/Test/Application.cpp

@@ -29,6 +29,7 @@
 #include "Application.h"
 #include "BillboardSet.h"
 #include "Button.h"
+#include "CheckBox.h"
 #include "CollisionShape.h"
 #include "Cursor.h"
 #include "CustomObject.h"
@@ -205,7 +206,7 @@ void Application::init()
     cursor->setPosition(renderer->getWidth() / 2, renderer->getHeight() / 2);
     ui->setCursor(cursor);
     
-    //Button* button = new Button("Testbutton");
+    //Button* button = new Button("TestButton");
     //button->loadParameters(uiSetup, "Button", mCache);
     //Text* text = new Text("TEST");
     //text->setFont(mCache->getResource<Font>("cour.ttf"), 12);
@@ -213,6 +214,14 @@ void Application::init()
     //button->setAlignment(HA_CENTER, VA_CENTER);
     //button->setSize(100, 40);
     //uiRoot->addChild(button);
+    //
+    //for (unsigned i = 0; i < 4; ++i)
+    //{
+    //    CheckBox* checkBox = new CheckBox("TestCheckBox" + toString(i));
+    //    checkBox->loadParameters(uiSetup, "CheckBox", mCache);
+    //    checkBox->setPosition(renderer->getWidth() / 3, renderer->getHeight() / 3 + 32 * i);
+    //    uiRoot->addChild(checkBox);
+    //}
     
     mScene = mEngine->createScene();
     PhysicsWorld* world = mScene->getExtension<PhysicsWorld>();