diff --git a/include/eepp/ui/base.hpp b/include/eepp/ui/base.hpp index 7d24d0505..39d7aa5d0 100644 --- a/include/eepp/ui/base.hpp +++ b/include/eepp/ui/base.hpp @@ -10,6 +10,7 @@ #include #include #include +#include using namespace EE::Math; #include diff --git a/include/eepp/ui/uicontrol.hpp b/include/eepp/ui/uicontrol.hpp index fb5261d99..373ec9712 100644 --- a/include/eepp/ui/uicontrol.hpp +++ b/include/eepp/ui/uicontrol.hpp @@ -247,6 +247,7 @@ class EE_API UIControl { Vector2i mPos; Vector2i mScreenPos; + Vector2f mScreenPosf; Sizei mSize; Uint32 mFlags; @@ -322,6 +323,8 @@ class EE_API UIControl { virtual void UpdateQuad(); + virtual void UpdateCenter(); + virtual void MatrixSet(); virtual void MatrixUnset(); diff --git a/include/eepp/ui/uicontrolanim.hpp b/include/eepp/ui/uicontrolanim.hpp index cb0f1431f..016609f26 100644 --- a/include/eepp/ui/uicontrolanim.hpp +++ b/include/eepp/ui/uicontrolanim.hpp @@ -23,11 +23,27 @@ class EE_API UIControlAnim : public UIDragable { void Angle( const Float& angle ); + void Angle( const Float& angle, const OriginPoint& center ); + + const OriginPoint& AngleOriginPoint() const; + + void AngleOriginPoint( const OriginPoint& center ); + + Vector2f AngleCenter(); + const Vector2f& Scale() const; void Scale( const Vector2f& scale ); - void Scale( const Float& scale ); + void Scale( const Vector2f& scale, const OriginPoint& center ); + + void Scale( const Float& scale , const OriginPoint & center = OriginPoint::OriginCenter ); + + const OriginPoint& ScaleOriginPoint() const; + + void ScaleOriginPoint( const OriginPoint& center ); + + Vector2f ScaleCenter(); const Float& Alpha() const; @@ -68,9 +84,12 @@ class EE_API UIControlAnim : public UIDragable { bool FadingOut(); protected: friend class UIManager; + friend class UIControl; Float mAngle; + OriginPoint mAngleOriginPoint; Vector2f mScale; + OriginPoint mScaleOriginPoint; Float mAlpha; Interpolation * mAngleAnim; @@ -86,6 +105,8 @@ class EE_API UIControlAnim : public UIDragable { virtual void UpdateQuad(); + virtual void OnSizeChange(); + virtual void OnAngleChange(); virtual void OnScaleChange(); @@ -95,6 +116,8 @@ class EE_API UIControlAnim : public UIDragable { virtual void MatrixSet(); virtual void MatrixUnset(); + + void UpdateOriginPoint(); }; }} diff --git a/src/eepp/ui/uicontrol.cpp b/src/eepp/ui/uicontrol.cpp index e64357fa9..8f605cb87 100644 --- a/src/eepp/ui/uicontrol.cpp +++ b/src/eepp/ui/uicontrol.cpp @@ -120,11 +120,13 @@ bool UIControl::IsInside( const Vector2i& Pos ) const { void UIControl::Pos( const Vector2i& Pos ) { mPos = Pos; + OnPosChange(); } void UIControl::Pos( const Int32& x, const Int32& y ) { mPos = Vector2i( x, y ); + OnPosChange(); } @@ -250,7 +252,7 @@ void UIControl::Draw() { BorderDraw(); if ( NULL != mSkinState ) - mSkinState->Draw( (Float)mScreenPos.x, (Float)mScreenPos.y, (Float)mSize.Width(), (Float)mSize.Height(), 255 ); + mSkinState->Draw( mScreenPosf.x, mScreenPosf.y, (Float)mSize.Width(), (Float)mSize.Height(), 255 ); if ( UIManager::instance()->HighlightFocus() && UIManager::instance()->FocusControl() == this ) { Primitives P; @@ -514,11 +516,13 @@ void UIControl::OnPosChange() { } void UIControl::OnSizeChange() { + UpdateCenter(); + SendCommonEvent( UIEvent::EventOnSizeChange ); } Rectf UIControl::GetRectf() { - return Rectf( Vector2f( (Float)mScreenPos.x, (Float)mScreenPos.y ), Sizef( (Float)mSize.Width(), (Float)mSize.Height() ) ); + return Rectf( mScreenPosf, Sizef( (Float)mSize.Width(), (Float)mSize.Height() ) ); } void UIControl::BackgroundDraw() { @@ -551,7 +555,7 @@ void UIControl::BorderDraw() { //! @TODO: Check why was this +0.1f -0.1f? if ( mFlags & UI_CLIP_ENABLE ) { - Rectf R( Vector2f( (Float)mScreenPos.x + 0.1f, (Float)mScreenPos.y + 0.1f ), Sizef( (Float)mSize.Width() - 0.1f, (Float)mSize.Height() - 0.1f ) ); + Rectf R( Vector2f( mScreenPosf.x + 0.1f, mScreenPosf.y + 0.1f ), Sizef( (Float)mSize.Width() - 0.1f, (Float)mSize.Height() - 0.1f ) ); if ( mBackground->Corners() ) { P.DrawRoundedRectangle( GetRectf(), 0.f, Vector2f::One, mBackground->Corners() ); @@ -871,8 +875,7 @@ const Vector2f& UIControl::GetPolygonCenter() const { } void UIControl::UpdateQuad() { - mPoly = Polygon2f( eeAABB( (Float)mScreenPos.x, (Float)mScreenPos.y, (Float)mScreenPos.x + mSize.Width(), (Float)mScreenPos.y + mSize.Height() ) ); - mCenter = Vector2f( (Float)mScreenPos.x + (Float)mSize.Width() * 0.5f, (Float)mScreenPos.y + (Float)mSize.Height() * 0.5f ); + mPoly = Polygon2f( eeAABB( mScreenPosf.x, mScreenPosf.y, mScreenPosf.x + mSize.Width(), mScreenPosf.y + mSize.Height() ) ); UIControl * tParent = Parent(); @@ -880,14 +883,18 @@ void UIControl::UpdateQuad() { if ( tParent->IsAnimated() ) { UIControlAnim * tP = reinterpret_cast ( tParent ); - mPoly.Rotate( tP->Angle(), tP->GetPolygonCenter() ); - mPoly.Scale( tP->Scale(), tP->GetPolygonCenter() ); + mPoly.Rotate( tP->Angle(), tP->AngleCenter() ); + mPoly.Scale( tP->Scale(), tP->ScaleCenter() ); } tParent = tParent->Parent(); }; } +void UIControl::UpdateCenter() { + mCenter = Vector2f( mScreenPosf.x + (Float)mSize.Width() * 0.5f, mScreenPosf.y + (Float)mSize.Height() * 0.5f ); +} + Time UIControl::Elapsed() { return UIManager::instance()->Elapsed(); } @@ -1031,6 +1038,9 @@ void UIControl::UpdateScreenPos() { ControlToScreen( Pos ); mScreenPos = Pos; + mScreenPosf = Vector2f( Pos.x, Pos.y ); + + UpdateCenter(); } UISkin * UIControl::GetSkin() { @@ -1238,9 +1248,10 @@ void UIControl::WorldToControl( Vector2i& pos ) const { UIControl * tParent = (*it); UIControlAnim * tP = tParent->IsAnimated() ? reinterpret_cast ( tParent ) : NULL; Vector2f pPos ( tParent->mPos.x * scale.x , tParent->mPos.y * scale.y ); - Vector2f Center ( tParent->mSize.x * 0.5f * scale.x , tParent->mSize.y * 0.5f * scale.y ); + Vector2f Center; if ( NULL != tP && 1.f != tP->Scale() ) { + Center = tP->ScaleOriginPoint() * scale; scale *= tP->Scale(); pPos.Scale( scale, pPos + Center ); @@ -1249,7 +1260,7 @@ void UIControl::WorldToControl( Vector2i& pos ) const { Pos -= pPos; if ( NULL != tP && 0.f != tP->Angle() ) { - Center = Vector2f( tParent->mSize.x * 0.5f * scale.x , tParent->mSize.y * 0.5f * scale.y ); + Center = tP->AngleOriginPoint() * scale; Pos.Rotate( -tP->Angle(), Center ); } } @@ -1275,13 +1286,15 @@ void UIControl::ControlToWorld( Vector2i& pos ) const { UIControl * tParent = (*it); UIControlAnim * tP = tParent->IsAnimated() ? reinterpret_cast ( tParent ) : NULL; Vector2f pPos ( tParent->mPos.x , tParent->mPos.y ); - Vector2f Center ( pPos.x + tParent->mSize.x * 0.5f , pPos.y + tParent->mSize.y * 0.5f ); Pos += pPos; if ( NULL != tP ) { - Pos.Rotate( tP->Angle(), Center ); - Pos.Scale( tP->Scale(), Center ); + Vector2f CenterAngle( pPos.x + tP->mAngleOriginPoint.x, pPos.y + tP->mAngleOriginPoint.y ); + Vector2f CenterScale( pPos.x + tP->mScaleOriginPoint.x, pPos.y + tP->mScaleOriginPoint.y ); + + Pos.Rotate( tP->Angle(), CenterAngle ); + Pos.Scale( tP->Scale(), CenterScale ); } } diff --git a/src/eepp/ui/uicontrolanim.cpp b/src/eepp/ui/uicontrolanim.cpp index 7c0b031a4..4ed7ebdc2 100644 --- a/src/eepp/ui/uicontrolanim.cpp +++ b/src/eepp/ui/uicontrolanim.cpp @@ -17,6 +17,8 @@ UIControlAnim::UIControlAnim( const CreateParams& Params ) : mMoveAnim(NULL) { mControlFlags |= UI_CTRL_FLAG_ANIM; + + UpdateOriginPoint(); } UIControlAnim::~UIControlAnim() { @@ -43,7 +45,7 @@ void UIControlAnim::Draw() { BorderDraw(); if ( NULL != mSkinState ) - mSkinState->Draw( (Float)mScreenPos.x, (Float)mScreenPos.y, (Float)mSize.Width(), (Float)mSize.Height(), (Uint32)mAlpha ); + mSkinState->Draw( mScreenPosf.x, mScreenPosf.y, (Float)mSize.Width(), (Float)mSize.Height(), (Uint32)mAlpha ); if ( UIManager::instance()->HighlightFocus() && UIManager::instance()->FocusControl() == this ) { Primitives P; @@ -67,22 +69,68 @@ const Float& UIControlAnim::Angle() const { return mAngle; } +const OriginPoint& UIControlAnim::AngleOriginPoint() const { + return mAngleOriginPoint; +} + +void UIControlAnim::AngleOriginPoint( const OriginPoint & center ) { + mAngleOriginPoint = center; + UpdateOriginPoint(); +} + +Vector2f UIControlAnim::AngleCenter() { + switch ( mAngleOriginPoint.OriginType ) { + case OriginPoint::OriginCenter: return mCenter; + case OriginPoint::OriginTopLeft: return mScreenPosf; + case OriginPoint::OriginCustom: default: return mScreenPosf + mAngleOriginPoint; + } +} + void UIControlAnim::Angle( const Float& angle ) { mAngle = angle; OnAngleChange(); } +void UIControlAnim::Angle( const Float& angle , const OriginPoint & center ) { + mAngleOriginPoint = center; + UpdateOriginPoint(); + Angle( angle ); +} + const Vector2f& UIControlAnim::Scale() const { return mScale; } -void UIControlAnim::Scale( const Vector2f& scale ) { +void UIControlAnim::Scale( const Vector2f & scale ) { mScale = scale; OnScaleChange(); } -void UIControlAnim::Scale( const Float& scale ) { - Scale( Vector2f( scale, scale ) ); +const OriginPoint& UIControlAnim::ScaleOriginPoint() const { + return mScaleOriginPoint; +} + +void UIControlAnim::ScaleOriginPoint( const OriginPoint & center ) { + mScaleOriginPoint = center; + UpdateOriginPoint(); +} + +Vector2f UIControlAnim::ScaleCenter() { + switch ( mScaleOriginPoint.OriginType ) { + case OriginPoint::OriginCenter: return mCenter; + case OriginPoint::OriginTopLeft: return mScreenPosf; + case OriginPoint::OriginCustom: default: return mScreenPosf + mScaleOriginPoint; + } +} + +void UIControlAnim::Scale( const Vector2f& scale, const OriginPoint& center ) { + mScaleOriginPoint = center; + UpdateOriginPoint(); + Scale( scale ); +} + +void UIControlAnim::Scale( const Float& scale, const OriginPoint& center ) { + Scale( Vector2f( scale, scale ), center ); } const Float& UIControlAnim::Alpha() const { @@ -113,18 +161,25 @@ void UIControlAnim::AlphaChilds( const Float &alpha ) { void UIControlAnim::MatrixSet() { if ( mScale != 1.f || mAngle != 0.f ) { GlobalBatchRenderer::instance()->Draw(); + GLi->PushMatrix(); - Vector2f Center( mScreenPos.x + mSize.Width() * 0.5f, mScreenPos.y + mSize.Height() * 0.5f ); - GLi->Translatef( Center.x , Center.y, 0.f ); - GLi->Rotatef( mAngle, 0.0f, 0.0f, 1.0f ); + + Vector2f scaleCenter = ScaleCenter(); + GLi->Translatef( scaleCenter.x , scaleCenter.y, 0.f ); GLi->Scalef( mScale.x, mScale.y, 1.0f ); - GLi->Translatef( -Center.x, -Center.y, 0.f ); + GLi->Translatef( -scaleCenter.x, -scaleCenter.y, 0.f ); + + Vector2f angleCenter = AngleCenter(); + GLi->Translatef( angleCenter.x , angleCenter.y, 0.f ); + GLi->Rotatef( mAngle, 0.0f, 0.0f, 1.0f ); + GLi->Translatef( -angleCenter.x, -angleCenter.y, 0.f ); } } void UIControlAnim::MatrixUnset() { if ( mScale != 1.f || mAngle != 0.f ) { GlobalBatchRenderer::instance()->Draw(); + GLi->PopMatrix(); } } @@ -320,7 +375,7 @@ void UIControlAnim::BorderDraw() { //! @TODO: Check why was this +0.1f -0.1f? if ( mFlags & UI_CLIP_ENABLE ) { - Rectf R( Vector2f( (Float)mScreenPos.x + 0.1f, (Float)mScreenPos.y + 0.1f ), Sizef( (Float)mSize.Width() - 0.1f, (Float)mSize.Height() - 0.1f ) ); + Rectf R( Vector2f( mScreenPosf.x + 0.1f, mScreenPosf.y + 0.1f ), Sizef( (Float)mSize.Width() - 0.1f, (Float)mSize.Height() - 0.1f ) ); if ( mBackground->Corners() ) { P.DrawRoundedRectangle( GetRectf(), 0.f, Vector2f::One, mBackground->Corners() ); @@ -341,11 +396,10 @@ ColorA UIControlAnim::GetColor( const ColorA& Col ) { } void UIControlAnim::UpdateQuad() { - mPoly = Polygon2f( eeAABB( (Float)mScreenPos.x, (Float)mScreenPos.y, (Float)mScreenPos.x + mSize.Width(), (Float)mScreenPos.y + mSize.Height() ) ); - mCenter = Vector2f( (Float)mScreenPos.x + (Float)mSize.Width() * 0.5f, (Float)mScreenPos.y + (Float)mSize.Height() * 0.5f ); + mPoly = Polygon2f( eeAABB( mScreenPosf.x, mScreenPosf.y, mScreenPosf.x + mSize.Width(), mScreenPosf.y + mSize.Height() ) ); - mPoly.Rotate( mAngle, mCenter ); - mPoly.Scale( mScale, mCenter ); + mPoly.Rotate( mAngle, AngleCenter() ); + mPoly.Scale( mScale, ScaleCenter() ); UIControl * tParent = Parent(); @@ -353,14 +407,42 @@ void UIControlAnim::UpdateQuad() { if ( tParent->IsAnimated() ) { UIControlAnim * tP = reinterpret_cast ( tParent ); - mPoly.Rotate( tP->Angle(), tP->GetPolygonCenter() ); - mPoly.Scale( tP->Scale(), tP->GetPolygonCenter() ); + mPoly.Rotate( tP->Angle(), tP->AngleCenter() ); + mPoly.Scale( tP->Scale(), tP->ScaleCenter() ); } tParent = tParent->Parent(); }; } +void UIControlAnim::OnSizeChange() { + UpdateOriginPoint(); +} + +void UIControlAnim::UpdateOriginPoint() { + switch ( mAngleOriginPoint.OriginType ) { + case OriginPoint::OriginCenter: + mAngleOriginPoint.x = mSize.x * 0.5f; + mAngleOriginPoint.y = mSize.y * 0.5f; + break; + case OriginPoint::OriginTopLeft: + mAngleOriginPoint.x = mAngleOriginPoint.y = 0; + break; + default: {} + } + + switch ( mScaleOriginPoint.OriginType ) { + case OriginPoint::OriginCenter: + mScaleOriginPoint.x = mSize.x * 0.5f; + mScaleOriginPoint.y = mSize.y * 0.5f; + break; + case OriginPoint::OriginTopLeft: + mScaleOriginPoint.x = mScaleOriginPoint.y = 0; + break; + default: {} + } +} + Interpolation * UIControlAnim::RotationInterpolation() { if ( NULL == mAngleAnim ) mAngleAnim = eeNew( Interpolation, () );