2 * Copyright (C) 2005-2013 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() :
34 m_diffuseColor(0xffffffff)
36 m_hasProcessed = false;
41 m_visibleFromSkinCondition = true;
42 m_forceHidden = false;
43 m_visibleCondition = 0;
44 m_enableCondition = 0;
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),
62 m_diffuseColor(0xffffffff)
69 m_controlID = controlID;
70 m_parentID = parentID;
72 m_visibleFromSkinCondition = true;
73 m_forceHidden = false;
74 m_visibleCondition = 0;
75 m_enableCondition = 0;
77 ControlType = GUICONTROL_UNKNOWN;
78 m_bInvalidated = true;
80 m_hasProcessed = 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_hasProcessed = 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_hasProcessed = 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);
138 m_cachedTransform = g_graphicsContext.AddTransform(m_transform);
140 g_graphicsContext.SetCameraPosition(m_camera);
142 Process(currentTime, dirtyregions);
143 m_bInvalidated = false;
145 if (dirtyRegion != m_renderRegion)
147 dirtyRegion.Union(m_renderRegion);
152 g_graphicsContext.RestoreCameraPosition();
153 g_graphicsContext.RemoveTransform();
156 changed |= m_controlIsDirty;
158 m_controlIsDirty = false;
162 dirtyregions.push_back(dirtyRegion);
166 void CGUIControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
168 // update our render region
169 m_renderRegion = g_graphicsContext.generateAABB(CalcRenderRegion());
170 m_hasProcessed = true;
173 // the main render routine.
174 // 1. set the animation transform
175 // 2. if visible, paint
176 // 3. reset the animation transform
177 void CGUIControl::DoRender()
181 g_graphicsContext.SetTransform(m_cachedTransform);
183 g_graphicsContext.SetCameraPosition(m_camera);
185 GUIPROFILER_RENDER_BEGIN(this);
187 GUIPROFILER_RENDER_END(this);
190 g_graphicsContext.RestoreCameraPosition();
191 g_graphicsContext.RemoveTransform();
195 bool CGUIControl::OnAction(const CAction &action)
199 switch (action.GetID())
201 case ACTION_MOVE_DOWN:
209 case ACTION_MOVE_LEFT:
213 case ACTION_MOVE_RIGHT:
217 case ACTION_NAV_BACK:
220 case ACTION_NEXT_CONTROL:
224 case ACTION_PREV_CONTROL:
232 bool CGUIControl::Navigate(int direction) const
236 CGUIMessage msg(GUI_MSG_MOVE, GetParentID(), GetID(), direction);
237 return SendWindowMessage(msg);
242 // Movement controls (derived classes can override)
243 void CGUIControl::OnUp()
245 Navigate(ACTION_MOVE_UP);
248 void CGUIControl::OnDown()
250 Navigate(ACTION_MOVE_DOWN);
253 void CGUIControl::OnLeft()
255 Navigate(ACTION_MOVE_LEFT);
258 void CGUIControl::OnRight()
260 Navigate(ACTION_MOVE_RIGHT);
263 bool CGUIControl::OnBack()
265 return Navigate(ACTION_NAV_BACK);
268 void CGUIControl::OnNextControl()
270 Navigate(ACTION_NEXT_CONTROL);
273 void CGUIControl::OnPrevControl()
275 Navigate(ACTION_PREV_CONTROL);
278 bool CGUIControl::SendWindowMessage(CGUIMessage &message) const
280 CGUIWindow *pWindow = g_windowManager.GetWindow(GetParentID());
282 return pWindow->OnMessage(message);
283 return g_windowManager.SendMessage(message);
286 int CGUIControl::GetID(void) const
292 int CGUIControl::GetParentID(void) const
297 bool CGUIControl::HasFocus(void) const
302 void CGUIControl::SetFocus(bool focus)
304 if (m_bHasFocus && !focus)
305 QueueAnimation(ANIM_TYPE_UNFOCUS);
306 else if (!m_bHasFocus && focus)
307 QueueAnimation(ANIM_TYPE_FOCUS);
311 bool CGUIControl::OnMessage(CGUIMessage& message)
313 if ( message.GetControlId() == GetID() )
315 switch (message.GetMessage() )
317 case GUI_MSG_SETFOCUS:
318 // if control is disabled then move 2 the next control
321 CLog::Log(LOGERROR, "Control %u in window %u has been asked to focus, "
323 GetID(), GetParentID());
328 // inform our parent window that this has happened
329 CGUIMessage message(GUI_MSG_FOCUSED, GetParentID(), GetID());
331 m_parentControl->OnMessage(message);
336 case GUI_MSG_LOSTFOCUS:
339 // and tell our parent so it can unfocus
341 m_parentControl->OnMessage(message);
346 case GUI_MSG_VISIBLE:
347 SetVisible(true, true);
355 // Note that the skin <enable> tag will override these messages
356 case GUI_MSG_ENABLED:
360 case GUI_MSG_DISABLED:
364 case GUI_MSG_WINDOW_RESIZE:
365 // invalidate controls to get them to recalculate sizing information
373 bool CGUIControl::CanFocus() const
375 if (!IsVisible() && !m_allowHiddenFocus) return false;
376 if (IsDisabled()) return false;
380 bool CGUIControl::IsVisible() const
382 if (m_forceHidden) return false;
383 return m_visible == VISIBLE;
386 bool CGUIControl::IsDisabled() const
391 void CGUIControl::SetEnabled(bool bEnable)
393 if (bEnable != m_enabled)
400 void CGUIControl::SetEnableCondition(const CStdString &expression)
402 if (expression == "true")
404 else if (expression == "false")
407 m_enableCondition = g_infoManager.Register(expression, GetParentID());
410 void CGUIControl::SetPosition(float posX, float posY)
412 if ((m_posX != posX) || (m_posY != posY))
416 m_hitRect += CPoint(posX - m_posX, posY - m_posY);
424 bool CGUIControl::SetColorDiffuse(const CGUIInfoColor &color)
426 bool changed = m_diffuseColor != color;
427 m_diffuseColor = color;
431 float CGUIControl::GetXPosition() const
436 float CGUIControl::GetYPosition() const
441 float CGUIControl::GetWidth() const
446 float CGUIControl::GetHeight() const
451 void CGUIControl::MarkDirtyRegion()
453 m_controlIsDirty = true;
456 CRect CGUIControl::CalcRenderRegion() const
458 CPoint tl(GetXPosition(), GetYPosition());
459 CPoint br(tl.x + GetWidth(), tl.y + GetHeight());
461 return CRect(tl.x, tl.y, br.x, br.y);
464 void CGUIControl::SetNavigation(int up, int down, int left, int right, int back)
466 m_actionUp.SetNavigation(up);
467 m_actionDown.SetNavigation(down);
468 m_actionLeft.SetNavigation(left);
469 m_actionRight.SetNavigation(right);
470 m_actionBack.SetNavigation(back);
473 void CGUIControl::SetTabNavigation(int next, int prev)
475 m_actionNext.SetNavigation(next);
476 m_actionPrev.SetNavigation(prev);
479 void CGUIControl::SetNavigationActions(const CGUIAction &up, const CGUIAction &down,
480 const CGUIAction &left, const CGUIAction &right,
481 const CGUIAction &back, bool replace)
483 if (!m_actionLeft.HasAnyActions() || replace) m_actionLeft = left;
484 if (!m_actionRight.HasAnyActions() || replace) m_actionRight = right;
485 if (!m_actionUp.HasAnyActions() || replace) m_actionUp = up;
486 if (!m_actionDown.HasAnyActions() || replace) m_actionDown = down;
487 if (!m_actionBack.HasAnyActions() || replace) m_actionBack = back;
490 void CGUIControl::SetNavigationAction(int direction, const CGUIAction &action, bool replace /*= true*/)
495 if (!m_actionUp.HasAnyActions() || replace)
498 case ACTION_MOVE_DOWN:
499 if (!m_actionDown.HasAnyActions() || replace)
500 m_actionDown = action;
502 case ACTION_MOVE_LEFT:
503 if (!m_actionLeft.HasAnyActions() || replace)
504 m_actionLeft = action;
506 case ACTION_MOVE_RIGHT:
507 if (!m_actionRight.HasAnyActions() || replace)
508 m_actionRight = action;
510 case ACTION_NAV_BACK:
511 if (!m_actionBack.HasAnyActions() || replace)
512 m_actionBack = action;
517 void CGUIControl::SetWidth(float width)
519 if (m_width != width)
523 m_hitRect.x2 = m_hitRect.x1 + width;
528 void CGUIControl::SetHeight(float height)
530 if (m_height != height)
534 m_hitRect.y2 = m_hitRect.y1 + height;
539 void CGUIControl::SetVisible(bool bVisible, bool setVisState)
541 if (bVisible && setVisState)
542 { // TODO: currently we only update m_visible from GUI_MSG_VISIBLE (SET_CONTROL_VISIBLE)
543 // otherwise we just set m_forceHidden
544 GUIVISIBLE visible = m_visible;
545 if (m_visibleCondition)
546 visible = g_infoManager.GetBoolValue(m_visibleCondition) ? VISIBLE : HIDDEN;
549 if (visible != m_visible)
555 if (m_forceHidden == bVisible)
557 m_forceHidden = !bVisible;
561 { // reset any visible animations that are in process
562 if (IsAnimating(ANIM_TYPE_VISIBLE))
564 // CLog::Log(LOGDEBUG, "Resetting visible animation on control %i (we are %s)", m_controlID, m_visible ? "visible" : "hidden");
565 CAnimation *visibleAnim = GetAnimation(ANIM_TYPE_VISIBLE);
566 if (visibleAnim) visibleAnim->ResetAnimation();
571 bool CGUIControl::HitTest(const CPoint &point) const
573 return m_hitRect.PtInRect(point);
576 EVENT_RESULT CGUIControl::SendMouseEvent(const CPoint &point, const CMouseEvent &event)
578 CPoint childPoint(point);
579 m_transform.InverseTransformPosition(childPoint.x, childPoint.y);
580 if (!CanFocusFromPoint(childPoint))
581 return EVENT_RESULT_UNHANDLED;
583 bool handled = OnMouseOver(childPoint);
584 EVENT_RESULT ret = OnMouseEvent(childPoint, event);
587 return (handled && (event.m_id == ACTION_MOUSE_MOVE)) ? EVENT_RESULT_HANDLED : EVENT_RESULT_UNHANDLED;
590 // override this function to implement custom mouse behaviour
591 bool CGUIControl::OnMouseOver(const CPoint &point)
593 if (g_Mouse.GetState() != MOUSE_STATE_DRAG)
594 g_Mouse.SetState(MOUSE_STATE_FOCUS);
595 if (!CanFocus()) return false;
598 CGUIMessage msg(GUI_MSG_SETFOCUS, GetParentID(), GetID());
604 void CGUIControl::UpdateVisibility(const CGUIListItem *item)
606 if (m_visibleCondition)
608 bool bWasVisible = m_visibleFromSkinCondition;
609 m_visibleFromSkinCondition = g_infoManager.GetBoolValue(m_visibleCondition, item);
610 if (!bWasVisible && m_visibleFromSkinCondition)
611 { // automatic change of visibility - queue the in effect
612 // CLog::Log(LOGDEBUG, "Visibility changed to visible for control id %i", m_controlID);
613 QueueAnimation(ANIM_TYPE_VISIBLE);
615 else if (bWasVisible && !m_visibleFromSkinCondition)
616 { // automatic change of visibility - do the out effect
617 // CLog::Log(LOGDEBUG, "Visibility changed to hidden for control id %i", m_controlID);
618 QueueAnimation(ANIM_TYPE_HIDDEN);
621 // check for conditional animations
622 for (unsigned int i = 0; i < m_animations.size(); i++)
624 CAnimation &anim = m_animations[i];
625 if (anim.GetType() == ANIM_TYPE_CONDITIONAL)
626 anim.UpdateCondition(item);
628 // and check for conditional enabling - note this overrides SetEnabled() from the code currently
629 // this may need to be reviewed at a later date
630 bool enabled = m_enabled;
631 if (m_enableCondition)
632 m_enabled = g_infoManager.GetBoolValue(m_enableCondition, item);
634 if (m_enabled != enabled)
637 m_allowHiddenFocus.Update(item);
640 // and finally, update our control information (if not pushed)
641 if (!m_pushedUpdates)
645 bool CGUIControl::UpdateColors()
647 return m_diffuseColor.Update();
650 void CGUIControl::SetInitialVisibility()
652 if (m_visibleCondition)
654 m_visibleFromSkinCondition = g_infoManager.GetBoolValue(m_visibleCondition);
655 m_visible = m_visibleFromSkinCondition ? VISIBLE : HIDDEN;
656 // CLog::Log(LOGDEBUG, "Set initial visibility for control %i: %s", m_controlID, m_visible == VISIBLE ? "visible" : "hidden");
658 else if (m_visible == DELAYED)
660 // and handle animation conditions as well
661 for (unsigned int i = 0; i < m_animations.size(); i++)
663 CAnimation &anim = m_animations[i];
664 if (anim.GetType() == ANIM_TYPE_CONDITIONAL)
665 anim.SetInitialCondition();
667 // and check for conditional enabling - note this overrides SetEnabled() from the code currently
668 // this may need to be reviewed at a later date
669 if (m_enableCondition)
670 m_enabled = g_infoManager.GetBoolValue(m_enableCondition);
671 m_allowHiddenFocus.Update();
677 void CGUIControl::SetVisibleCondition(const CStdString &expression, const CStdString &allowHiddenFocus)
679 if (expression == "true")
681 else if (expression == "false")
683 else // register with the infomanager for updates
684 m_visibleCondition = g_infoManager.Register(expression, GetParentID());
685 m_allowHiddenFocus.Parse(allowHiddenFocus, GetParentID());
688 void CGUIControl::SetAnimations(const vector<CAnimation> &animations)
690 m_animations = animations;
694 void CGUIControl::ResetAnimation(ANIMATION_TYPE type)
698 for (unsigned int i = 0; i < m_animations.size(); i++)
700 if (m_animations[i].GetType() == type)
701 m_animations[i].ResetAnimation();
705 void CGUIControl::ResetAnimations()
709 for (unsigned int i = 0; i < m_animations.size(); i++)
710 m_animations[i].ResetAnimation();
715 bool CGUIControl::CheckAnimation(ANIMATION_TYPE animType)
717 // rule out the animations we shouldn't perform
718 if (!IsVisible() || !HasProcessed())
719 { // hidden or never processed - don't allow exit or entry animations for this control
720 if (animType == ANIM_TYPE_WINDOW_CLOSE)
721 { // could be animating a (delayed) window open anim, so reset it
722 ResetAnimation(ANIM_TYPE_WINDOW_OPEN);
727 { // hidden - only allow hidden anims if we're animating a visible anim
728 if (animType == ANIM_TYPE_HIDDEN && !IsAnimating(ANIM_TYPE_VISIBLE))
730 // update states to force it hidden
731 UpdateStates(animType, ANIM_PROCESS_NORMAL, ANIM_STATE_APPLIED);
734 if (animType == ANIM_TYPE_WINDOW_OPEN)
740 void CGUIControl::QueueAnimation(ANIMATION_TYPE animType)
743 if (!CheckAnimation(animType))
745 CAnimation *reverseAnim = GetAnimation((ANIMATION_TYPE)-animType, false);
746 CAnimation *forwardAnim = GetAnimation(animType);
747 // we first check whether the reverse animation is in progress (and reverse it)
748 // then we check for the normal animation, and queue it
749 if (reverseAnim && reverseAnim->IsReversible() && (reverseAnim->GetState() == ANIM_STATE_IN_PROCESS || reverseAnim->GetState() == ANIM_STATE_DELAYED))
751 reverseAnim->QueueAnimation(ANIM_PROCESS_REVERSE);
752 if (forwardAnim) forwardAnim->ResetAnimation();
754 else if (forwardAnim)
756 forwardAnim->QueueAnimation(ANIM_PROCESS_NORMAL);
757 if (reverseAnim) reverseAnim->ResetAnimation();
760 { // hidden and visible animations delay the change of state. If there is no animations
761 // to perform, then we should just change the state straightaway
762 if (reverseAnim) reverseAnim->ResetAnimation();
763 UpdateStates(animType, ANIM_PROCESS_NORMAL, ANIM_STATE_APPLIED);
767 CAnimation *CGUIControl::GetAnimation(ANIMATION_TYPE type, bool checkConditions /* = true */)
769 for (unsigned int i = 0; i < m_animations.size(); i++)
771 CAnimation &anim = m_animations[i];
772 if (anim.GetType() == type)
774 if (!checkConditions || anim.CheckCondition())
781 bool CGUIControl::HasAnimation(ANIMATION_TYPE type)
783 return (NULL != GetAnimation(type, true));
786 void CGUIControl::UpdateStates(ANIMATION_TYPE type, ANIMATION_PROCESS currentProcess, ANIMATION_STATE currentState)
788 // Make sure control is hidden or visible at the appropriate times
789 // while processing a visible or hidden animation it needs to be visible,
790 // but when finished a hidden operation it needs to be hidden
791 if (type == ANIM_TYPE_VISIBLE)
793 if (currentProcess == ANIM_PROCESS_REVERSE)
795 if (currentState == ANIM_STATE_APPLIED)
798 else if (currentProcess == ANIM_PROCESS_NORMAL)
800 if (currentState == ANIM_STATE_DELAYED)
803 m_visible = m_visibleFromSkinCondition ? VISIBLE : HIDDEN;
806 else if (type == ANIM_TYPE_HIDDEN)
808 if (currentProcess == ANIM_PROCESS_NORMAL) // a hide animation
810 if (currentState == ANIM_STATE_APPLIED)
811 m_visible = HIDDEN; // finished
813 m_visible = VISIBLE; // have to be visible until we are finished
815 else if (currentProcess == ANIM_PROCESS_REVERSE) // a visible animation
816 { // no delay involved here - just make sure it's visible
817 m_visible = m_visibleFromSkinCondition ? VISIBLE : HIDDEN;
820 else if (type == ANIM_TYPE_WINDOW_OPEN)
822 if (currentProcess == ANIM_PROCESS_NORMAL)
824 if (currentState == ANIM_STATE_DELAYED)
825 m_visible = DELAYED; // delayed
827 m_visible = m_visibleFromSkinCondition ? VISIBLE : HIDDEN;
830 else if (type == ANIM_TYPE_FOCUS)
832 // call the focus function if we have finished a focus animation
833 // (buttons can "click" on focus)
834 if (currentProcess == ANIM_PROCESS_NORMAL && currentState == ANIM_STATE_APPLIED)
837 else if (type == ANIM_TYPE_UNFOCUS)
839 // call the unfocus function if we have finished a focus animation
840 // (buttons can "click" on focus)
841 if (currentProcess == ANIM_PROCESS_NORMAL && currentState == ANIM_STATE_APPLIED)
846 bool CGUIControl::Animate(unsigned int currentTime)
848 // check visible state outside the loop, as it could change
849 GUIVISIBLE visible = m_visible;
852 bool changed = false;
854 CPoint center(GetXPosition() + GetWidth() * 0.5f, GetYPosition() + GetHeight() * 0.5f);
855 for (unsigned int i = 0; i < m_animations.size(); i++)
857 CAnimation &anim = m_animations[i];
858 anim.Animate(currentTime, HasProcessed() || visible == DELAYED);
859 // Update the control states (such as visibility)
860 UpdateStates(anim.GetType(), anim.GetProcess(), anim.GetState());
861 // and render the animation effect
862 changed |= (anim.GetProcess() != ANIM_PROCESS_NONE);
863 anim.RenderAnimation(m_transform, center);
866 if (anim.currentProcess != ANIM_PROCESS_NONE)
868 if (anim.effect == EFFECT_TYPE_ZOOM)
871 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");
873 else if (anim.effect == EFFECT_TYPE_FADE)
876 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");
884 bool CGUIControl::IsAnimating(ANIMATION_TYPE animType)
886 for (unsigned int i = 0; i < m_animations.size(); i++)
888 CAnimation &anim = m_animations[i];
889 if (anim.GetType() == animType)
891 if (anim.GetQueuedProcess() == ANIM_PROCESS_NORMAL)
893 if (anim.GetProcess() == ANIM_PROCESS_NORMAL)
896 else if (anim.GetType() == -animType)
898 if (anim.GetQueuedProcess() == ANIM_PROCESS_REVERSE)
900 if (anim.GetProcess() == ANIM_PROCESS_REVERSE)
907 bool CGUIControl::GetNavigationAction(int direction, CGUIAction& action) const
914 case ACTION_MOVE_DOWN:
915 action = m_actionDown;
917 case ACTION_MOVE_LEFT:
918 action = m_actionLeft;
920 case ACTION_MOVE_RIGHT:
921 action = m_actionRight;
923 case ACTION_NAV_BACK:
924 action = m_actionBack;
931 bool CGUIControl::CanFocusFromPoint(const CPoint &point) const
933 return CanFocus() && HitTest(point);
936 void CGUIControl::UnfocusFromPoint(const CPoint &point)
940 CPoint controlPoint(point);
941 m_transform.InverseTransformPosition(controlPoint.x, controlPoint.y);
942 if (!HitTest(controlPoint))
947 bool CGUIControl::HasID(int id) const
949 return GetID() == id;
952 bool CGUIControl::HasVisibleID(int id) const
954 return GetID() == id && IsVisible();
957 void CGUIControl::SaveStates(vector<CControlState> &states)
959 // empty for now - do nothing with the majority of controls
962 void CGUIControl::SetHitRect(const CRect &rect)
967 void CGUIControl::SetCamera(const CPoint &camera)
973 CPoint CGUIControl::GetRenderPosition() const
976 CPoint point(GetPosition());
977 m_transform.TransformPosition(point.x, point.y, z);
979 point += m_parentControl->GetRenderPosition();