diff --git a/include/eepp/ui.hpp b/include/eepp/ui.hpp index b31699d98..23b3e89e5 100644 --- a/include/eepp/ui.hpp +++ b/include/eepp/ui.hpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include diff --git a/include/eepp/ui/uiloader.hpp b/include/eepp/ui/uiloader.hpp new file mode 100644 index 000000000..d2c34a200 --- /dev/null +++ b/include/eepp/ui/uiloader.hpp @@ -0,0 +1,71 @@ +#ifndef EE_UI_UILOADER_HPP +#define EE_UI_UILOADER_HPP + +#include +#include +#include + +namespace EE { namespace UI { + +class EE_API UILoader : public UIWidget { + public: + static UILoader * New(); + + UILoader(); + + virtual void draw(); + + virtual void update(); + + UILoader * setOutlineThickness( const Float& thickness ); + + const Float& getOutlineThickness() const; + + UILoader * setRadius( const Float& radius ); + + const Float& getRadius() const; + + UILoader * setFillColor( const ColorA& color ); + + const ColorA& getFillColor() const; + + const bool& isIndeterminate() const; + + UILoader * setIndeterminate( const bool& indeterminate ); + + UILoader * setProgress( const Float& progress ); + + const Float& getProgress() const; + + const Float& getMaxProgress() const; + + UILoader * setMaxProgress( const Float& maxProgress ); + + const Float& getAnimationSpeed() const; + + UILoader * setAnimationSpeed( const Float& animationSpeed ); + + virtual void loadFromXmlNode( const pugi::xml_node& node); + protected: + Float mRadius; + Float mOutlineThickness; + ArcDrawable mArc; + CircleDrawable mCircle; + ColorA mColor; + Float mArcAngle; + Float mArcStartAngle; + Float mProgress; + Float mMaxProgress; + Float mAnimationSpeed; + IntPtr mOp; + bool mIndeterminate; + bool mNeedsUpdate; + + virtual void onPositionChange(); + + virtual void onSizeChange(); +}; + +}} + +#endif diff --git a/projects/linux/ee.files b/projects/linux/ee.files index 1bda16342..2216c4f0a 100644 --- a/projects/linux/ee.files +++ b/projects/linux/ee.files @@ -68,6 +68,7 @@ ../../src/eepp/ui/uihelper.cpp ../../src/eepp/ui/uiimage.cpp ../../src/eepp/ui/uilinearlayout.cpp +../../src/eepp/ui/uiloader.cpp ../../src/eepp/ui/uimenuseparator.cpp ../../src/eepp/ui/uirelativelayout.cpp ../../src/eepp/ui/uisubtexture.cpp diff --git a/src/eepp/ui/uihelper.cpp b/src/eepp/ui/uihelper.cpp index b64989f09..e22e57020 100644 --- a/src/eepp/ui/uihelper.cpp +++ b/src/eepp/ui/uihelper.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include namespace EE { namespace UI { @@ -81,6 +82,8 @@ UIWidget * UIHelper::createUIWidgetFromName( std::string name ) { return UITextInput::New(); } else if ( name == "textinputpassword" || name == "inputpassword" ) { return UITextInputPassword::New(); + } else if ( name == "loader" ) { + return UILoader::New(); } else if ( name == "window" ) { return UIWindow::New(); } diff --git a/src/eepp/ui/uiloader.cpp b/src/eepp/ui/uiloader.cpp new file mode 100644 index 000000000..bd354a42f --- /dev/null +++ b/src/eepp/ui/uiloader.cpp @@ -0,0 +1,185 @@ +#include +#include +#include + +namespace EE { namespace UI { + +UILoader * UILoader::New() { + return eeNew( UILoader, () ); +} + +UILoader::UILoader() : + UIWidget(), + mRadius(0), + mOutlineThickness( PixelDensity::dpToPx(8) ), + mColor( 0x00FF00FF ), + mArcAngle(0), + mArcStartAngle(0), + mProgress(0), + mMaxProgress(100), + mAnimationSpeed(0.5f), + mOp(1), + mIndeterminate(true), + mNeedsUpdate(true) +{ + mArc.setFillMode( DRAW_FILL ); + mCircle.setFillMode( DRAW_FILL ); + setFillColor( mColor ); +} + +void UILoader::draw() { + UIWidget::draw(); + + if ( mNeedsUpdate ) { + mNeedsUpdate = false; + + Rectf rect( mScreenPosf, Sizef( mRealSize.x, mRealSize.y ) ); + mArc.setPosition( rect.getCenter() ); + mCircle.setPosition( rect.getCenter() ); + } + + ClippingMask * clippingMask = Renderer::instance()->getClippingMask(); + clippingMask->setMaskMode( ClippingMask::Exclusive ); + clippingMask->clearMasks(); + clippingMask->appendMask( mCircle ); + clippingMask->stencilMaskEnable(); + + mArc.draw(); + + clippingMask->stencilMaskDisable(); +} + +void UILoader::update() { + UIWidget::update(); + + if ( mIndeterminate ) { + mArcAngle += getElapsed().asMilliseconds() * mAnimationSpeed * mOp; + mArcStartAngle += getElapsed().asMilliseconds() * (mAnimationSpeed*1.5f); + + if ( mOp == 1 && mArcAngle > 340 ) { + mOp = -1; + } else if ( mOp == -1 && mArcAngle < 20 ) { + mOp = 1; + } + + mArc.setArcAngle( mArcAngle ); + mArc.setArcStartAngle( mArcStartAngle ); + } else { + mArcStartAngle += getElapsed().asMilliseconds() * (mAnimationSpeed*1.5f); + mArc.setArcStartAngle( mArcStartAngle ); + } +} + +UILoader * UILoader::setOutlineThickness( const Float& thickness ) { + mOutlineThickness = thickness; + mCircle.setRadius( PixelDensity::dpToPx( mRadius ) - mOutlineThickness ); + return this; +} + +const Float& UILoader::getOutlineThickness() const { + return mOutlineThickness; +} + +UILoader * UILoader::setRadius( const Float& radius ) { + mRadius = radius; + Float rRadius = PixelDensity::dpToPx( radius ); + mCircle.setRadius( rRadius - mOutlineThickness ); + mArc.setRadius( rRadius ); + return this; +} + +const Float& UILoader::getRadius() const { + return mRadius; +} + +UILoader * UILoader::setFillColor( const ColorA& color ) { + mColor = color; + mArc.setColor( mColor ); + mCircle.setColor( mColor ); + return this; +} + +const ColorA& UILoader::getFillColor() const { + return mColor; +} + +void UILoader::onPositionChange() { + mNeedsUpdate = true; +} + +void UILoader::onSizeChange() { + mNeedsUpdate = true; + + if ( mRadius == 0 ) { + setRadius( eemin( mSize.x, mSize.y ) / 2.f ); + } +} + +const bool& UILoader::isIndeterminate() const { + return mIndeterminate; +} + +UILoader * UILoader::setIndeterminate( const bool& indeterminate ) { + mIndeterminate = indeterminate; + return this; +} + +UILoader * UILoader::setProgress( const Float& progress ) { + mProgress = eemax( 0.f, eemin( progress, mMaxProgress ) ); + + if ( !mIndeterminate ) { + mArcAngle = progress / mMaxProgress * 360.f; + mArc.setArcAngle( mArcAngle ); + } + + return this; +} + +const Float& UILoader::getProgress() const { + return mProgress; +} + +const Float& UILoader::getMaxProgress() const { + return mMaxProgress; +} + +UILoader * UILoader::setMaxProgress( const Float& maxProgress ) { + mMaxProgress = maxProgress; + return this; +} + +const Float& UILoader::getAnimationSpeed() const { + return mAnimationSpeed; +} + +UILoader * UILoader::setAnimationSpeed( const Float& animationSpeed ) { + mAnimationSpeed = animationSpeed; + return this; +} + +void UILoader::loadFromXmlNode(const pugi::xml_node & node) { + UIWidget::loadFromXmlNode( node ); + + for (pugi::xml_attribute_iterator ait = node.attributes_begin(); ait != node.attributes_end(); ++ait) { + std::string name = ait->name(); + String::toLowerInPlace( name ); + + if ( "indeterminate" == name ) { + setIndeterminate( ait->as_bool() ); + } else if ( "maxprogress" == name ) { + setMaxProgress( ait->as_float() ); + } else if ( "progress" == name ) { + setProgress( ait->as_float() ); + } else if ( "fillcolor" == name ) { + setFillColor( ColorA::fromString( ait->as_string() ) ); + } else if ( "radius" == name ) { + setRadius( ait->as_float() ); + } else if ( "outlinethickness" == name ) { + setOutlineThickness( ait->as_float() ); + } else if ( "animationspeed" ) { + setAnimationSpeed( ait->as_float() ); + } + } +} + +}} diff --git a/src/examples/empty_window/empty_window.cpp b/src/examples/empty_window/empty_window.cpp index 18ca2e9f4..d9ede8885 100644 --- a/src/examples/empty_window/empty_window.cpp +++ b/src/examples/empty_window/empty_window.cpp @@ -1,10 +1,6 @@ #include EE::Window::Window * win = NULL; -float circ = 0, circ2 = 0; -int op = 1; -ArcDrawable arcDrawable( 200, 64 ); -CircleDrawable circleDrawableMask( 150, 64 ); void mainLoop() { @@ -26,34 +22,8 @@ void mainLoop() win->close(); } - circ += win->getElapsed().asMilliseconds() * 0.5f * op; - circ2 += win->getElapsed().asMilliseconds() * 0.75f; - - if ( op == 1 && circ > 340 ) - { - op = -1; - } - else if ( op == -1 && circ < 20 ) - { - op = 1; - } - - Vector2f winCenter( win->getWidth() * 0.5f, win->getHeight() * 0.5f ); - - ClippingMask * clippingMask = Renderer::instance()->getClippingMask(); - - circleDrawableMask.setPosition( winCenter ); - - clippingMask->setMaskMode( ClippingMask::Exclusive ); - clippingMask->clearMasks(); - clippingMask->appendMask( circleDrawableMask ); - clippingMask->stencilMaskEnable(); - - arcDrawable.setArcAngle( circ ); - arcDrawable.setArcStartAngle( circ2 ); - arcDrawable.draw( winCenter ); - - clippingMask->stencilMaskDisable(); + // Draw a circle + p.drawCircle( Vector2f( win->getWidth() * 0.5f, win->getHeight() * 0.5f ), 200, 50 ); // Draw frame win->display(); @@ -70,12 +40,6 @@ EE_MAIN_FUNC int main (int argc, char * argv []) // Set window background color win->setClearColor( Color( 50, 50, 50 ) ); - arcDrawable.setColor( ColorA( 0, 255, 0, 150 ) ); - arcDrawable.setFillMode( DRAW_FILL ); - - circleDrawableMask.setColor( ColorA( 0, 255, 0, 150 ) ); - circleDrawableMask.setFillMode( DRAW_FILL ); - // Set the MainLoop function and run it // This is the application loop, it will loop until the window is closed. // This is only a requirement if you want to support Emscripten builds ( WebGL + Canvas ). diff --git a/src/test/eetest.cpp b/src/test/eetest.cpp index dab7359c2..2d3e23927 100644 --- a/src/test/eetest.cpp +++ b/src/test/eetest.cpp @@ -510,6 +510,14 @@ void EETest::createUI() { void EETest::createNewUI() { std::vector str = getTestStringArr(); + UILoader * loader = UILoader::New(); + loader->setOutlineThickness(8) + ->setRadius( 25 ) + ->setOutlineThickness( 8 ) + ->setPosition( 800, 0 ) + ->setSize( 100, 100 ) + ->setBackgroundFillEnabled( true )->setColor( 0xCCCCCCCC ); + UIRadioButton * ctrl = UIRadioButton::New(); ctrl->setPosition( 50, 100 )->setSize( 200, 32 ); ctrl->setBackgroundFillEnabled( true )->setColor( 0x33333333 );