2 * Copyright (C) 2005-2012 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
21 #include "GUIControl.h"
23 #include "GUIInfoManager.h"
24 #include "utils/log.h"
25 #include "LocalizeStrings.h"
26 #include "GUIWindowManager.h"
27 #include "GUIControlProfiler.h"
28 #include "input/MouseStat.h"
33 CGUIControl::CGUIControl()
35 m_hasRendered = false;
40 m_visibleFromSkinCondition = true;
41 m_forceHidden = false;
42 m_visibleCondition = 0;
43 m_enableCondition = 0;
45 m_diffuseColor = 0xffffffff;
50 ControlType = GUICONTROL_UNKNOWN;
51 m_bInvalidated = true;
53 m_parentControl = NULL;
55 m_pushedUpdates = false;
56 m_pulseOnSelect = false;
57 m_controlIsDirty = true;
60 CGUIControl::CGUIControl(int parentID, int controlID, float posX, float posY, float width, float height)
61 : m_hitRect(posX, posY, posX + width, posY + height)
68 m_controlID = controlID;
69 m_parentID = parentID;
71 m_visibleFromSkinCondition = true;
72 m_diffuseColor = 0xffffffff;
73 m_forceHidden = false;
74 m_visibleCondition = 0;
75 m_enableCondition = 0;
77 ControlType = GUICONTROL_UNKNOWN;
78 m_bInvalidated = true;
80 m_hasRendered = false;
81 m_parentControl = NULL;
83 m_pushedUpdates = false;
84 m_pulseOnSelect = false;
85 m_controlIsDirty = false;
89 CGUIControl::~CGUIControl(void)
94 void CGUIControl::AllocResources()
96 m_hasRendered = false;
97 m_bInvalidated = true;
101 void CGUIControl::FreeResources(bool immediately)
105 // Reset our animation states - not conditional anims though.
106 // I'm not sure if this is needed for most cases anyway. I believe it's only here
107 // because some windows aren't loaded on demand
108 for (unsigned int i = 0; i < m_animations.size(); i++)
110 CAnimation &anim = m_animations[i];
111 if (anim.GetType() != ANIM_TYPE_CONDITIONAL)
112 anim.ResetAnimation();
116 m_hasRendered = false;
119 void CGUIControl::DynamicResourceAlloc(bool bOnOff)
124 // the main processing routine.
125 // 1. animate and set animation transform
126 // 2. if visible, process
127 // 3. reset the animation transform
128 void CGUIControl::DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyregions)
130 CRect dirtyRegion = m_renderRegion;
132 bool changed = m_bInvalidated && IsVisible();
134 changed |= Animate(currentTime);
136 m_cachedTransform = g_graphicsContext.AddTransform(m_transform);
138 g_graphicsContext.SetCameraPosition(m_camera);
142 Process(currentTime, dirtyregions);
143 m_bInvalidated = false;
146 changed |= m_controlIsDirty;
148 if (changed || dirtyRegion != m_renderRegion)
150 dirtyRegion.Union(m_renderRegion);
151 dirtyregions.push_back(dirtyRegion);
155 g_graphicsContext.RestoreCameraPosition();
156 g_graphicsContext.RemoveTransform();
158 m_controlIsDirty = false;
161 void CGUIControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
163 // update our render region
164 m_renderRegion = g_graphicsContext.generateAABB(CalcRenderRegion());
167 // the main render routine.
168 // 1. set the animation transform
169 // 2. if visible, paint
170 // 3. reset the animation transform
171 void CGUIControl::DoRender()
173 g_graphicsContext.SetTransform(m_cachedTransform);
175 g_graphicsContext.SetCameraPosition(m_camera);
178 GUIPROFILER_RENDER_BEGIN(this);
180 GUIPROFILER_RENDER_END(this);
183 g_graphicsContext.RestoreCameraPosition();
184 g_graphicsContext.RemoveTransform();
187 void CGUIControl::Render()
189 m_hasRendered = true;
192 bool CGUIControl::OnAction(const CAction &action)
196 switch (action.GetID())
198 case ACTION_MOVE_DOWN:
206 case ACTION_MOVE_LEFT:
210 case ACTION_MOVE_RIGHT:
214 case ACTION_NAV_BACK:
217 case ACTION_NEXT_CONTROL:
221 case ACTION_PREV_CONTROL:
229 bool CGUIControl::Navigate(int direction)
233 CGUIMessage msg(GUI_MSG_MOVE, GetParentID(), GetID(), direction);
234 return SendWindowMessage(msg);
239 // Movement controls (derived classes can override)
240 void CGUIControl::OnUp()
242 Navigate(ACTION_MOVE_UP);
245 void CGUIControl::OnDown()
247 Navigate(ACTION_MOVE_DOWN);
250 void CGUIControl::OnLeft()
252 Navigate(ACTION_MOVE_LEFT);
255 void CGUIControl::OnRight()
257 Navigate(ACTION_MOVE_RIGHT);
260 bool CGUIControl::OnBack()
262 return Navigate(ACTION_NAV_BACK);
265 void CGUIControl::OnNextControl()
267 Navigate(ACTION_NEXT_CONTROL);
270 void CGUIControl::OnPrevControl()
272 Navigate(ACTION_PREV_CONTROL);
275 bool CGUIControl::SendWindowMessage(CGUIMessage &message)
277 CGUIWindow *pWindow = g_windowManager.GetWindow(GetParentID());
279 return pWindow->OnMessage(message);
280 return g_windowManager.SendMessage(message);
283 int CGUIControl::GetID(void) const
289 int CGUIControl::GetParentID(void) const
294 bool CGUIControl::HasFocus(void) const
299 void CGUIControl::SetFocus(bool focus)
301 if (m_bHasFocus && !focus)
302 QueueAnimation(ANIM_TYPE_UNFOCUS);
303 else if (!m_bHasFocus && focus)
304 QueueAnimation(ANIM_TYPE_FOCUS);
308 bool CGUIControl::OnMessage(CGUIMessage& message)
310 if ( message.GetControlId() == GetID() )
312 switch (message.GetMessage() )
314 case GUI_MSG_SETFOCUS:
315 // if control is disabled then move 2 the next control
318 CLog::Log(LOGERROR, "Control %u in window %u has been asked to focus, "
320 GetID(), GetParentID());
325 // inform our parent window that this has happened
326 CGUIMessage message(GUI_MSG_FOCUSED, GetParentID(), GetID());
328 m_parentControl->OnMessage(message);
333 case GUI_MSG_LOSTFOCUS:
336 // and tell our parent so it can unfocus
338 m_parentControl->OnMessage(message);
343 case GUI_MSG_VISIBLE:
344 SetVisible(true, true);
352 // Note that the skin <enable> tag will override these messages
353 case GUI_MSG_ENABLED:
357 case GUI_MSG_DISABLED:
361 case GUI_MSG_WINDOW_RESIZE:
362 // invalidate controls to get them to recalculate sizing information
370 bool CGUIControl::CanFocus() const
372 if (!IsVisible() && !m_allowHiddenFocus) return false;
373 if (IsDisabled()) return false;
377 bool CGUIControl::IsVisible() const
379 if (m_forceHidden) return false;
380 return m_visible == VISIBLE;
383 bool CGUIControl::IsDisabled() const
388 void CGUIControl::SetEnabled(bool bEnable)
390 if (bEnable != m_enabled)
397 void CGUIControl::SetEnableCondition(const CStdString &expression)
399 if (expression == "true")
401 else if (expression == "false")
404 m_enableCondition = g_infoManager.Register(expression, GetParentID());
407 void CGUIControl::SetPosition(float posX, float posY)
409 if ((m_posX != posX) || (m_posY != posY))
413 m_hitRect += CPoint(posX - m_posX, posY - m_posY);
421 bool CGUIControl::SetColorDiffuse(const CGUIInfoColor &color)
423 bool changed = m_diffuseColor != color;
424 m_diffuseColor = color;
428 float CGUIControl::GetXPosition() const
433 float CGUIControl::GetYPosition() const
438 float CGUIControl::GetWidth() const
443 float CGUIControl::GetHeight() const
448 void CGUIControl::MarkDirtyRegion()
450 m_controlIsDirty = true;
453 CRect CGUIControl::CalcRenderRegion() const
455 CPoint tl(GetXPosition(), GetYPosition());
456 CPoint br(tl.x + GetWidth(), tl.y + GetHeight());
458 return CRect(tl.x, tl.y, br.x, br.y);
461 void CGUIControl::SetNavigation(int up, int down, int left, int right, int back)
463 m_actionUp.SetNavigation(up);
464 m_actionDown.SetNavigation(down);
465 m_actionLeft.SetNavigation(left);
466 m_actionRight.SetNavigation(right);
467 m_actionBack.SetNavigation(back);
470 void CGUIControl::SetTabNavigation(int next, int prev)
472 m_actionNext.SetNavigation(next);
473 m_actionPrev.SetNavigation(prev);
476 void CGUIControl::SetNavigationActions(const CGUIAction &up, const CGUIAction &down,
477 const CGUIAction &left, const CGUIAction &right,
478 const CGUIAction &back, bool replace)
480 if (!m_actionLeft.HasAnyActions() || replace) m_actionLeft = left;
481 if (!m_actionRight.HasAnyActions() || replace) m_actionRight = right;
482 if (!m_actionUp.HasAnyActions() || replace) m_actionUp = up;
483 if (!m_actionDown.HasAnyActions() || replace) m_actionDown = down;
484 if (!m_actionBack.HasAnyActions() || replace) m_actionBack = back;
487 void CGUIControl::SetNavigationAction(int direction, const CGUIAction &action, bool replace /*= true*/)
492 if (!m_actionUp.HasAnyActions() || replace)
495 case ACTION_MOVE_DOWN:
496 if (!m_actionDown.HasAnyActions() || replace)
497 m_actionDown = action;
499 case ACTION_MOVE_LEFT:
500 if (!m_actionLeft.HasAnyActions() || replace)
501 m_actionLeft = action;
503 case ACTION_MOVE_RIGHT:
504 if (!m_actionRight.HasAnyActions() || replace)
505 m_actionRight = action;
507 case ACTION_NAV_BACK:
508 if (!m_actionBack.HasAnyActions() || replace)
509 m_actionBack = action;
514 void CGUIControl::SetWidth(float width)
516 if (m_width != width)
520 m_hitRect.x2 = m_hitRect.x1 + width;
525 void CGUIControl::SetHeight(float height)
527 if (m_height != height)
531 m_hitRect.y2 = m_hitRect.y1 + height;
536 void CGUIControl::SetVisible(bool bVisible, bool setVisState)
538 if (bVisible && setVisState)
539 { // TODO: currently we only update m_visible from GUI_MSG_VISIBLE (SET_CONTROL_VISIBLE)
540 // otherwise we just set m_forceHidden
541 GUIVISIBLE visible = m_visible;
542 if (m_visibleCondition)
543 visible = g_infoManager.GetBoolValue(m_visibleCondition) ? VISIBLE : HIDDEN;
546 if (visible != m_visible)
552 if (m_forceHidden == bVisible)
554 m_forceHidden = !bVisible;
558 { // reset any visible animations that are in process
559 if (IsAnimating(ANIM_TYPE_VISIBLE))
561 // CLog::Log(LOGDEBUG, "Resetting visible animation on control %i (we are %s)", m_controlID, m_visible ? "visible" : "hidden");
562 CAnimation *visibleAnim = GetAnimation(ANIM_TYPE_VISIBLE);
563 if (visibleAnim) visibleAnim->ResetAnimation();
568 bool CGUIControl::HitTest(const CPoint &point) const
570 return m_hitRect.PtInRect(point);
573 EVENT_RESULT CGUIControl::SendMouseEvent(const CPoint &point, const CMouseEvent &event)
575 CPoint childPoint(point);
576 m_transform.InverseTransformPosition(childPoint.x, childPoint.y);
577 if (!CanFocusFromPoint(childPoint))
578 return EVENT_RESULT_UNHANDLED;
580 bool handled = OnMouseOver(childPoint);
581 EVENT_RESULT ret = OnMouseEvent(childPoint, event);
584 return (handled && (event.m_id == ACTION_MOUSE_MOVE)) ? EVENT_RESULT_HANDLED : EVENT_RESULT_UNHANDLED;
587 // override this function to implement custom mouse behaviour
588 bool CGUIControl::OnMouseOver(const CPoint &point)
590 if (g_Mouse.GetState() != MOUSE_STATE_DRAG)
591 g_Mouse.SetState(MOUSE_STATE_FOCUS);
592 if (!CanFocus()) return false;
593 CGUIMessage msg(GUI_MSG_SETFOCUS, GetParentID(), GetID());
598 void CGUIControl::UpdateVisibility(const CGUIListItem *item)
600 if (m_visibleCondition)
602 bool bWasVisible = m_visibleFromSkinCondition;
603 m_visibleFromSkinCondition = g_infoManager.GetBoolValue(m_visibleCondition, item);
604 if (!bWasVisible && m_visibleFromSkinCondition)
605 { // automatic change of visibility - queue the in effect
606 // CLog::Log(LOGDEBUG, "Visibility changed to visible for control id %i", m_controlID);
607 QueueAnimation(ANIM_TYPE_VISIBLE);
609 else if (bWasVisible && !m_visibleFromSkinCondition)
610 { // automatic change of visibility - do the out effect
611 // CLog::Log(LOGDEBUG, "Visibility changed to hidden for control id %i", m_controlID);
612 QueueAnimation(ANIM_TYPE_HIDDEN);
615 // check for conditional animations
616 for (unsigned int i = 0; i < m_animations.size(); i++)
618 CAnimation &anim = m_animations[i];
619 if (anim.GetType() == ANIM_TYPE_CONDITIONAL)
620 anim.UpdateCondition(item);
622 // and check for conditional enabling - note this overrides SetEnabled() from the code currently
623 // this may need to be reviewed at a later date
624 bool enabled = m_enabled;
625 if (m_enableCondition)
626 m_enabled = g_infoManager.GetBoolValue(m_enableCondition, item);
628 if (m_enabled != enabled)
631 m_allowHiddenFocus.Update(item);
634 // and finally, update our control information (if not pushed)
635 if (!m_pushedUpdates)
639 bool CGUIControl::UpdateColors()
641 return m_diffuseColor.Update();
644 void CGUIControl::SetInitialVisibility()
646 if (m_visibleCondition)
648 m_visibleFromSkinCondition = g_infoManager.GetBoolValue(m_visibleCondition);
649 m_visible = m_visibleFromSkinCondition ? VISIBLE : HIDDEN;
650 // CLog::Log(LOGDEBUG, "Set initial visibility for control %i: %s", m_controlID, m_visible == VISIBLE ? "visible" : "hidden");
652 // and handle animation conditions as well
653 for (unsigned int i = 0; i < m_animations.size(); i++)
655 CAnimation &anim = m_animations[i];
656 if (anim.GetType() == ANIM_TYPE_CONDITIONAL)
657 anim.SetInitialCondition();
659 // and check for conditional enabling - note this overrides SetEnabled() from the code currently
660 // this may need to be reviewed at a later date
661 if (m_enableCondition)
662 m_enabled = g_infoManager.GetBoolValue(m_enableCondition);
663 m_allowHiddenFocus.Update();
669 void CGUIControl::SetVisibleCondition(const CStdString &expression, const CStdString &allowHiddenFocus)
671 if (expression == "true")
673 else if (expression == "false")
675 else // register with the infomanager for updates
676 m_visibleCondition = g_infoManager.Register(expression, GetParentID());
677 m_allowHiddenFocus.Parse(allowHiddenFocus, GetParentID());
680 void CGUIControl::SetAnimations(const vector<CAnimation> &animations)
682 m_animations = animations;
686 void CGUIControl::ResetAnimation(ANIMATION_TYPE type)
690 for (unsigned int i = 0; i < m_animations.size(); i++)
692 if (m_animations[i].GetType() == type)
693 m_animations[i].ResetAnimation();
697 void CGUIControl::ResetAnimations()
701 for (unsigned int i = 0; i < m_animations.size(); i++)
702 m_animations[i].ResetAnimation();
707 bool CGUIControl::CheckAnimation(ANIMATION_TYPE animType)
709 // rule out the animations we shouldn't perform
710 if (!IsVisible() || !HasRendered())
711 { // hidden or never rendered - don't allow exit or entry animations for this control
712 if (animType == ANIM_TYPE_WINDOW_CLOSE)
713 { // could be animating a (delayed) window open anim, so reset it
714 ResetAnimation(ANIM_TYPE_WINDOW_OPEN);
719 { // hidden - only allow hidden anims if we're animating a visible anim
720 if (animType == ANIM_TYPE_HIDDEN && !IsAnimating(ANIM_TYPE_VISIBLE))
722 // update states to force it hidden
723 UpdateStates(animType, ANIM_PROCESS_NORMAL, ANIM_STATE_APPLIED);
726 if (animType == ANIM_TYPE_WINDOW_OPEN)
732 void CGUIControl::QueueAnimation(ANIMATION_TYPE animType)
735 if (!CheckAnimation(animType))
737 CAnimation *reverseAnim = GetAnimation((ANIMATION_TYPE)-animType, false);
738 CAnimation *forwardAnim = GetAnimation(animType);
739 // we first check whether the reverse animation is in progress (and reverse it)
740 // then we check for the normal animation, and queue it
741 if (reverseAnim && reverseAnim->IsReversible() && (reverseAnim->GetState() == ANIM_STATE_IN_PROCESS || reverseAnim->GetState() == ANIM_STATE_DELAYED))
743 reverseAnim->QueueAnimation(ANIM_PROCESS_REVERSE);
744 if (forwardAnim) forwardAnim->ResetAnimation();
746 else if (forwardAnim)
748 forwardAnim->QueueAnimation(ANIM_PROCESS_NORMAL);
749 if (reverseAnim) reverseAnim->ResetAnimation();
752 { // hidden and visible animations delay the change of state. If there is no animations
753 // to perform, then we should just change the state straightaway
754 if (reverseAnim) reverseAnim->ResetAnimation();
755 UpdateStates(animType, ANIM_PROCESS_NORMAL, ANIM_STATE_APPLIED);
759 CAnimation *CGUIControl::GetAnimation(ANIMATION_TYPE type, bool checkConditions /* = true */)
761 for (unsigned int i = 0; i < m_animations.size(); i++)
763 CAnimation &anim = m_animations[i];
764 if (anim.GetType() == type)
766 if (!checkConditions || anim.CheckCondition())
773 bool CGUIControl::HasAnimation(ANIMATION_TYPE type)
775 return (NULL != GetAnimation(type, true));
778 void CGUIControl::UpdateStates(ANIMATION_TYPE type, ANIMATION_PROCESS currentProcess, ANIMATION_STATE currentState)
780 // Make sure control is hidden or visible at the appropriate times
781 // while processing a visible or hidden animation it needs to be visible,
782 // but when finished a hidden operation it needs to be hidden
783 if (type == ANIM_TYPE_VISIBLE)
785 if (currentProcess == ANIM_PROCESS_REVERSE)
787 if (currentState == ANIM_STATE_APPLIED)
790 else if (currentProcess == ANIM_PROCESS_NORMAL)
792 if (currentState == ANIM_STATE_DELAYED)
795 m_visible = m_visibleFromSkinCondition ? VISIBLE : HIDDEN;
798 else if (type == ANIM_TYPE_HIDDEN)
800 if (currentProcess == ANIM_PROCESS_NORMAL) // a hide animation
802 if (currentState == ANIM_STATE_APPLIED)
803 m_visible = HIDDEN; // finished
805 m_visible = VISIBLE; // have to be visible until we are finished
807 else if (currentProcess == ANIM_PROCESS_REVERSE) // a visible animation
808 { // no delay involved here - just make sure it's visible
809 m_visible = m_visibleFromSkinCondition ? VISIBLE : HIDDEN;
812 else if (type == ANIM_TYPE_WINDOW_OPEN)
814 if (currentProcess == ANIM_PROCESS_NORMAL)
816 if (currentState == ANIM_STATE_DELAYED)
817 m_visible = DELAYED; // delayed
819 m_visible = m_visibleFromSkinCondition ? VISIBLE : HIDDEN;
822 else if (type == ANIM_TYPE_FOCUS)
824 // call the focus function if we have finished a focus animation
825 // (buttons can "click" on focus)
826 if (currentProcess == ANIM_PROCESS_NORMAL && currentState == ANIM_STATE_APPLIED)
829 else if (type == ANIM_TYPE_UNFOCUS)
831 // call the unfocus function if we have finished a focus animation
832 // (buttons can "click" on focus)
833 if (currentProcess == ANIM_PROCESS_NORMAL && currentState == ANIM_STATE_APPLIED)
838 bool CGUIControl::Animate(unsigned int currentTime)
840 // check visible state outside the loop, as it could change
841 GUIVISIBLE visible = m_visible;
844 bool changed = false;
846 CPoint center(GetXPosition() + GetWidth() * 0.5f, GetYPosition() + GetHeight() * 0.5f);
847 for (unsigned int i = 0; i < m_animations.size(); i++)
849 CAnimation &anim = m_animations[i];
850 anim.Animate(currentTime, HasRendered() || visible == DELAYED);
851 // Update the control states (such as visibility)
852 UpdateStates(anim.GetType(), anim.GetProcess(), anim.GetState());
853 // and render the animation effect
854 changed |= (anim.GetProcess() != ANIM_PROCESS_NONE);
855 anim.RenderAnimation(m_transform, center);
858 if (anim.currentProcess != ANIM_PROCESS_NONE)
860 if (anim.effect == EFFECT_TYPE_ZOOM)
863 CLog::Log(LOGDEBUG, "Animating control %d with a %s zoom effect %s. Amount is %2.1f, visible=%s", m_controlID, anim.type == ANIM_TYPE_CONDITIONAL ? (anim.lastCondition ? "conditional_on" : "conditional_off") : (anim.type == ANIM_TYPE_VISIBLE ? "visible" : "hidden"), anim.currentProcess == ANIM_PROCESS_NORMAL ? "normal" : "reverse", anim.amount, IsVisible() ? "true" : "false");
865 else if (anim.effect == EFFECT_TYPE_FADE)
868 CLog::Log(LOGDEBUG, "Animating control %d with a %s fade effect %s. Amount is %2.1f. Visible=%s", m_controlID, anim.type == ANIM_TYPE_CONDITIONAL ? (anim.lastCondition ? "conditional_on" : "conditional_off") : (anim.type == ANIM_TYPE_VISIBLE ? "visible" : "hidden"), anim.currentProcess == ANIM_PROCESS_NORMAL ? "normal" : "reverse", anim.amount, IsVisible() ? "true" : "false");
876 bool CGUIControl::IsAnimating(ANIMATION_TYPE animType)
878 for (unsigned int i = 0; i < m_animations.size(); i++)
880 CAnimation &anim = m_animations[i];
881 if (anim.GetType() == animType)
883 if (anim.GetQueuedProcess() == ANIM_PROCESS_NORMAL)
885 if (anim.GetProcess() == ANIM_PROCESS_NORMAL)
888 else if (anim.GetType() == -animType)
890 if (anim.GetQueuedProcess() == ANIM_PROCESS_REVERSE)
892 if (anim.GetProcess() == ANIM_PROCESS_REVERSE)
899 bool CGUIControl::GetNavigationAction(int direction, CGUIAction& action) const
906 case ACTION_MOVE_DOWN:
907 action = m_actionDown;
909 case ACTION_MOVE_LEFT:
910 action = m_actionLeft;
912 case ACTION_MOVE_RIGHT:
913 action = m_actionRight;
915 case ACTION_NAV_BACK:
916 action = m_actionBack;
923 bool CGUIControl::CanFocusFromPoint(const CPoint &point) const
925 return CanFocus() && HitTest(point);
928 void CGUIControl::UnfocusFromPoint(const CPoint &point)
930 CPoint controlPoint(point);
931 m_transform.InverseTransformPosition(controlPoint.x, controlPoint.y);
932 if (!HitTest(controlPoint))
936 bool CGUIControl::HasID(int id) const
938 return GetID() == id;
941 bool CGUIControl::HasVisibleID(int id) const
943 return GetID() == id && IsVisible();
946 void CGUIControl::SaveStates(vector<CControlState> &states)
948 // empty for now - do nothing with the majority of controls
951 void CGUIControl::SetHitRect(const CRect &rect)
956 void CGUIControl::SetCamera(const CPoint &camera)
962 CPoint CGUIControl::GetRenderPosition() const
965 CPoint point(GetPosition());
966 m_transform.TransformPosition(point.x, point.y, z);
968 point += m_parentControl->GetRenderPosition();