1 #include "../stdafx.h"
\r
6 #pragma warning (disable : 4244)
\r
8 #include "../concurrency/executor.h"
\r
9 #include "../utility/timer.h"
\r
11 #include <SFML/Graphics.hpp>
\r
13 #include <boost/foreach.hpp>
\r
14 #include <boost/optional.hpp>
\r
15 #include <boost/circular_buffer.hpp>
\r
16 #include <boost/range/algorithm_ext/erase.hpp>
\r
22 namespace caspar { namespace diagnostics {
\r
24 class guide : public drawable
\r
29 guide(color c = color(1.0f, 1.0f, 1.0f, 0.6f))
\r
33 guide(float value, color c = color(1.0f, 1.0f, 1.0f, 0.6f))
\r
37 void set_color(color c) {c_ = c;}
\r
39 void render(sf::RenderTarget&)
\r
41 glEnable(GL_LINE_STIPPLE);
\r
42 glLineStipple(3, 0xAAAA);
\r
43 glBegin(GL_LINE_STRIP);
\r
44 glColor4f(c_.red, c_.green, c_.blue+0.2f, c_.alpha);
\r
45 glVertex3f(0.0f, (1.0f-value_) * 0.8f + 0.1f, 0.0f);
\r
46 glVertex3f(1.0f, (1.0f-value_) * 0.8f + 0.1f, 0.0f);
\r
48 glDisable(GL_LINE_STIPPLE);
\r
52 class line : public drawable
\r
54 boost::optional<diagnostics::guide> guide_;
\r
55 boost::circular_buffer<std::pair<float, bool>> line_data_;
\r
57 std::vector<float> tick_data_;
\r
61 line(size_t res = 600)
\r
64 , c_(1.0f, 1.0f, 1.0f)
\r
66 line_data_.push_back(std::make_pair(-1.0f, false));
\r
69 void update(float value)
\r
71 tick_data_.push_back(value);
\r
79 void guide(const guide& guide)
\r
82 guide_->set_color(c_);
\r
85 void set_color(color c)
\r
89 guide_->set_color(c_);
\r
92 color get_color() const { return c_; }
\r
94 void render(sf::RenderTarget& target)
\r
96 float dx = 1.0f/static_cast<float>(line_data_.capacity());
\r
97 float x = static_cast<float>(line_data_.capacity()-line_data_.size())*dx;
\r
99 if(!tick_data_.empty())
\r
101 float sum = std::accumulate(tick_data_.begin(), tick_data_.end(), 0.0) + std::numeric_limits<float>::min();
\r
102 line_data_.push_back(std::make_pair(static_cast<float>(sum)/static_cast<float>(tick_data_.size()), tick_tag_));
\r
103 tick_data_.clear();
\r
105 else if(!line_data_.empty())
\r
107 line_data_.push_back(std::make_pair(line_data_.back().first, tick_tag_));
\r
112 target.Draw(*guide_);
\r
114 glBegin(GL_LINE_STRIP);
\r
115 glColor4f(c_.red, c_.green, c_.blue, 1.0f);
\r
116 for(size_t n = 0; n < line_data_.size(); ++n)
\r
117 if(line_data_[n].first > -0.5)
\r
118 glVertex3f(x+n*dx, std::max(0.05f, std::min(0.95f, (1.0f-line_data_[n].first)*0.8f + 0.1f)), 0.0f);
\r
121 glEnable(GL_LINE_STIPPLE);
\r
122 glLineStipple(3, 0xAAAA);
\r
123 for(size_t n = 0; n < line_data_.size(); ++n)
\r
125 if(line_data_[n].second)
\r
127 glBegin(GL_LINE_STRIP);
\r
128 glColor4f(c_.red, c_.green, c_.blue, c_.alpha);
\r
129 glVertex3f(x+n*dx, 0.0f, 0.0f);
\r
130 glVertex3f(x+n*dx, 1.0f, 0.0f);
\r
134 glDisable(GL_LINE_STIPPLE);
\r
138 struct graph::implementation : public drawable
\r
140 std::map<std::string, diagnostics::line> lines_;
\r
142 float height_scale_;
\r
144 implementation(const std::string& name)
\r
146 , height_scale_(0){}
\r
148 void update(const std::string& name, float value)
\r
150 context::begin_invoke([=]
\r
152 lines_[name].update(value);
\r
156 void tag(const std::string& name)
\r
158 context::begin_invoke([=]
\r
160 lines_[name].tag();
\r
164 void set_color(const std::string& name, color c)
\r
166 context::begin_invoke([=]
\r
168 lines_[name].set_color(c);
\r
172 void guide(const std::string& name, float value)
\r
174 context::begin_invoke([=]
\r
176 lines_[name].guide(diagnostics::guide(value));
\r
181 void render(sf::RenderTarget& target)
\r
184 glScaled(1.0f, height_scale_, 1.0f);
\r
185 height_scale_ = std::min(1.0f, height_scale_+0.1f);
\r
187 const size_t text_size = 15;
\r
188 const size_t text_margin = 2;
\r
189 const size_t text_offset = text_size+text_margin*2;
\r
191 sf::String text(name_.c_str(), sf::Font::GetDefaultFont(), text_size);
\r
192 text.SetStyle(sf::String::Italic);
\r
193 text.Move(text_margin, text_margin);
\r
196 glScaled(1.0f/GetScale().x, 1.0f/GetScale().y, 1.0f);
\r
198 float x_offset = text.GetPosition().x + text.GetRect().Right + text_margin*4;
\r
199 for(auto it = lines_.begin(); it != lines_.end(); ++it)
\r
201 sf::String line_text(it->first, sf::Font::GetDefaultFont(), text_size);
\r
202 line_text.SetPosition(x_offset, text_margin);
\r
203 auto c = it->second.get_color();
\r
204 line_text.SetColor(sf::Color(c.red*255.0f, c.green*255.0f, c.blue*255.0f, c.alpha*255.0f));
\r
205 target.Draw(line_text);
\r
206 x_offset = line_text.GetRect().Right + text_margin*2;
\r
209 glDisable(GL_TEXTURE_2D);
\r
213 glColor4f(1.0f, 1.0f, 1.0f, 0.2f);
\r
214 glVertex2f(1.0f, 0.99f);
\r
215 glVertex2f(0.0f, 0.99f);
\r
216 glVertex2f(0.0f, 0.01f);
\r
217 glVertex2f(1.0f, 0.01f);
\r
221 glTranslated(0.0f, text_offset/GetScale().y, 1.0f);
\r
222 glScaled(1.0f, 1.0-text_offset/GetScale().y, 1.0f);
\r
224 target.Draw(diagnostics::guide(1.0f, color(1.0f, 1.0f, 1.0f, 0.6f)));
\r
225 target.Draw(diagnostics::guide(0.0f, color(1.0f, 1.0f, 1.0f, 0.6f)));
\r
227 for(auto it = lines_.begin(); it != lines_.end(); ++it)
\r
228 target.Draw(it->second);
\r
235 implementation(implementation&);
\r
236 implementation& operator=(implementation&);
\r
239 graph::graph(const std::string& name) : impl_(new implementation(name))
\r
241 context::register_drawable(impl_);
\r
244 void graph::update(const std::string& name, float value){impl_->update(name, value);}
\r
245 void graph::tag(const std::string& name){impl_->tag(name);}
\r
246 void graph::guide(const std::string& name, float value){impl_->guide(name, value);}
\r
247 void graph::set_color(const std::string& name, color c){impl_->set_color(name, c);}
\r
249 safe_ptr<graph> create_graph(const std::string& name)
\r
251 return safe_ptr<graph>(new graph(name));
\r