fixed: severe global namespace pollution
[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 #include "../xbmc/utils/GUIInfoManager.h"
7
8 using namespace DIRECTORY;
9
10 CGUIMultiImage::CGUIMultiImage(DWORD dwParentID, DWORD dwControlId, float posX, float posY, float width, float height, const CStdString& strTexturePath, DWORD timePerImage, DWORD fadeTime, bool randomized, bool loop)
11     : CGUIControl(dwParentID, dwControlId, posX, posY, width, height)
12 {
13   m_currentPath = m_texturePath = strTexturePath;
14   m_currentImage = 0;
15   m_timePerImage = timePerImage;
16   m_fadeTime = fadeTime;
17   m_randomized = randomized;
18   m_loop = loop;
19   m_aspectRatio = CGUIImage::ASPECT_RATIO_STRETCH;
20   ControlType = GUICONTROL_MULTI_IMAGE;
21   m_bDynamicResourceAlloc=false;
22   m_Info = 0;
23   m_directoryLoaded = false;
24 }
25
26 CGUIMultiImage::~CGUIMultiImage(void)
27 {
28 }
29
30 void CGUIMultiImage::Render()
31 {
32   if (!IsVisible())
33   {
34     if (m_bDynamicResourceAlloc && IsAllocated())
35       FreeResources();
36     return;
37   }
38
39   // check for conditional information before we
40   // alloc as this can free our resources
41   if (m_Info)
42   {
43     CStdString texturePath = g_infoManager.GetImage(m_Info, WINDOW_INVALID);
44     if (texturePath != m_currentPath && !texturePath.IsEmpty())
45     {
46       m_currentPath = texturePath;
47       FreeResources();
48       LoadDirectory();
49     }
50     else if (texturePath.IsEmpty() && m_currentPath != m_texturePath)
51     {
52       m_currentPath = m_texturePath;
53       FreeResources();
54       LoadDirectory();
55     }
56   }
57
58   if (m_bDynamicResourceAlloc && !IsAllocated())
59     AllocResources();
60   else if (!m_bDynamicResourceAlloc && !IsAllocated())
61     AllocResources();  // not dynamic, make sure we allocate!
62
63   if (!m_images.empty())
64   {
65     // Set a viewport so that we don't render outside the defined area
66     g_graphicsContext.SetViewPort(m_posX, m_posY, m_width, m_height);
67     m_images[m_currentImage]->Render();
68
69     unsigned int nextImage = m_currentImage + 1;
70     if (nextImage >= m_images.size())
71       nextImage = m_loop ? 0 : m_currentImage;  // stay on the last image if <loop>no</loop>
72
73     if (nextImage != m_currentImage)
74     {
75       // check if we should be loading a new image yet
76       if (m_imageTimer.IsRunning() && m_imageTimer.GetElapsedMilliseconds() > m_timePerImage)
77       {
78         m_imageTimer.Stop();
79         // grab a new image
80         LoadImage(nextImage);
81         // start the fade timer
82         m_fadeTimer.StartZero();
83       }
84
85       // check if we are still fading
86       if (m_fadeTimer.IsRunning())
87       {
88         // check if the fade timer has run out
89         float timeFading = m_fadeTimer.GetElapsedMilliseconds();
90         if (timeFading > m_fadeTime)
91         {
92           m_fadeTimer.Stop();
93           // swap images
94           m_images[m_currentImage]->FreeResources();
95           m_images[nextImage]->SetAlpha(255);
96           m_currentImage = nextImage;
97           // start the load timer
98           m_imageTimer.StartZero();
99         }
100         else
101         { // perform the fade
102           float fadeAmount = timeFading / m_fadeTime;
103           m_images[nextImage]->SetAlpha((unsigned char)(255 * fadeAmount));
104         }
105         m_images[nextImage]->Render();
106       }
107     }
108     g_graphicsContext.RestoreViewPort();
109   }
110   CGUIControl::Render();
111 }
112
113 bool CGUIMultiImage::OnAction(const CAction &action)
114 {
115   return false;
116 }
117
118 bool CGUIMultiImage::OnMessage(CGUIMessage &message)
119 {
120   if (message.GetMessage() == GUI_MSG_REFRESH_THUMBS)
121   {
122     if (m_Info)
123       FreeResources();
124     return true;
125   }
126   return CGUIControl::OnMessage(message);
127 }
128
129 void CGUIMultiImage::PreAllocResources()
130 {
131   FreeResources();
132 }
133
134 void CGUIMultiImage::AllocResources()
135 {
136   FreeResources();
137   CGUIControl::AllocResources();
138
139   if (!m_directoryLoaded)
140     LoadDirectory();
141
142   // Randomize or sort our images if necessary
143   if (m_randomized)
144     random_shuffle(m_files.begin(), m_files.end());
145
146   for (unsigned int i=0; i < m_files.size(); i++)
147   {
148     CGUIImage *pImage = new CGUIImage(GetParentID(), GetID(), m_posX, m_posY, m_width, m_height, m_files[i]);
149     if (pImage)
150       m_images.push_back(pImage);
151   }
152   // Load in the current image, and reset our timer
153   m_imageTimer.StartZero();
154   m_fadeTimer.Stop();
155   m_currentImage = 0;
156   if (m_images.empty())
157     return;
158
159   LoadImage(m_currentImage);
160 }
161
162 void CGUIMultiImage::LoadImage(int image)
163 {
164   if (image < 0 || image >= (int)m_images.size())
165     return;
166
167   m_images[image]->AllocResources();
168   m_images[image]->SetColorDiffuse(m_diffuseColor);
169
170   // Scale image so that it will fill our render area
171   if (m_aspectRatio != CGUIImage::ASPECT_RATIO_STRETCH)
172   {
173     // image is scaled so that the aspect ratio is maintained (taking into account the TV pixel ratio)
174     // and so that it fills the allocated space (so is zoomed then cropped)
175     float sourceAspectRatio = (float)m_images[image]->GetTextureWidth() / m_images[image]->GetTextureHeight();
176     float aspectRatio = sourceAspectRatio / g_graphicsContext.GetPixelRatio(g_graphicsContext.GetVideoResolution());
177
178     float newWidth = m_width;
179     float newHeight = newWidth / aspectRatio;
180     if ((m_aspectRatio == CGUIImage::ASPECT_RATIO_SCALE && newHeight < m_height) ||
181         (m_aspectRatio == CGUIImage::ASPECT_RATIO_KEEP && newHeight > m_height))
182     {
183       newHeight = m_height;
184       newWidth = newHeight * aspectRatio;
185     }
186     m_images[image]->SetPosition(m_posX - (newWidth - m_width)*0.5f, m_posY - (newHeight - m_height)*0.5f);
187     m_images[image]->SetWidth(newWidth);
188     m_images[image]->SetHeight(newHeight);
189   }
190 }
191
192 void CGUIMultiImage::FreeResources()
193 {
194   for (unsigned int i = 0; i < m_images.size(); ++i)
195   {
196     m_images[i]->FreeResources();
197     delete m_images[i];
198   }
199
200   m_images.clear();
201   m_currentImage = 0;
202   CGUIControl::FreeResources();
203 }
204
205 void CGUIMultiImage::DynamicResourceAlloc(bool bOnOff)
206 {
207   CGUIControl::DynamicResourceAlloc(bOnOff);
208   m_bDynamicResourceAlloc=bOnOff;
209 }
210
211 bool CGUIMultiImage::CanFocus() const
212 {
213   return false;
214 }
215
216 void CGUIMultiImage::SetAspectRatio(CGUIImage::GUIIMAGE_ASPECT_RATIO ratio)
217 {
218   if (m_aspectRatio != ratio)
219   {
220     m_aspectRatio = ratio;
221     m_bInvalidated = true;
222   }
223 }
224
225 void CGUIMultiImage::LoadDirectory()
226 {
227   // Load any images from our texture bundle first
228   m_files.clear();
229
230   // don't load any images if our path is empty
231   if (m_currentPath.IsEmpty()) return;
232
233   // check to see if we have a single image or a folder of images
234   CFileItem item(m_currentPath, true);
235   if (item.IsPicture())
236   {
237     m_files.push_back(g_TextureManager.GetTexturePath(m_currentPath));
238   }
239   else
240   { // folder of images
241     g_TextureManager.GetBundledTexturesFromPath(m_currentPath, m_files);
242
243     // Load in our images from the directory specified
244     // m_currentPath is relative (as are all skin paths)
245     CStdString realPath = g_TextureManager.GetTexturePath(m_currentPath);
246     CHDDirectory dir;
247     CFileItemList items;
248     dir.GetDirectory(realPath, items);
249     for (int i=0; i < items.Size(); i++)
250     {
251       CFileItem *pItem = items[i];
252       if (pItem->IsPicture())
253         m_files.push_back(pItem->m_strPath);
254     }
255   }
256
257   // sort our images - they'll be randomized in AllocResources() if necessary
258   sort(m_files.begin(), m_files.end());
259
260   // flag as loaded - no point in constantly reloading them
261   m_directoryLoaded = true;
262 }