2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "GUIControl.h"
11 #include "GUIAction.h"
12 #include "GUIComponent.h"
13 #include "GUIControlProfiler.h"
14 #include "GUIInfoManager.h"
15 #include "GUIMessage.h"
16 #include "GUITexture.h"
17 #include "GUIWindowManager.h"
18 #include "ServiceBroker.h"
19 #include "input/InputManager.h"
20 #include "input/actions/Action.h"
21 #include "input/actions/ActionIDs.h"
22 #include "input/mouse/MouseEvent.h"
23 #include "input/mouse/MouseStat.h"
24 #include "utils/log.h"
27 using namespace GUILIB
;
29 CGUIControl::CGUIControl()
31 m_hasProcessed
= false;
36 m_visibleFromSkinCondition
= true;
37 m_forceHidden
= false;
43 ControlType
= GUICONTROL_UNKNOWN
;
44 m_bInvalidated
= true;
46 m_parentControl
= NULL
;
48 m_pushedUpdates
= false;
49 m_pulseOnSelect
= false;
50 m_controlDirtyState
= DIRTY_STATE_CONTROL
;
52 m_controlStats
= nullptr;
55 CGUIControl::CGUIControl(int parentID
, int controlID
, float posX
, float posY
, float width
, float height
)
56 : m_hitRect(posX
, posY
, posX
+ width
, posY
+ height
),
57 m_diffuseColor(0xffffffff)
64 m_controlID
= controlID
;
65 m_parentID
= parentID
;
67 m_visibleFromSkinCondition
= true;
68 m_forceHidden
= false;
70 ControlType
= GUICONTROL_UNKNOWN
;
71 m_bInvalidated
= true;
73 m_hasProcessed
= false;
74 m_parentControl
= NULL
;
76 m_pushedUpdates
= false;
77 m_pulseOnSelect
= false;
78 m_controlDirtyState
= DIRTY_STATE_CONTROL
;
80 m_controlStats
= nullptr;
83 CGUIControl::CGUIControl(const CGUIControl
&) = default;
85 CGUIControl::~CGUIControl(void) = default;
87 void CGUIControl::AllocResources()
89 m_hasProcessed
= false;
90 m_bInvalidated
= true;
94 void CGUIControl::FreeResources(bool immediately
)
98 // Reset our animation states - not conditional anims though.
99 // I'm not sure if this is needed for most cases anyway. I believe it's only here
100 // because some windows aren't loaded on demand
101 for (unsigned int i
= 0; i
< m_animations
.size(); i
++)
103 CAnimation
&anim
= m_animations
[i
];
104 if (anim
.GetType() != ANIM_TYPE_CONDITIONAL
)
105 anim
.ResetAnimation();
109 m_hasProcessed
= false;
112 void CGUIControl::DynamicResourceAlloc(bool bOnOff
)
117 // the main processing routine.
118 // 1. animate and set animation transform
119 // 2. if visible, process
120 // 3. reset the animation transform
121 void CGUIControl::DoProcess(unsigned int currentTime
, CDirtyRegionList
&dirtyregions
)
123 CRect dirtyRegion
= m_renderRegion
;
125 bool changed
= (m_controlDirtyState
& DIRTY_STATE_CONTROL
) != 0 || (m_bInvalidated
&& IsVisible());
126 m_controlDirtyState
= 0;
128 if (Animate(currentTime
))
131 // if the control changed culling state from true to false, mark it
132 const bool culled
= m_transform
.alpha
<= 0.01f
;
133 if (m_isCulled
!= culled
)
142 m_cachedTransform
= CServiceBroker::GetWinSystem()->GetGfxContext().AddTransform(m_transform
);
144 CServiceBroker::GetWinSystem()->GetGfxContext().SetCameraPosition(m_camera
);
146 Process(currentTime
, dirtyregions
);
147 m_bInvalidated
= false;
149 if (dirtyRegion
!= m_renderRegion
)
151 dirtyRegion
.Union(m_renderRegion
);
156 CServiceBroker::GetWinSystem()->GetGfxContext().RestoreCameraPosition();
157 CServiceBroker::GetWinSystem()->GetGfxContext().RemoveTransform();
160 UpdateControlStats();
162 changed
|= (m_controlDirtyState
& DIRTY_STATE_CONTROL
) != 0;
166 dirtyregions
.emplace_back(dirtyRegion
);
170 void CGUIControl::Process(unsigned int currentTime
, CDirtyRegionList
&dirtyregions
)
172 // update our render region
173 m_renderRegion
= CServiceBroker::GetWinSystem()->GetGfxContext().GenerateAABB(CalcRenderRegion());
174 m_hasProcessed
= true;
177 // the main render routine.
178 // 1. set the animation transform
179 // 2. if visible, paint
180 // 3. reset the animation transform
181 void CGUIControl::DoRender()
183 if (IsControlRenderable() &&
184 !m_renderRegion
.Intersects(CServiceBroker::GetWinSystem()->GetGfxContext().GetScissors()))
187 if (IsVisible() && !m_isCulled
)
191 CServiceBroker::GetWinSystem()->GetGfxContext().GetStereoMode() !=
192 RENDER_STEREO_MODE_MONO
&&
193 CServiceBroker::GetWinSystem()->GetGfxContext().GetStereoMode() != RENDER_STEREO_MODE_OFF
;
195 CServiceBroker::GetWinSystem()->GetGfxContext().SetTransform(m_cachedTransform
);
197 CServiceBroker::GetWinSystem()->GetGfxContext().SetCameraPosition(m_camera
);
199 CServiceBroker::GetWinSystem()->GetGfxContext().SetStereoFactor(m_stereo
);
201 GUIPROFILER_RENDER_BEGIN(this);
203 if (m_hitColor
!= 0xffffffff)
205 KODI::UTILS::COLOR::Color color
=
206 CServiceBroker::GetWinSystem()->GetGfxContext().MergeAlpha(m_hitColor
);
207 CGUITexture::DrawQuad(CServiceBroker::GetWinSystem()->GetGfxContext().GenerateAABB(m_hitRect
), color
);
212 GUIPROFILER_RENDER_END(this);
215 CServiceBroker::GetWinSystem()->GetGfxContext().RestoreStereoFactor();
217 CServiceBroker::GetWinSystem()->GetGfxContext().RestoreCameraPosition();
218 CServiceBroker::GetWinSystem()->GetGfxContext().RemoveTransform();
222 bool CGUIControl::OnAction(const CAction
&action
)
226 switch (action
.GetID())
228 case ACTION_MOVE_DOWN
:
236 case ACTION_MOVE_LEFT
:
240 case ACTION_MOVE_RIGHT
:
244 case ACTION_SHOW_INFO
:
247 case ACTION_NAV_BACK
:
250 case ACTION_NEXT_CONTROL
:
254 case ACTION_PREV_CONTROL
:
262 bool CGUIControl::Navigate(int direction
) const
266 CGUIMessage
msg(GUI_MSG_MOVE
, GetParentID(), GetID(), direction
);
267 return SendWindowMessage(msg
);
272 // Movement controls (derived classes can override)
273 void CGUIControl::OnUp()
275 Navigate(ACTION_MOVE_UP
);
278 void CGUIControl::OnDown()
280 Navigate(ACTION_MOVE_DOWN
);
283 void CGUIControl::OnLeft()
285 Navigate(ACTION_MOVE_LEFT
);
288 void CGUIControl::OnRight()
290 Navigate(ACTION_MOVE_RIGHT
);
293 bool CGUIControl::OnBack()
295 return Navigate(ACTION_NAV_BACK
);
298 bool CGUIControl::OnInfo()
300 CGUIAction action
= GetAction(ACTION_SHOW_INFO
);
301 if (action
.HasAnyActions())
302 return action
.ExecuteActions(GetID(), GetParentID());
306 void CGUIControl::OnNextControl()
308 Navigate(ACTION_NEXT_CONTROL
);
311 void CGUIControl::OnPrevControl()
313 Navigate(ACTION_PREV_CONTROL
);
316 bool CGUIControl::SendWindowMessage(CGUIMessage
&message
) const
318 CGUIWindow
*pWindow
= CServiceBroker::GetGUI()->GetWindowManager().GetWindow(GetParentID());
320 return pWindow
->OnMessage(message
);
321 return CServiceBroker::GetGUI()->GetWindowManager().SendMessage(message
);
324 int CGUIControl::GetID(void) const
330 int CGUIControl::GetParentID(void) const
335 bool CGUIControl::HasFocus(void) const
340 void CGUIControl::SetFocus(bool focus
)
342 if (m_bHasFocus
&& !focus
)
343 QueueAnimation(ANIM_TYPE_UNFOCUS
);
344 else if (!m_bHasFocus
&& focus
)
345 QueueAnimation(ANIM_TYPE_FOCUS
);
349 bool CGUIControl::OnMessage(CGUIMessage
& message
)
351 if ( message
.GetControlId() == GetID() )
353 switch (message
.GetMessage() )
355 case GUI_MSG_SETFOCUS
:
356 // if control is disabled then move 2 the next control
360 "Control {} in window {} has been asked to focus, "
362 GetID(), GetParentID());
367 // inform our parent window that this has happened
368 CGUIMessage
message(GUI_MSG_FOCUSED
, GetParentID(), GetID());
370 m_parentControl
->OnMessage(message
);
375 case GUI_MSG_LOSTFOCUS
:
378 // and tell our parent so it can unfocus
380 m_parentControl
->OnMessage(message
);
385 case GUI_MSG_VISIBLE
:
386 SetVisible(true, true);
394 // Note that the skin <enable> tag will override these messages
395 case GUI_MSG_ENABLED
:
399 case GUI_MSG_DISABLED
:
403 case GUI_MSG_WINDOW_RESIZE
:
404 // invalidate controls to get them to recalculate sizing information
412 bool CGUIControl::CanFocus() const
414 if (!IsVisible() && !m_allowHiddenFocus
) return false;
415 if (IsDisabled()) return false;
419 bool CGUIControl::IsVisible() const
423 return m_visible
== VISIBLE
;
426 bool CGUIControl::IsDisabled() const
431 void CGUIControl::SetEnabled(bool bEnable
)
433 if (bEnable
!= m_enabled
)
440 void CGUIControl::SetEnableCondition(const std::string
&expression
)
442 if (expression
== "true")
444 else if (expression
== "false")
447 m_enableCondition
= CServiceBroker::GetGUI()->GetInfoManager().Register(expression
, GetParentID());
450 void CGUIControl::SetPosition(float posX
, float posY
)
452 if ((m_posX
!= posX
) || (m_posY
!= posY
))
456 m_hitRect
+= CPoint(posX
- m_posX
, posY
- m_posY
);
464 bool CGUIControl::SetColorDiffuse(const GUIINFO::CGUIInfoColor
&color
)
466 bool changed
= m_diffuseColor
!= color
;
467 m_diffuseColor
= color
;
471 float CGUIControl::GetXPosition() const
476 float CGUIControl::GetYPosition() const
481 float CGUIControl::GetWidth() const
486 float CGUIControl::GetHeight() const
491 void CGUIControl::AssignDepth()
493 m_cachedTransform
.depth
= CServiceBroker::GetWinSystem()->GetGfxContext().GetDepth();
496 void CGUIControl::MarkDirtyRegion(const unsigned int dirtyState
)
498 // if the control is culled, bail
499 if (dirtyState
== DIRTY_STATE_CONTROL
&& m_isCulled
)
501 if (!m_controlDirtyState
&& m_parentControl
)
502 m_parentControl
->MarkDirtyRegion(DIRTY_STATE_CHILD
);
504 m_controlDirtyState
|= dirtyState
;
507 CRect
CGUIControl::CalcRenderRegion() const
509 CPoint
tl(GetXPosition(), GetYPosition());
510 CPoint
br(tl
.x
+ GetWidth(), tl
.y
+ GetHeight());
512 return CRect(tl
.x
, tl
.y
, br
.x
, br
.y
);
515 void CGUIControl::SetActions(const ActionMap
&actions
)
520 void CGUIControl::SetAction(int actionID
, const CGUIAction
&action
, bool replace
/*= true*/)
522 ActionMap::iterator i
= m_actions
.find(actionID
);
523 if (i
== m_actions
.end() || !i
->second
.HasAnyActions() || replace
)
524 m_actions
[actionID
] = action
;
527 void CGUIControl::SetWidth(float width
)
529 if (m_width
!= width
)
533 m_hitRect
.x2
= m_hitRect
.x1
+ width
;
538 void CGUIControl::SetHeight(float height
)
540 if (m_height
!= height
)
544 m_hitRect
.y2
= m_hitRect
.y1
+ height
;
549 void CGUIControl::SetVisible(bool bVisible
, bool setVisState
)
551 if (bVisible
&& setVisState
)
552 { //! @todo currently we only update m_visible from GUI_MSG_VISIBLE (SET_CONTROL_VISIBLE)
553 //! otherwise we just set m_forceHidden
555 if (m_visibleCondition
)
556 visible
= m_visibleCondition
->Get(INFO::DEFAULT_CONTEXT
) ? VISIBLE
: HIDDEN
;
559 if (visible
!= m_visible
)
565 if (m_forceHidden
== bVisible
)
567 m_forceHidden
= !bVisible
;
573 { // reset any visible animations that are in process
574 if (IsAnimating(ANIM_TYPE_VISIBLE
))
576 // CLog::Log(LOGDEBUG, "Resetting visible animation on control {} (we are {})", m_controlID, m_visible ? "visible" : "hidden");
577 CAnimation
*visibleAnim
= GetAnimation(ANIM_TYPE_VISIBLE
);
578 if (visibleAnim
) visibleAnim
->ResetAnimation();
583 bool CGUIControl::HitTest(const CPoint
&point
) const
585 return m_hitRect
.PtInRect(point
);
588 EVENT_RESULT
CGUIControl::SendMouseEvent(const CPoint
& point
, const MOUSE::CMouseEvent
& event
)
590 CPoint
childPoint(point
);
591 m_transform
.InverseTransformPosition(childPoint
.x
, childPoint
.y
);
592 if (!CanFocusFromPoint(childPoint
))
593 return EVENT_RESULT_UNHANDLED
;
595 bool handled
= event
.m_id
!= ACTION_MOUSE_MOVE
|| OnMouseOver(childPoint
);
596 EVENT_RESULT ret
= OnMouseEvent(childPoint
, event
);
599 return (handled
&& (event
.m_id
== ACTION_MOUSE_MOVE
)) ? EVENT_RESULT_HANDLED
: EVENT_RESULT_UNHANDLED
;
602 // override this function to implement custom mouse behaviour
603 bool CGUIControl::OnMouseOver(const CPoint
&point
)
605 if (CServiceBroker::GetInputManager().GetMouseState() != MOUSE_STATE_DRAG
)
606 CServiceBroker::GetInputManager().SetMouseState(MOUSE_STATE_FOCUS
);
607 if (!CanFocus()) return false;
610 CGUIMessage
msg(GUI_MSG_SETFOCUS
, GetParentID(), GetID());
616 void CGUIControl::UpdateVisibility(const CGUIListItem
*item
)
618 if (m_visibleCondition
)
620 bool bWasVisible
= m_visibleFromSkinCondition
;
621 m_visibleFromSkinCondition
= m_visibleCondition
->Get(INFO::DEFAULT_CONTEXT
, item
);
622 if (!bWasVisible
&& m_visibleFromSkinCondition
)
623 { // automatic change of visibility - queue the in effect
624 // CLog::Log(LOGDEBUG, "Visibility changed to visible for control id {}", m_controlID);
625 QueueAnimation(ANIM_TYPE_VISIBLE
);
627 else if (bWasVisible
&& !m_visibleFromSkinCondition
)
628 { // automatic change of visibility - do the out effect
629 // CLog::Log(LOGDEBUG, "Visibility changed to hidden for control id {}", m_controlID);
630 QueueAnimation(ANIM_TYPE_HIDDEN
);
633 // check for conditional animations
634 for (unsigned int i
= 0; i
< m_animations
.size(); i
++)
636 CAnimation
&anim
= m_animations
[i
];
637 if (anim
.GetType() == ANIM_TYPE_CONDITIONAL
)
638 anim
.UpdateCondition(item
);
640 // and check for conditional enabling - note this overrides SetEnabled() from the code currently
641 // this may need to be reviewed at a later date
642 bool enabled
= m_enabled
;
643 if (m_enableCondition
)
644 m_enabled
= m_enableCondition
->Get(INFO::DEFAULT_CONTEXT
, item
);
646 if (m_enabled
!= enabled
)
649 m_allowHiddenFocus
.Update(INFO::DEFAULT_CONTEXT
, item
);
650 if (UpdateColors(item
))
652 // and finally, update our control information (if not pushed)
653 if (!m_pushedUpdates
)
657 bool CGUIControl::UpdateColors(const CGUIListItem
* item
)
659 return m_diffuseColor
.Update(item
);
662 void CGUIControl::SetInitialVisibility()
664 if (m_visibleCondition
)
666 m_visibleFromSkinCondition
= m_visibleCondition
->Get(INFO::DEFAULT_CONTEXT
);
667 m_visible
= m_visibleFromSkinCondition
? VISIBLE
: HIDDEN
;
668 // CLog::Log(LOGDEBUG, "Set initial visibility for control {}: {}", m_controlID, m_visible == VISIBLE ? "visible" : "hidden");
670 else if (m_visible
== DELAYED
)
672 // and handle animation conditions as well
673 for (unsigned int i
= 0; i
< m_animations
.size(); i
++)
675 CAnimation
&anim
= m_animations
[i
];
676 if (anim
.GetType() == ANIM_TYPE_CONDITIONAL
)
677 anim
.SetInitialCondition();
679 // and check for conditional enabling - note this overrides SetEnabled() from the code currently
680 // this may need to be reviewed at a later date
681 if (m_enableCondition
)
682 m_enabled
= m_enableCondition
->Get(INFO::DEFAULT_CONTEXT
);
683 m_allowHiddenFocus
.Update(INFO::DEFAULT_CONTEXT
);
684 UpdateColors(nullptr);
689 void CGUIControl::SetVisibleCondition(const std::string
&expression
, const std::string
&allowHiddenFocus
)
691 if (expression
== "true")
693 else if (expression
== "false")
695 else // register with the infomanager for updates
696 m_visibleCondition
= CServiceBroker::GetGUI()->GetInfoManager().Register(expression
, GetParentID());
697 m_allowHiddenFocus
.Parse(allowHiddenFocus
, GetParentID());
700 void CGUIControl::SetAnimations(const std::vector
<CAnimation
> &animations
)
702 m_animations
= animations
;
706 void CGUIControl::ResetAnimation(ANIMATION_TYPE type
)
710 for (unsigned int i
= 0; i
< m_animations
.size(); i
++)
712 if (m_animations
[i
].GetType() == type
)
713 m_animations
[i
].ResetAnimation();
717 void CGUIControl::ResetAnimations()
721 for (unsigned int i
= 0; i
< m_animations
.size(); i
++)
722 m_animations
[i
].ResetAnimation();
727 bool CGUIControl::CheckAnimation(ANIMATION_TYPE animType
)
729 // rule out the animations we shouldn't perform
730 if (!IsVisible() || !HasProcessed())
731 { // hidden or never processed - don't allow exit or entry animations for this control
732 if (animType
== ANIM_TYPE_WINDOW_CLOSE
)
733 { // could be animating a (delayed) window open anim, so reset it
734 ResetAnimation(ANIM_TYPE_WINDOW_OPEN
);
739 { // hidden - only allow hidden anims if we're animating a visible anim
740 if (animType
== ANIM_TYPE_HIDDEN
&& !IsAnimating(ANIM_TYPE_VISIBLE
))
742 // update states to force it hidden
743 UpdateStates(animType
, ANIM_PROCESS_NORMAL
, ANIM_STATE_APPLIED
);
746 if (animType
== ANIM_TYPE_WINDOW_OPEN
)
752 void CGUIControl::QueueAnimation(ANIMATION_TYPE animType
)
754 if (!CheckAnimation(animType
))
759 CAnimation
*reverseAnim
= GetAnimation((ANIMATION_TYPE
)-animType
, false);
760 CAnimation
*forwardAnim
= GetAnimation(animType
);
761 // we first check whether the reverse animation is in progress (and reverse it)
762 // then we check for the normal animation, and queue it
763 if (reverseAnim
&& reverseAnim
->IsReversible() && (reverseAnim
->GetState() == ANIM_STATE_IN_PROCESS
|| reverseAnim
->GetState() == ANIM_STATE_DELAYED
))
765 reverseAnim
->QueueAnimation(ANIM_PROCESS_REVERSE
);
766 if (forwardAnim
) forwardAnim
->ResetAnimation();
768 else if (forwardAnim
)
770 forwardAnim
->QueueAnimation(ANIM_PROCESS_NORMAL
);
771 if (reverseAnim
) reverseAnim
->ResetAnimation();
774 { // hidden and visible animations delay the change of state. If there is no animations
775 // to perform, then we should just change the state straightaway
776 if (reverseAnim
) reverseAnim
->ResetAnimation();
777 UpdateStates(animType
, ANIM_PROCESS_NORMAL
, ANIM_STATE_APPLIED
);
781 CAnimation
*CGUIControl::GetAnimation(ANIMATION_TYPE type
, bool checkConditions
/* = true */)
783 for (unsigned int i
= 0; i
< m_animations
.size(); i
++)
785 CAnimation
&anim
= m_animations
[i
];
786 if (anim
.GetType() == type
)
788 if (!checkConditions
|| anim
.CheckCondition())
795 bool CGUIControl::HasAnimation(ANIMATION_TYPE type
)
797 return (NULL
!= GetAnimation(type
, true));
800 void CGUIControl::UpdateStates(ANIMATION_TYPE type
, ANIMATION_PROCESS currentProcess
, ANIMATION_STATE currentState
)
802 // Make sure control is hidden or visible at the appropriate times
803 // while processing a visible or hidden animation it needs to be visible,
804 // but when finished a hidden operation it needs to be hidden
805 if (type
== ANIM_TYPE_VISIBLE
)
807 if (currentProcess
== ANIM_PROCESS_REVERSE
)
809 if (currentState
== ANIM_STATE_APPLIED
)
812 else if (currentProcess
== ANIM_PROCESS_NORMAL
)
814 if (currentState
== ANIM_STATE_DELAYED
)
817 m_visible
= m_visibleFromSkinCondition
? VISIBLE
: HIDDEN
;
820 else if (type
== ANIM_TYPE_HIDDEN
)
822 if (currentProcess
== ANIM_PROCESS_NORMAL
) // a hide animation
824 if (currentState
== ANIM_STATE_APPLIED
)
825 m_visible
= HIDDEN
; // finished
827 m_visible
= VISIBLE
; // have to be visible until we are finished
829 else if (currentProcess
== ANIM_PROCESS_REVERSE
) // a visible animation
830 { // no delay involved here - just make sure it's visible
831 m_visible
= m_visibleFromSkinCondition
? VISIBLE
: HIDDEN
;
834 else if (type
== ANIM_TYPE_WINDOW_OPEN
)
836 if (currentProcess
== ANIM_PROCESS_NORMAL
)
838 if (currentState
== ANIM_STATE_DELAYED
)
839 m_visible
= DELAYED
; // delayed
841 m_visible
= m_visibleFromSkinCondition
? VISIBLE
: HIDDEN
;
844 else if (type
== ANIM_TYPE_FOCUS
)
846 // call the focus function if we have finished a focus animation
847 // (buttons can "click" on focus)
848 if (currentProcess
== ANIM_PROCESS_NORMAL
&& currentState
== ANIM_STATE_APPLIED
)
851 else if (type
== ANIM_TYPE_UNFOCUS
)
853 // call the unfocus function if we have finished a focus animation
854 // (buttons can "click" on focus)
855 if (currentProcess
== ANIM_PROCESS_NORMAL
&& currentState
== ANIM_STATE_APPLIED
)
860 bool CGUIControl::Animate(unsigned int currentTime
)
862 // check visible state outside the loop, as it could change
863 GUIVISIBLE visible
= m_visible
;
866 bool changed
= false;
868 CPoint
center(GetXPosition() + GetWidth() * 0.5f
, GetYPosition() + GetHeight() * 0.5f
);
869 for (unsigned int i
= 0; i
< m_animations
.size(); i
++)
871 CAnimation
&anim
= m_animations
[i
];
872 anim
.Animate(currentTime
, HasProcessed() || visible
== DELAYED
);
873 // Update the control states (such as visibility)
874 UpdateStates(anim
.GetType(), anim
.GetProcess(), anim
.GetState());
875 // and render the animation effect
876 changed
|= (anim
.GetProcess() != ANIM_PROCESS_NONE
);
877 anim
.RenderAnimation(m_transform
, center
);
880 //if (anim.GetProcess() != ANIM_PROCESS_NONE && IsVisible())
882 // CLog::Log(LOGDEBUG, "Animating control {}", m_controlID);
889 bool CGUIControl::IsAnimating(ANIMATION_TYPE animType
)
891 for (unsigned int i
= 0; i
< m_animations
.size(); i
++)
893 CAnimation
&anim
= m_animations
[i
];
894 if (anim
.GetType() == animType
)
896 if (anim
.GetQueuedProcess() == ANIM_PROCESS_NORMAL
)
898 if (anim
.GetProcess() == ANIM_PROCESS_NORMAL
)
901 else if (anim
.GetType() == -animType
)
903 if (anim
.GetQueuedProcess() == ANIM_PROCESS_REVERSE
)
905 if (anim
.GetProcess() == ANIM_PROCESS_REVERSE
)
912 CGUIAction
CGUIControl::GetAction(int actionID
) const
914 ActionMap::const_iterator i
= m_actions
.find(actionID
);
915 if (i
!= m_actions
.end())
920 bool CGUIControl::CanFocusFromPoint(const CPoint
&point
) const
922 return CanFocus() && HitTest(point
);
925 void CGUIControl::UnfocusFromPoint(const CPoint
&point
)
929 CPoint
controlPoint(point
);
930 m_transform
.InverseTransformPosition(controlPoint
.x
, controlPoint
.y
);
931 if (!HitTest(controlPoint
))
935 // and tell our parent so it can unfocus
938 CGUIMessage
msgLostFocus(GUI_MSG_LOSTFOCUS
, GetID(), GetID());
939 m_parentControl
->OnMessage(msgLostFocus
);
945 void CGUIControl::SaveStates(std::vector
<CControlState
> &states
)
947 // empty for now - do nothing with the majority of controls
950 CGUIControl
*CGUIControl::GetControl(int iControl
, std::vector
<CGUIControl
*> *idCollector
)
952 return (iControl
== m_controlID
) ? this : nullptr;
956 void CGUIControl::UpdateControlStats()
960 ++m_controlStats
->nCountTotal
;
961 if (IsVisible() && IsVisibleFromSkin())
962 ++m_controlStats
->nCountVisible
;
966 bool CGUIControl::IsControlRenderable()
970 case GUICONTAINER_EPGGRID
:
971 case GUICONTAINER_FIXEDLIST
:
972 case GUICONTAINER_LIST
:
973 case GUICONTAINER_PANEL
:
974 case GUICONTAINER_WRAPLIST
:
975 case GUICONTROL_GROUP
:
976 case GUICONTROL_GROUPLIST
:
977 case GUICONTROL_LISTGROUP
:
984 void CGUIControl::SetHitRect(const CRect
& rect
, const KODI::UTILS::COLOR::Color
& color
)
990 void CGUIControl::SetCamera(const CPoint
&camera
)
996 CPoint
CGUIControl::GetRenderPosition() const
999 CPoint
point(GetPosition());
1000 m_transform
.TransformPosition(point
.x
, point
.y
, z
);
1001 if (m_parentControl
)
1002 point
+= m_parentControl
->GetRenderPosition();
1006 void CGUIControl::SetStereoFactor(const float &factor
)