Some minor refactor for the CSS transitions. Starting new transition system.

--HG--
branch : dev
This commit is contained in:
Martín Lucas Golini
2019-11-27 01:39:33 -03:00
parent c22194c554
commit f7119463f1
17 changed files with 406 additions and 311 deletions

View File

@@ -50,6 +50,8 @@ class StyleSheetLength {
Float asDp( const Float& parentSize, const Sizef& viewSize, const Float& displayDpi, const Float& elFontSize = 12, const Float& globalFontSize = 12 ) const;
bool operator==( const StyleSheetLength& val );
StyleSheetLength& operator=( const StyleSheetLength& val );
StyleSheetLength& operator=( const Float& val );

View File

@@ -0,0 +1,69 @@
#ifndef EE_UI_CSS_STYLESHEETLENGTHTRANSITION_HPP
#define EE_UI_CSS_STYLESHEETLENGTHTRANSITION_HPP
#include <eepp/scene/action.hpp>
#include <eepp/math/ease.hpp>
#include <functional>
using namespace EE::Math;
using namespace EE::Scene;
namespace EE { namespace UI { namespace CSS {
class EE_API StyleSheetLengthTransition : public Action {
public:
typedef std::function<Float()> ContainerLengthProvider;
static StyleSheetLengthTransition * New( const std::string& propertyName, const std::string& startValue, const std::string& endValue, const Time& duration, const Ease::Interpolation& type = Ease::Linear );
void start() override;
void stop() override;
void update( const Time& time ) override;
bool isDone() override;
Float getCurrentProgress();
Action * clone() const override;
Action * reverse() const override;
const std::string& getPropertyName() const;
const std::string& getStartValue() const;
const std::string& getEndValue() const;
const Time& getDuration() const;
const Ease::Interpolation& getType() const;
const Time& getElapsed() const;
const Float& getContainerLength() const;
StyleSheetLengthTransition& setContainerLength(const Float& containerLength);
StyleSheetLengthTransition& setContainerLengthFunction(const ContainerLengthProvider& containerLengthProvider);
protected:
StyleSheetLengthTransition( const std::string& propertyName, const std::string& startValue, const std::string& endValue, const Time& duration, const Ease::Interpolation& type = Ease::Linear );
void onStart() override;
void onUpdate( const Time& time ) override;
std::string mPropertyName;
std::string mStartValue;
std::string mEndValue;
Time mDuration;
Time mElapsed;
Ease::Interpolation mType;
Float mContainerLength;
ContainerLengthProvider mContainerLengthFunction;
};
}}}
#endif

View File

@@ -17,6 +17,8 @@ class EE_API StyleSheetProperty {
const std::string& getName() const;
const Uint32& getNameHash() const;
const std::string& getValue() const;
const Uint32& getSpecificity() const;
@@ -32,8 +34,11 @@ class EE_API StyleSheetProperty {
const bool& isVolatile() const;
void setVolatile( const bool& isVolatile );
bool operator==( const StyleSheetProperty& property );
protected:
std::string mName;
Uint32 mNameHash;
std::string mValue;
Uint32 mSpecificity;
bool mVolatile;

View File

@@ -0,0 +1,42 @@
#ifndef EE_UI_CSS_TRANSITIONDEFINITION_HPP
#define EE_UI_CSS_TRANSITIONDEFINITION_HPP
#include <eepp/ui/css/stylesheetproperty.hpp>
#include <eepp/math/ease.hpp>
#include <eepp/system/time.hpp>
#include <map>
#include <vector>
using namespace EE::Math;
using namespace EE::System;
namespace EE { namespace UI { namespace CSS {
class EE_API TransitionDefinition {
public:
static std::map<std::string, TransitionDefinition> parseTransitionProperties( const std::vector<StyleSheetProperty>& styleSheetProperties );
TransitionDefinition() :
timingFunction( Ease::Linear )
{}
const std::string& getProperty() const { return property; }
Ease::Interpolation getTimingFunction() const { return timingFunction; }
const Time& getDelay() const { return delay; }
const Time& getDuration() const { return duration; }
std::string property;
Ease::Interpolation timingFunction;
Time delay;
Time duration;
};
typedef std::map<std::string, TransitionDefinition> TransitionsMap;
}}}
#endif

View File

@@ -197,9 +197,9 @@ class EE_API UINode : public Node {
virtual void setFocus();
virtual Float convertLength( const CSS::StyleSheetLength& length, const Sizef& drawableSize, const bool& percentAsWidth = true );
virtual Float convertLength( const CSS::StyleSheetLength& length, const Float& containerLength );
Float lengthAsDp( const CSS::StyleSheetLength& length, const Sizef& drawableSize, const bool& percentAsWidth = true );
Float convertLengthAsDp( const CSS::StyleSheetLength& length, const Float& containerLength );
protected:
Vector2f mDpPos;
Sizef mDpSize;

View File

@@ -26,40 +26,6 @@ class EE_API UINodeDrawable : public Drawable {
static Repeat repeatFromText( const std::string& text );
class EE_API MoveAction : public Action {
public:
static MoveAction * New( const std::string& posEqStart, const std::string& posEqEnd, const Time& duration, const Ease::Interpolation& type = Ease::Linear );
void start() override;
void stop() override;
void update( const Time& time ) override;
bool isDone() override;
Float getCurrentProgress();
Action * clone() const override;
Action * reverse() const override;
const Vector2f& getOffset() const { return mOffset; }
protected:
MoveAction( const std::string& posEqStart, const std::string& posEqEnd, const Time& duration, const Ease::Interpolation& type = Ease::Linear );
void onStart() override;
void onUpdate( const Time& time ) override;
std::string mStart;
std::string mEnd;
Time mDuration;
Ease::Interpolation mType;
Time mElapsed;
Vector2f mOffset;
};
class EE_API LayerDrawable : public Drawable {
public:
static LayerDrawable * New( UINodeDrawable * container );
@@ -111,10 +77,6 @@ class EE_API UINodeDrawable : public Drawable {
Sizef calcDrawableSize( const std::string& drawableSizeEq );
Vector2f calcPosition( const std::string& positionEq );
MoveAction * getMoveAction() const;
void setMoveAction(MoveAction * moveAction);
protected:
UINodeDrawable * mContainer;
Sizef mSize;
@@ -127,8 +89,6 @@ class EE_API UINodeDrawable : public Drawable {
Drawable * mDrawable;
Uint32 mResourceChangeCbId;
Repeat mRepeat;
MoveAction * mMoveAction;
Uint32 mMoveActionCbId;
virtual void onPositionChange();

View File

@@ -5,6 +5,7 @@
#include <eepp/scene/nodeattribute.hpp>
#include <eepp/ui/css/stylesheetproperty.hpp>
#include <eepp/ui/css/stylesheetstyle.hpp>
#include <eepp/ui/css/transitiondefinition.hpp>
#include <eepp/graphics/fontstyleconfig.hpp>
#include <eepp/math/ease.hpp>
#include <set>
@@ -22,27 +23,6 @@ class UIWidget;
class EE_API UIStyle : public UIState {
public:
class TransitionInfo
{
public:
TransitionInfo() :
timingFunction( Ease::Linear )
{}
const std::string& getProperty() const { return property; }
Ease::Interpolation getTimingFunction() const { return timingFunction; }
const Time& getDelay() const { return delay; }
const Time& getDuration() const { return duration; }
std::string property;
Ease::Interpolation timingFunction;
Time delay;
Time duration;
};
static UIStyle * New( UIWidget * widget );
explicit UIStyle( UIWidget * widget );
@@ -67,19 +47,17 @@ class EE_API UIStyle : public UIState {
bool hasTransition( const std::string& propertyName );
TransitionInfo getTransition( const std::string& propertyName );
CSS::TransitionDefinition getTransition( const std::string& propertyName );
const bool& isChangingState() const;
protected:
typedef std::map<std::string, TransitionInfo> TransitionsMap;
UIWidget * mWidget;
CSS::StyleSheetStyleVector mCacheableStyles;
CSS::StyleSheetStyleVector mNoncacheableStyles;
CSS::StyleSheetStyle mElementStyle;
CSS::StyleSheetProperties mProperties;
std::vector<CSS::StyleSheetProperty> mTransitionAttributes;
TransitionsMap mTransitions;
CSS::TransitionsMap mTransitions;
std::set<UIWidget*> mRelatedWidgets;
std::set<UIWidget*> mSubscribedWidgets;
bool mChangingState;
@@ -88,8 +66,6 @@ class EE_API UIStyle : public UIState {
void updateState();
void parseTransitions();
void subscribeNonCacheableStyles();
void unsubscribeNonCacheableStyles();

View File

@@ -292,6 +292,7 @@
../../include/eepp/ui/css/stylesheet.hpp
../../include/eepp/ui/css/stylesheetelement.hpp
../../include/eepp/ui/css/stylesheetlength.hpp
../../include/eepp/ui/css/stylesheetlengthtransition.hpp
../../include/eepp/ui/css/stylesheetparser.hpp
../../include/eepp/ui/css/stylesheetpropertiesparser.hpp
../../include/eepp/ui/css/stylesheetproperty.hpp
@@ -299,6 +300,7 @@
../../include/eepp/ui/css/stylesheetselectorparser.hpp
../../include/eepp/ui/css/stylesheetselectorrule.hpp
../../include/eepp/ui/css/stylesheetstyle.hpp
../../include/eepp/ui/css/transitiondefinition.hpp
../../include/eepp/ui/marginmove/scale.hpp
../../include/eepp/ui/tools/textureatlaseditor.hpp
../../include/eepp/ui/tools/uicolorpicker.hpp
@@ -712,6 +714,7 @@
../../src/eepp/system/zip.cpp
../../src/eepp/ui/css/stylesheet.cpp
../../src/eepp/ui/css/stylesheetlength.cpp
../../src/eepp/ui/css/stylesheetlengthtransition.cpp
../../src/eepp/ui/css/stylesheetparser.cpp
../../src/eepp/ui/css/stylesheetpropertiesparser.cpp
../../src/eepp/ui/css/stylesheetproperty.cpp
@@ -719,6 +722,7 @@
../../src/eepp/ui/css/stylesheetselectorparser.cpp
../../src/eepp/ui/css/stylesheetselectorrule.cpp
../../src/eepp/ui/css/stylesheetstyle.cpp
../../src/eepp/ui/css/transitiondefinition.cpp
../../src/eepp/ui/tools/textureatlaseditor.cpp
../../src/eepp/ui/tools/textureatlasnew.cpp
../../src/eepp/ui/tools/textureatlasnew.hpp

View File

@@ -110,6 +110,10 @@ Float StyleSheetLength::asDp( const Float& parentSize, const Sizef& viewSize, co
return PixelDensity::pxToDp( asPixels( parentSize, viewSize, displayDpi, elFontSize, globalFontSize ) );
}
bool StyleSheetLength::operator==( const StyleSheetLength& length ) {
return mValue == length.mValue && mUnit == length.mUnit;
}
StyleSheetLength& StyleSheetLength::operator=( const Float& val ) {
mValue = val;
mUnit = Unit::Px;

View File

@@ -0,0 +1,112 @@
#include <eepp/ui/css/stylesheetlengthtransition.hpp>
#include <eepp/ui/uiwidget.hpp>
#include <eepp/math/easing.hpp>
using namespace EE::Math::easing;
namespace EE { namespace UI { namespace CSS {
StyleSheetLengthTransition * StyleSheetLengthTransition::New( const std::string& propertyName, const std::string& startValue, const std::string& endValue, const Time& duration, const Ease::Interpolation& type ) {
return eeNew( StyleSheetLengthTransition, ( propertyName, startValue, endValue, duration, type ) );
}
StyleSheetLengthTransition::StyleSheetLengthTransition( const std::string& propertyName, const std::string& startValue, const std::string& endValue, const Time& duration, const Ease::Interpolation& type ) :
mPropertyName( propertyName ),
mStartValue( startValue ),
mEndValue( endValue ),
mDuration( duration ),
mType( type )
{}
Action * StyleSheetLengthTransition::clone() const {
return &StyleSheetLengthTransition::New( mPropertyName, mStartValue, mEndValue, mDuration, mType )
->setContainerLength( mContainerLength )
.setContainerLengthFunction( mContainerLengthFunction );
}
Action * StyleSheetLengthTransition::reverse() const {
return &StyleSheetLengthTransition::New( mPropertyName, mEndValue, mStartValue, mDuration, mType )
->setContainerLength( mContainerLength )
.setContainerLengthFunction( mContainerLengthFunction );
}
void StyleSheetLengthTransition::start() {
onStart();
sendEvent( ActionType::OnStart );
}
void StyleSheetLengthTransition::stop() {
onStop();
sendEvent( ActionType::OnStop );
}
void StyleSheetLengthTransition::update( const Time& time ) {
mElapsed += time;
onUpdate( time );
}
bool StyleSheetLengthTransition::isDone() {
return mElapsed.asMicroseconds() >= mDuration.asMicroseconds();
}
Float StyleSheetLengthTransition::getCurrentProgress() {
return mElapsed.asMilliseconds() / mDuration.asMilliseconds();
}
void StyleSheetLengthTransition::onStart() {
onUpdate( Time::Zero );
}
void StyleSheetLengthTransition::onUpdate( const Time& ) {
if ( NULL != mNode && mNode->isWidget() ) {
UIWidget * node = mNode->asType<UIWidget>();
Float start = node->convertLength( mStartValue, mContainerLengthFunction ? mContainerLengthFunction() : mContainerLength );
Float end = node->convertLength( mEndValue, mContainerLengthFunction ? mContainerLengthFunction() : mContainerLength );
Time time = mElapsed.asMicroseconds() > mDuration.asMicroseconds() ? mDuration : mElapsed;
Float value = easingCb[ mType ]( time.asMilliseconds(), start, end - start, mDuration.asMilliseconds() );
node->setStyleSheetProperty( mPropertyName, String::format( "%.f", value ) );
}
}
const Float& StyleSheetLengthTransition::getContainerLength() const {
return mContainerLength;
}
StyleSheetLengthTransition& StyleSheetLengthTransition::setContainerLength( const Float& containerLength ) {
mContainerLength = containerLength;
return *this;
}
StyleSheetLengthTransition& StyleSheetLengthTransition::setContainerLengthFunction( const StyleSheetLengthTransition::ContainerLengthProvider& containerLengthProvider ) {
mContainerLengthFunction = containerLengthProvider;
return *this;
}
const Time& StyleSheetLengthTransition::getElapsed() const {
return mElapsed;
}
const Ease::Interpolation& StyleSheetLengthTransition::getType() const {
return mType;
}
const Time& StyleSheetLengthTransition::getDuration() const {
return mDuration;
}
const std::string& StyleSheetLengthTransition::getEndValue() const {
return mEndValue;
}
const std::string& StyleSheetLengthTransition::getStartValue() const {
return mStartValue;
}
const std::string& StyleSheetLengthTransition::getPropertyName() const {
return mPropertyName;
}
}}}

View File

@@ -12,6 +12,7 @@ StyleSheetProperty::StyleSheetProperty() :
StyleSheetProperty::StyleSheetProperty( const std::string& name, const std::string& value ) :
mName( String::toLower( String::trim( name ) ) ),
mNameHash( String::hash( mName ) ),
mValue( String::trim( value ) ),
mSpecificity( 0 ),
mVolatile( false ),
@@ -22,6 +23,7 @@ StyleSheetProperty::StyleSheetProperty( const std::string& name, const std::stri
StyleSheetProperty::StyleSheetProperty( const std::string & name, const std::string& value, const Uint32 & specificity, const bool& isVolatile ) :
mName( String::toLower( String::trim( name ) ) ),
mNameHash( String::hash( mName ) ),
mValue( String::trim( value ) ),
mSpecificity( specificity ),
mVolatile( isVolatile ),
@@ -56,6 +58,7 @@ bool StyleSheetProperty::isEmpty() const {
void StyleSheetProperty::setName( const std::string& name ) {
mName = name;
mNameHash = String::hash( mName );
}
void StyleSheetProperty::setValue( const std::string& value ) {
@@ -70,6 +73,14 @@ void StyleSheetProperty::setVolatile( const bool & isVolatile ) {
mVolatile = isVolatile;
}
bool StyleSheetProperty::operator==( const StyleSheetProperty& property ) {
return mNameHash == property.mNameHash && mValue == property.mValue;
}
const Uint32& StyleSheetProperty::getNameHash() const {
return mNameHash;
}
void StyleSheetProperty::checkImportant() {
if ( String::endsWith( mValue, "!important" ) ) {
mImportant = true;

View File

@@ -0,0 +1,115 @@
#include <eepp/ui/css/transitiondefinition.hpp>
#include <eepp/core/string.hpp>
#include <eepp/scene/nodeattribute.hpp>
using namespace EE::Scene;
namespace EE { namespace UI { namespace CSS {
std::map<std::string, TransitionDefinition> TransitionDefinition::parseTransitionProperties( const std::vector<StyleSheetProperty>& styleSheetProperties ) {
std::vector<std::string> properties;
std::vector<Time> durations;
std::vector<Time> delays;
std::vector<Ease::Interpolation> timingFunctions;
TransitionsMap transitions;
for ( auto& prop : styleSheetProperties ) {
if ( prop.getName() == "transition" ) {
auto strTransitions = String::split( prop.getValue(), ',' );
for ( auto tit = strTransitions.begin(); tit != strTransitions.end(); ++tit ) {
auto strTransition = String::trim( *tit );
auto splitTransition = String::split( strTransition, ' ' );
if ( !splitTransition.empty() ) {
TransitionDefinition transitionDef;
if ( splitTransition.size() >= 2 ) {
std::string property = String::trim( splitTransition[0] );
String::toLowerInPlace( property );
Time duration = NodeAttribute( prop.getName(), String::toLower( splitTransition[1] ) ).asTime();
transitionDef.property = property;
transitionDef.duration = duration;
if ( splitTransition.size() >= 3 ) {
transitionDef.timingFunction = Ease::fromName( String::toLower( splitTransition[2] ) );
if ( transitionDef.timingFunction == Ease::Linear && splitTransition[2] != "linear" && splitTransition.size() == 3 ) {
transitionDef.delay = NodeAttribute( prop.getName(), String::toLower( splitTransition[2] ) ).asTime();
} else if ( splitTransition.size() >= 4 ) {
transitionDef.delay = NodeAttribute( prop.getName(), String::toLower( splitTransition[3] ) ).asTime();
}
}
transitions[ transitionDef.getProperty() ] = transitionDef;
}
}
}
} else if ( prop.getName() == "transitionduration" || prop.getName() == "transition-duration" ) {
auto strDurations = String::split( prop.getValue(), ',' );
for ( auto dit = strDurations.begin(); dit != strDurations.end(); ++dit ) {
std::string duration( String::trim( *dit ) );
String::toLowerInPlace( duration );
durations.push_back( NodeAttribute( prop.getName(), duration ).asTime() );
}
} else if ( prop.getName() == "transitiondelay" || prop.getName() == "transition-delay" ) {
auto strDelays = String::split( prop.getValue(), ',' );
for ( auto dit = strDelays.begin(); dit != strDelays.end(); ++dit ) {
std::string delay( String::trim( *dit ) );
String::toLowerInPlace( delay );
delays.push_back( NodeAttribute( prop.getName(), delay ).asTime() );
}
} else if ( prop.getName() == "transitiontimingfunction" || prop.getName() == "transition-timing-function" ) {
auto strTimingFuncs = String::split( prop.getValue(), ',' );
for ( auto dit = strTimingFuncs.begin(); dit != strTimingFuncs.end(); ++dit ) {
std::string timingFunction( String::trim( *dit ) );
String::toLowerInPlace( timingFunction );
timingFunctions.push_back( Ease::fromName( timingFunction ) );
}
} else if ( prop.getName() == "transitionproperty" || prop.getName() == "transition-property" ) {
auto strProperties = String::split( prop.getValue(), ',' );
for ( auto dit = strProperties.begin(); dit != strProperties.end(); ++dit ) {
std::string property( String::trim( *dit ) );
String::toLowerInPlace( property );
properties.push_back( property );
}
}
}
for ( size_t i = 0; i < properties.size(); i++ ) {
const std::string& property = properties.at( i );
TransitionDefinition transitionDef;
transitionDef.property = property;
if ( durations.size() < i ) {
transitionDef.duration = durations[i];
} else if ( !durations.empty() ) {
transitionDef.duration = durations[0];
}
if ( delays.size() < i ) {
transitionDef.delay = delays[i];
} else if ( !delays.empty() ) {
transitionDef.delay = delays[0];
}
if ( timingFunctions.size() < i ) {
transitionDef.timingFunction = timingFunctions[i];
} else if ( !delays.empty() ) {
transitionDef.timingFunction = timingFunctions[0];
}
transitions[ property ] = transitionDef;
}
return transitions;
}
}}}

View File

@@ -986,16 +986,12 @@ Uint32 UINode::onFocusLoss() {
return Node::onFocusLoss();
}
Float UINode::convertLength( const CSS::StyleSheetLength& length, const Sizef& drawableSize, const bool& percentAsWidth ) {
return length.asPixels(
percentAsWidth ? getPixelsSize().getWidth() - drawableSize.getWidth() :
getPixelsSize().getHeight() - drawableSize.getHeight(),
getSceneNode()->getPixelsSize(),
getSceneNode()->getDPI(), 12, 12 );
Float UINode::convertLength( const CSS::StyleSheetLength& length, const Float& containerLength ) {
return length.asPixels( containerLength, getSceneNode()->getPixelsSize(), getSceneNode()->getDPI(), 12, 12 );
}
Float UINode::lengthAsDp( const CSS::StyleSheetLength& length, const Sizef& drawableSize, const bool& percentAsWidth ) {
return PixelDensity::pxToDp( convertLength( length, drawableSize, percentAsWidth ) );
Float UINode::convertLengthAsDp( const CSS::StyleSheetLength& length, const Float& containerLength ) {
return PixelDensity::pxToDp( convertLength( length, containerLength ) );
}
}}

View File

@@ -198,9 +198,7 @@ UINodeDrawable::LayerDrawable::LayerDrawable( UINodeDrawable * container ) :
mNeedsUpdate(false),
mOwnsDrawable(false),
mDrawable(NULL),
mResourceChangeCbId(0),
mMoveAction(NULL),
mMoveActionCbId(0)
mResourceChangeCbId(0)
{}
UINodeDrawable::LayerDrawable::~LayerDrawable() {
@@ -237,12 +235,6 @@ void UINodeDrawable::LayerDrawable::draw( const Vector2f& position, const Sizef&
if ( mNeedsUpdate )
update();
if ( NULL != mMoveAction ) {
update();
mMoveAction->update( Time::Zero );
setOffset( mMoveAction->getOffset() );
}
mDrawable->draw( mPosition + mOffset, mDrawableSize );
}
@@ -372,18 +364,18 @@ Sizef UINodeDrawable::LayerDrawable::calcDrawableSize( const std::string& drawab
}
} else if ( sizePart[0] != "auto" ) {
CSS::StyleSheetLength wl( sizePart[0] );
size.x = mContainer->getOwner()->convertLength( wl, Sizef::Zero, true );
size.x = mContainer->getOwner()->convertLength( wl, mContainer->getOwner()->getPixelsSize().getWidth() );
if ( sizePart[1] == "auto" ) {
Sizef drawableSize( mDrawable->getSize() );
size.y = drawableSize.getHeight() * ( size.getWidth() / drawableSize.getWidth() );
} else {
CSS::StyleSheetLength hl( sizePart[1] );
size.y = mContainer->getOwner()->convertLength( hl, Sizef::Zero, false );
size.y = mContainer->getOwner()->convertLength( hl, mContainer->getOwner()->getPixelsSize().getHeight() );
}
} else {
CSS::StyleSheetLength hl( sizePart[1] );
size.y = mContainer->getOwner()->convertLength( hl, Sizef::Zero, false );
size.y = mContainer->getOwner()->convertLength( hl, mContainer->getOwner()->getPixelsSize().getHeight() );
Sizef drawableSize( mDrawable->getSize() );
size.x = drawableSize.getWidth() * ( size.getHeight() / drawableSize.getHeight() );
@@ -412,8 +404,8 @@ Vector2f UINodeDrawable::LayerDrawable::calcPosition( const std::string& positio
CSS::StyleSheetLength xl( pos[xFloatIndex] );
CSS::StyleSheetLength yl( pos[yFloatIndex] );
position.x = mContainer->getOwner()->convertLength( xl, mDrawableSize, true );
position.y = mContainer->getOwner()->convertLength( yl, mDrawableSize, false );
position.x = mContainer->getOwner()->convertLength( xl, mContainer->getOwner()->getPixelsSize().getWidth() - mDrawableSize.getWidth() );
position.y = mContainer->getOwner()->convertLength( yl, mContainer->getOwner()->getPixelsSize().getHeight() - mDrawableSize.getHeight() );
} else if ( pos.size() > 2 ) {
if ( pos.size() == 3 ) {
pos.push_back( "0dp" );
@@ -432,35 +424,20 @@ Vector2f UINodeDrawable::LayerDrawable::calcPosition( const std::string& positio
CSS::StyleSheetLength yl1( pos[yFloatIndex] );
CSS::StyleSheetLength yl2( pos[yFloatIndex+1] );
position.x = mContainer->getOwner()->convertLength( xl1, mDrawableSize, true );
position.x = mContainer->getOwner()->convertLength( xl1, mContainer->getOwner()->getPixelsSize().getWidth() - mDrawableSize.getWidth() );
Float xl2Val = mContainer->getOwner()->convertLength( xl2, mDrawableSize, true );
Float xl2Val = mContainer->getOwner()->convertLength( xl2, mContainer->getOwner()->getPixelsSize().getWidth() - mDrawableSize.getWidth() );
position.x += ( pos[xFloatIndex] == "right" ) ? -xl2Val : xl2Val;
position.y = mContainer->getOwner()->convertLength( yl1, mDrawableSize, false );
position.y = mContainer->getOwner()->convertLength( yl1, mContainer->getOwner()->getPixelsSize().getWidth() - mDrawableSize.getHeight() );
Float yl2Val = mContainer->getOwner()->convertLength( yl2, mDrawableSize, false );
Float yl2Val = mContainer->getOwner()->convertLength( yl2, mContainer->getOwner()->getPixelsSize().getWidth() - mDrawableSize.getHeight() );
position.y += ( pos[yFloatIndex] == "bottom" ) ? -yl2Val : yl2Val;
}
return position;
}
UINodeDrawable::MoveAction * UINodeDrawable::LayerDrawable::getMoveAction() const {
return mMoveAction;
}
void UINodeDrawable::LayerDrawable::setMoveAction(MoveAction * moveAction) {
mMoveAction = moveAction;
if ( mMoveAction != NULL ) {
auto delCb = [&] ( Action *, const Action::ActionType& ) {
mMoveAction = NULL;
};
mMoveAction->addEventListener( Action::OnDone, delCb );
mMoveAction->addEventListener( Action::OnDelete, delCb );
}
}
void UINodeDrawable::LayerDrawable::setOffset( const Vector2f& offset ) {
mOffset = offset;
}
@@ -483,73 +460,4 @@ void UINodeDrawable::LayerDrawable::update() {
mNeedsUpdate = false;
}
UINodeDrawable::MoveAction * UINodeDrawable::MoveAction::New( const std::string& posEqStart, const std::string& posEqEnd, const Time& duration, const Ease::Interpolation& type ) {
return eeNew( MoveAction, ( posEqStart, posEqEnd, duration, type ) );
}
UINodeDrawable::MoveAction::MoveAction( const std::string& posEqStart, const std::string& posEqEnd, const Time& duration, const Ease::Interpolation& type ) :
mStart( posEqStart ),
mEnd( posEqEnd ),
mDuration( duration ),
mType( type )
{}
Action * UINodeDrawable::MoveAction::clone() const {
return MoveAction::New( mStart, mEnd, mDuration, mType );
}
Action * UINodeDrawable::MoveAction::reverse() const {
return MoveAction::New( mEnd, mStart, mDuration, mType );
}
void UINodeDrawable::MoveAction::start() {
onStart();
sendEvent( ActionType::OnStart );
}
void UINodeDrawable::MoveAction::stop() {
onStop();
sendEvent( ActionType::OnStop );
}
void UINodeDrawable::MoveAction::update( const Time& time ) {
mElapsed += time;
onUpdate( time );
}
bool UINodeDrawable::MoveAction::isDone() {
return mElapsed.asMicroseconds() >= mDuration.asMicroseconds();
}
Float UINodeDrawable::MoveAction::getCurrentProgress() {
return mElapsed.asMilliseconds() / mDuration.asMilliseconds();
}
void UINodeDrawable::MoveAction::onStart() {
UINode * node = mNode->asType<UINode>();
LayerDrawable * layer = node->getBackground()->getLayer(0);
layer->setMoveAction( this );
onUpdate( Time::Zero );
}
void UINodeDrawable::MoveAction::onUpdate( const Time& ) {
if ( NULL != mNode && mNode->isUINode() ) {
UINode * node = mNode->asType<UINode>();
LayerDrawable * layer = node->getBackground()->getLayer(0);
Vector2f start = layer->calcPosition( mStart );
Vector2f end = layer->calcPosition( mEnd );
Time time = mElapsed.asMicroseconds() > mDuration.asMicroseconds() ? mDuration : mElapsed;
Float x = easingCb[ mType ]( time.asMilliseconds(), start.x, end.x - start.x, mDuration.asMilliseconds() );
Float y = easingCb[ mType ]( time.asMilliseconds(), start.y, end.y - start.y, mDuration.asMilliseconds() );
mOffset = Vector2f( x, y );
if ( isDone() ) {
layer->setMoveAction( NULL );
layer->setPositionEq( mEnd );
}
}
}
}}

View File

@@ -90,7 +90,7 @@ bool UIStyle::hasTransition( const std::string& propertyName ) {
return mTransitions.find( propertyName ) != mTransitions.end() || mTransitions.find( "all" ) != mTransitions.end();
}
UIStyle::TransitionInfo UIStyle::getTransition( const std::string& propertyName ) {
TransitionDefinition UIStyle::getTransition( const std::string& propertyName ) {
auto propertyTransitionIt = mTransitions.find( propertyName );
if ( propertyTransitionIt != mTransitions.end() ) {
@@ -99,7 +99,7 @@ UIStyle::TransitionInfo UIStyle::getTransition( const std::string& propertyName
return propertyTransitionIt->second;
}
return TransitionInfo();
return TransitionDefinition();
}
const bool& UIStyle::isChangingState() const {
@@ -147,7 +147,7 @@ void UIStyle::onStateChange() {
tryApplyStyle( style );
}
parseTransitions();
mTransitions = TransitionDefinition::parseTransitionProperties( mTransitionAttributes );
mWidget->beginAttributesTransaction();
@@ -263,115 +263,4 @@ void UIStyle::removeRelatedWidgets() {
mRelatedWidgets.clear();
}
void UIStyle::parseTransitions() {
std::vector<std::string> properties;
std::vector<Time> durations;
std::vector<Time> delays;
std::vector<Ease::Interpolation> timingFunctions;
TransitionsMap transitions;
for ( auto& attr : mTransitionAttributes ) {
if ( attr.getName() == "transition" ) {
auto strTransitions = String::split( attr.getValue(), ',' );
for ( auto tit = strTransitions.begin(); tit != strTransitions.end(); ++tit ) {
auto strTransition = String::trim( *tit );
auto splitTransition = String::split( strTransition, ' ' );
if ( !splitTransition.empty() ) {
TransitionInfo transitionInfo;
if ( splitTransition.size() >= 2 ) {
std::string property = String::trim( splitTransition[0] );
String::toLowerInPlace( property );
Time duration = NodeAttribute( attr.getName(), String::toLower( splitTransition[1] ) ).asTime();
transitionInfo.property = property;
transitionInfo.duration = duration;
if ( splitTransition.size() >= 3 ) {
transitionInfo.timingFunction = Ease::fromName( String::toLower( splitTransition[2] ) );
if ( transitionInfo.timingFunction == Ease::Linear && splitTransition[2] != "linear" && splitTransition.size() == 3 ) {
transitionInfo.delay = NodeAttribute( attr.getName(), String::toLower( splitTransition[2] ) ).asTime();
} else if ( splitTransition.size() >= 4 ) {
transitionInfo.delay = NodeAttribute( attr.getName(), String::toLower( splitTransition[3] ) ).asTime();
}
}
transitions[ transitionInfo.getProperty() ] = transitionInfo;
}
}
}
} else if ( attr.getName() == "transitionduration" || attr.getName() == "transition-duration" ) {
auto strDurations = String::split( attr.getValue(), ',' );
for ( auto dit = strDurations.begin(); dit != strDurations.end(); ++dit ) {
std::string duration( String::trim( *dit ) );
String::toLowerInPlace( duration );
durations.push_back( NodeAttribute( attr.getName(), duration ).asTime() );
}
} else if ( attr.getName() == "transitiondelay" || attr.getName() == "transition-delay" ) {
auto strDelays = String::split( attr.getValue(), ',' );
for ( auto dit = strDelays.begin(); dit != strDelays.end(); ++dit ) {
std::string delay( String::trim( *dit ) );
String::toLowerInPlace( delay );
delays.push_back( NodeAttribute( attr.getName(), delay ).asTime() );
}
} else if ( attr.getName() == "transitiontimingfunction" || attr.getName() == "transition-timing-function" ) {
auto strTimingFuncs = String::split( attr.getValue(), ',' );
for ( auto dit = strTimingFuncs.begin(); dit != strTimingFuncs.end(); ++dit ) {
std::string timingFunction( String::trim( *dit ) );
String::toLowerInPlace( timingFunction );
timingFunctions.push_back( Ease::fromName( timingFunction ) );
}
} else if ( attr.getName() == "transitionproperty" || attr.getName() == "transition-property" ) {
auto strProperties = String::split( attr.getValue(), ',' );
for ( auto dit = strProperties.begin(); dit != strProperties.end(); ++dit ) {
std::string property( String::trim( *dit ) );
String::toLowerInPlace( property );
properties.push_back( property );
}
}
}
if ( properties.empty() ) {
if ( !transitions.empty() )
mTransitions = transitions;
return;
}
for ( size_t i = 0; i < properties.size(); i++ ) {
const std::string& property = properties.at( i );
TransitionInfo transitionInfo;
transitionInfo.property = property;
if ( durations.size() < i ) {
transitionInfo.duration = durations[i];
} else if ( !durations.empty() ) {
transitionInfo.duration = durations[0];
}
if ( delays.size() < i ) {
transitionInfo.delay = delays[i];
} else if ( !delays.empty() ) {
transitionInfo.delay = delays[0];
}
if ( timingFunctions.size() < i ) {
transitionInfo.timingFunction = timingFunctions[i];
} else if ( !delays.empty() ) {
transitionInfo.timingFunction = timingFunctions[0];
}
mTransitions[ property ] = transitionInfo;
}
}
}}

View File

@@ -9,6 +9,7 @@
#include <eepp/window/clipboard.hpp>
#include <eepp/scene/actions/actions.hpp>
#include <eepp/ui/css/stylesheetproperty.hpp>
#include <eepp/ui/css/transitiondefinition.hpp>
namespace EE { namespace UI {
@@ -577,7 +578,7 @@ bool UITextView::setAttribute( const NodeAttribute& attribute, const Uint32& sta
Color color = attribute.asColor();
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Action * action = Actions::Tint::New( getFontColor(), color, true, transitionInfo.duration, transitionInfo.timingFunction, Actions::Tint::Text );
@@ -594,7 +595,7 @@ bool UITextView::setAttribute( const NodeAttribute& attribute, const Uint32& sta
Color color = attribute.asColor();
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Action * action = Actions::Tint::New( getFontShadowColor(), color, true, transitionInfo.duration, transitionInfo.timingFunction, Actions::Tint::TextShadow );
@@ -647,7 +648,7 @@ bool UITextView::setAttribute( const NodeAttribute& attribute, const Uint32& sta
Color color = attribute.asColor();
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Action * action = Actions::Tint::New( getOutlineColor(), color, true, transitionInfo.duration, transitionInfo.timingFunction, Actions::Tint::TextOutline );

View File

@@ -4,6 +4,7 @@
#include <eepp/ui/uitooltip.hpp>
#include <eepp/ui/uiscenenode.hpp>
#include <eepp/ui/uinodedrawable.hpp>
#include <eepp/ui/css/transitiondefinition.hpp>
#include <eepp/ui/css/stylesheetproperty.hpp>
#include <eepp/ui/css/stylesheetselector.hpp>
#include <eepp/graphics/drawablesearcher.hpp>
@@ -930,7 +931,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
Float newX = attribute.asDpDimensionI();
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Action * action = Actions::MoveCoordinate::New( getPosition().x, newX, transitionInfo.duration, transitionInfo.timingFunction, Actions::MoveCoordinate::CoordinateX );
@@ -950,7 +951,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
Float newY = attribute.asDpDimensionI();
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Action * action = Actions::MoveCoordinate::New( getPosition().y, newY, transitionInfo.duration, transitionInfo.timingFunction, Actions::MoveCoordinate::CoordinateY );
@@ -970,7 +971,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
Float newWidth = attribute.asDpDimensionI();
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
constexpr Uint32 tag = String::hash("width");
Action * action = Actions::ResizeWidth::New( getSize().getWidth(), newWidth, transitionInfo.duration, transitionInfo.timingFunction );
@@ -994,7 +995,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
constexpr Uint32 tag = String::hash("height");
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Action * action = Actions::ResizeHeight::New( getSize().getHeight(), newHeight, transitionInfo.duration, transitionInfo.timingFunction );
@@ -1020,7 +1021,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
Color color = attribute.asColor();
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Color start( getBackgroundColor() );
Action * action = Actions::Tint::New( start, color, true, transitionInfo.duration, transitionInfo.timingFunction, Actions::Tint::Background );
@@ -1042,7 +1043,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
/*if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
constexpr Uint32 tag = String::hash( "background-position" );
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Action * action = UINodeDrawable::MoveAction::New( getBackground()->getLayer(0)->getPositionEq(), attribute.value(), transitionInfo.duration, transitionInfo.timingFunction );
@@ -1073,7 +1074,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
Color color = attribute.asColor();
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Color start( getForegroundColor() );
Action * action = Actions::Tint::New( start, color, true, transitionInfo.duration, transitionInfo.timingFunction, Actions::Tint::Foreground );
@@ -1103,7 +1104,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
Color color = attribute.asColor();
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Color start( getBorderColor() );
Action * action = Actions::Tint::New( start, color, false, transitionInfo.duration, transitionInfo.timingFunction, Actions::Tint::Border );
@@ -1125,7 +1126,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
Uint32 borderRadius = PixelDensity::dpToPxI( attribute.asDpDimensionUint() );
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Uint32 start( getBorderRadius() );
Action * action = Actions::ResizeBorderRadius::New( start, borderRadius, transitionInfo.duration, transitionInfo.timingFunction );
@@ -1164,7 +1165,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
Color color = attribute.asColor();
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Color start( getSkinColor() );
Action * action = Actions::Tint::New( start, color, true, transitionInfo.duration, transitionInfo.timingFunction, Actions::Tint::Skin );
@@ -1257,7 +1258,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
}
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Action * action = Actions::MarginMove::New( mLayoutMargin, margin, transitionInfo.duration, transitionInfo.timingFunction, marginFlag );
if ( Time::Zero != transitionInfo.delay )
@@ -1372,7 +1373,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
SAVE_NORMAL_STATE_ATTR( String::format( "%2.f", mRotation ) )
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Float newRotation( mStyle->getNodeAttribute( attribute.getName() ).asFloat() );
Action * action = Actions::Rotate::New( mRotation, newRotation, transitionInfo.duration, transitionInfo.timingFunction );
@@ -1387,7 +1388,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
SAVE_NORMAL_STATE_ATTR( String::format( "%2.f, %2.f", mScale.x, mScale.y ) )
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Vector2f newScale( mStyle->getNodeAttribute( attribute.getName() ).asVector2f() );
Action * action = Actions::Scale::New( mScale, newScale, transitionInfo.duration, transitionInfo.timingFunction );
@@ -1433,7 +1434,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
}
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Action * action = Actions::PaddingTransition::New( mPadding, padding, transitionInfo.duration, transitionInfo.timingFunction, paddingFlag );
if ( Time::Zero != transitionInfo.delay )
@@ -1449,7 +1450,7 @@ bool UIWidget::setAttribute( const NodeAttribute& attribute, const Uint32& state
Float alpha = eemin( attribute.asFloat() * 255.f, 255.f );
if ( !isSceneNodeLoading() && NULL != mStyle && mStyle->hasTransition( attribute.getName() ) ) {
UIStyle::TransitionInfo transitionInfo( mStyle->getTransition( attribute.getName() ) );
CSS::TransitionDefinition transitionInfo( mStyle->getTransition( attribute.getName() ) );
Action * action = Actions::Fade::New( mAlpha, alpha, transitionInfo.duration, transitionInfo.timingFunction );
if ( Time::Zero != transitionInfo.delay )