]> git.lizzy.rs Git - minetest.git/blob - src/gui/guiAnimatedImage.cpp
Fix potential problem with core.get_connected_players()
[minetest.git] / src / gui / guiAnimatedImage.cpp
1 #include "guiAnimatedImage.h"
2
3 #include "client/guiscalingfilter.h"
4 #include "client/tile.h" // ITextureSource
5 #include "log.h"
6 #include "porting.h"
7 #include <string>
8
9 GUIAnimatedImage::GUIAnimatedImage(gui::IGUIEnvironment *env, gui::IGUIElement *parent,
10                 s32 id, const core::rect<s32> &rectangle, const std::string &name,
11                 ISimpleTextureSource *tsrc) :
12                 gui::IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, rectangle),
13                 m_name(name), m_tsrc(tsrc), m_texture(nullptr), m_global_time(0),
14                 m_frame_idx(0), m_frame_count(1), m_frame_duration(1), m_frame_time(0)
15 {
16         // Expected format: "texture_name:frame_count,frame_duration"
17         // If this format is not met, the string will be loaded as a normal texture
18
19         std::string::size_type colon_position = name.find(':', 0);
20         std::string::size_type comma_position = name.find(',', 0);
21
22         if (comma_position != std::string::npos &&
23                         colon_position != std::string::npos &&
24                         comma_position < name.size()) {
25                 m_texture = m_tsrc->getTexture(name.substr(0, colon_position));
26
27                 m_frame_count = std::max(stoi(name.substr(
28                                         colon_position + 1, comma_position - colon_position - 1)), 1);
29
30                 m_frame_duration = std::max(stoi(name.substr(comma_position + 1)), 1);
31         } else {
32                 // Leave the count/duration and display a static image
33                 m_texture = m_tsrc->getTexture(name);
34                 errorstream << "animated_image[]: Invalid texture format " << name <<
35                         ". Expected format: texture_name:frame_count,frame_duration" << std::endl;
36         }
37
38         if (m_texture != nullptr) {
39                 core::dimension2d<u32> size = m_texture->getOriginalSize();
40                 if (size.Height < (u64)m_frame_count) {
41                         m_frame_count = size.Height;
42                 }
43         } else {
44                 // No need to step an animation if we have nothing to draw
45                 m_frame_count = 1;
46         }
47 }
48
49 void GUIAnimatedImage::draw()
50 {
51         // Render the current frame
52         if (m_texture != nullptr) {
53                 video::IVideoDriver *driver = Environment->getVideoDriver();
54
55                 const video::SColor color(255, 255, 255, 255);
56                 const video::SColor colors[] = {color, color, color, color};
57
58                 core::dimension2d<u32> size = m_texture->getOriginalSize();
59                 size.Height /= m_frame_count;
60
61                 draw2DImageFilterScaled( driver, m_texture, AbsoluteRect,
62                                 core::rect<s32>(core::position2d<s32>(0, size.Height * m_frame_idx), size),
63                                 NoClip ? nullptr : &AbsoluteClippingRect, colors, true);
64         }
65
66         // Step the animation
67         if (m_frame_count > 1) {
68                 // Determine the delta time to step
69                 u64 new_global_time = porting::getTimeMs();
70                 if (m_global_time > 0)
71                         m_frame_time += new_global_time - m_global_time;
72
73                 m_global_time = new_global_time;
74
75                 // Advance by the number of elapsed frames, looping if necessary
76                 m_frame_idx += u32(m_frame_time / m_frame_duration);
77                 m_frame_idx %= m_frame_count;
78
79                 // If 1 or more frames have elapsed, reset the frame time counter with
80                 // the remainder
81                 m_frame_time %= m_frame_duration;
82         }
83 }