- 25-11-2005 added: <loop> tag to MultiImage control.
[xbmc:xbmc-antiquated.git] / XBMC / guilib / GUIMultiImage.cpp
1 #include "include.h"
2 #include "../xbmc/FileItem.h"
3 #include "GUIMultiImage.h"
4 #include "TextureManager.h"
5 #include "../xbmc/FileSystem/HDDirectory.h"
6
7 CGUIMultiImage::CGUIMultiImage(DWORD dwParentID, DWORD dwControlId, int iPosX, int iPosY, DWORD dwWidth, DWORD dwHeight, const CStdString& strTexturePath, DWORD timePerImage, DWORD fadeTime, bool randomized, bool loop)
8     : CGUIControl(dwParentID, dwControlId, iPosX, iPosY, dwWidth, dwHeight)
9 {
10   m_texturePath = strTexturePath;
11   m_currentImage = 0;
12   m_timePerImage = timePerImage;
13   m_fadeTime = fadeTime;
14   m_randomized = randomized;
15   m_loop = loop;
16   m_keepAspectRatio = false;
17   ControlType = GUICONTROL_MULTI_IMAGE;
18   m_bDynamicResourceAlloc=false;
19 }
20
21 CGUIMultiImage::~CGUIMultiImage(void)
22 {
23 }
24
25 void CGUIMultiImage::Render()
26 {
27   // check for conditional visibility
28   bool bVisible = UpdateEffectState();
29
30   if (m_bDynamicResourceAlloc && !bVisible && IsAllocated())
31     FreeResources();
32
33   if (!bVisible)
34     return;
35
36   if (m_bDynamicResourceAlloc && bVisible && !IsAllocated())
37     AllocResources();
38   else if (!m_bDynamicResourceAlloc && !IsAllocated())
39     AllocResources();  // not dynamic, make sure we allocate!
40
41   if (m_images.empty())
42     return ;
43
44   // Set a viewport so that we don't render outside the defined area
45   g_graphicsContext.SetViewPort((float)m_iPosX, (float)m_iPosY, (float)m_dwWidth, (float)m_dwHeight);
46   m_images[m_currentImage]->Render();
47
48   unsigned int nextImage = m_currentImage + 1;
49   if (nextImage >= m_images.size())
50     nextImage = m_loop ? 0 : m_currentImage;  // stay on the last image if <loop>no</loop>
51
52   if (nextImage == m_currentImage)
53   { // no need for complicated stuff if we aren't loading a new image!
54     g_graphicsContext.RestoreViewPort();
55     return;
56   }
57
58   // check if we should be loading a new image yet
59   if (m_imageTimer.IsRunning() && m_imageTimer.GetElapsedMilliseconds() > m_timePerImage)
60   {
61     m_imageTimer.Stop();
62     // grab a new image
63     LoadImage(nextImage);
64     // start the fade timer
65     m_fadeTimer.StartZero();
66   }
67
68   // check if we are still fading
69   if (m_fadeTimer.IsRunning())
70   {
71     // check if the fade timer has run out
72     float timeFading = m_fadeTimer.GetElapsedMilliseconds();
73     if (timeFading > m_fadeTime)
74     {
75       m_fadeTimer.Stop();
76       // swap images
77       m_images[m_currentImage]->FreeResources();
78       m_images[nextImage]->SetAlpha(255);
79       m_currentImage = nextImage;
80       // start the load timer
81       m_imageTimer.StartZero();
82     }
83     else
84     { // perform the fade
85       float fadeAmount = timeFading / m_fadeTime;
86       m_images[nextImage]->SetAlpha((DWORD)(255 * fadeAmount));
87     }
88     m_images[nextImage]->Render();
89   }
90
91   g_graphicsContext.RestoreViewPort();
92
93   CGUIControl::Render();
94 }
95
96 bool CGUIMultiImage::OnAction(const CAction &action)
97 {
98   return false;
99 }
100
101 void CGUIMultiImage::PreAllocResources()
102 {
103   FreeResources();
104 }
105
106 void CGUIMultiImage::AllocResources()
107 {
108   FreeResources();
109   CGUIControl::AllocResources();
110
111   // Load any images from our texture bundle first
112   CStdStringArray images;
113   g_TextureManager.GetBundledTexturesFromPath(m_texturePath, images);
114
115   // Load in our images from the directory specified
116   // m_texturePath is relative (as are all skin paths)
117   CStdString realPath = g_TextureManager.GetTexturePath(m_texturePath);
118   CHDDirectory dir;
119   CFileItemList items;
120   dir.GetDirectory(realPath, items);
121   for (int i=0; i < items.Size(); i++)
122   {
123     CFileItem *pItem = items[i];
124     if (pItem->IsPicture())
125       images.push_back(pItem->m_strPath);
126   }
127
128   // and sort them
129   if (m_randomized)
130     random_shuffle(images.begin(), images.end());
131   else
132     sort(images.begin(), images.end());
133
134   for (unsigned int i=0; i < images.size(); i++)
135   {
136     CGUIImage *pImage = new CGUIImage(GetParentID(), GetID(), m_iPosX, m_iPosY, m_dwWidth, m_dwHeight, images[i]);
137     if (pImage)
138       m_images.push_back(pImage);
139   }
140   // Load in the current image, and reset our timer
141   m_imageTimer.StartZero();
142   m_fadeTimer.Stop();
143   m_currentImage = 0;
144   if (m_images.empty())
145     return;
146
147   LoadImage(m_currentImage);
148 }
149
150 void CGUIMultiImage::LoadImage(int image)
151 {
152   if (image < 0 || image >= (int)m_images.size())
153     return;
154
155   m_images[image]->AllocResources();
156
157   // Scale image so that it will fill our render area
158   if (m_keepAspectRatio)
159   {
160     // image is scaled so that the aspect ratio is maintained (taking into account the TV pixel ratio)
161     // and so that it fills the allocated space (so is zoomed then cropped)
162     float sourceAspectRatio = (float)m_images[image]->GetTextureWidth() / m_images[image]->GetTextureHeight();
163     float aspectRatio = sourceAspectRatio / g_graphicsContext.GetPixelRatio(g_graphicsContext.GetVideoResolution());
164
165     unsigned int newWidth = m_dwWidth;
166     unsigned int newHeight = (unsigned int)((float)newWidth / aspectRatio);
167     if (newHeight < m_dwHeight)
168     {
169       newHeight = m_dwHeight;
170       newWidth = (unsigned int)((float)newHeight * aspectRatio);
171     }
172     m_images[image]->SetPosition(m_iPosX - (int)(newWidth - m_dwWidth)/2, m_iPosY - (int)(newHeight - m_dwHeight)/2);
173     m_images[image]->SetWidth(newWidth);
174     m_images[image]->SetHeight(newHeight);
175   }
176 }
177
178 void CGUIMultiImage::FreeResources()
179 {
180   for (unsigned int i = 0; i < m_images.size(); ++i)
181   {
182     m_images[i]->FreeResources();
183     delete m_images[i];
184   }
185
186   m_images.clear();
187   m_currentImage = 0;
188   CGUIControl::FreeResources();
189 }
190
191 void CGUIMultiImage::DynamicResourceAlloc(bool bOnOff)
192 {
193   CGUIControl::DynamicResourceAlloc(bOnOff);
194   m_bDynamicResourceAlloc=bOnOff;
195 }
196
197 bool CGUIMultiImage::CanFocus() const
198 {
199   return false;
200 }
201
202 void CGUIMultiImage::SetKeepAspectRatio(bool bOnOff)
203 {
204   if (m_keepAspectRatio != bOnOff)
205   {
206     m_keepAspectRatio = bOnOff;
207     m_bInvalidated = true;
208   }
209 }
210
211 bool CGUIMultiImage::GetKeepAspectRatio() const
212 {
213   return m_keepAspectRatio;
214 }
215