99#include " CommonFramework/GlobalServices.h"
1010#include " VideoOverlayWidget.h"
1111
12- // #include <iostream>
13- // using std::cout;
14- // using std::endl;
12+ // #include <iostream>
13+ // using std::cout;
14+ // using std::endl;
1515
1616namespace PokemonAutomation {
1717
@@ -33,6 +33,7 @@ VideoOverlayWidget::VideoOverlayWidget(QWidget& parent, VideoOverlaySession& ses
3333 , m_session(session)
3434 , m_boxes(std::make_shared<std::vector<OverlayBox>>(session.boxes()))
3535 , m_texts(std::make_shared<std::vector<OverlayText>>(session.texts()))
36+ , m_images(std::make_shared<std::vector<OverlayImage>>(session.images()))
3637 , m_log(std::make_shared<std::vector<OverlayLogLine>>(session.log_texts()))
3738 , m_stats(nullptr )
3839{
@@ -50,38 +51,37 @@ VideoOverlayWidget::VideoOverlayWidget(QWidget& parent, VideoOverlaySession& ses
5051 }
5152}
5253
53- void VideoOverlayWidget::enabled_boxes (bool enabled){
54- QMetaObject::invokeMethod (this , [this ]{ this ->update (); });
55- }
56- void VideoOverlayWidget::enabled_text (bool enabled){
57- QMetaObject::invokeMethod (this , [this ]{ this ->update (); });
58- }
59- void VideoOverlayWidget::enabled_log (bool enabled){
60- QMetaObject::invokeMethod (this , [this ]{ this ->update (); });
61- }
62- void VideoOverlayWidget::enabled_stats (bool enabled){
54+ void VideoOverlayWidget::async_update (){
55+ // by using QMetaObject::invokeMethod, we can call this->update() on a non-main thread
56+ // without trigger Qt crash, as normally this->update() can only be called on the main
57+ // thread.
6358 QMetaObject::invokeMethod (this , [this ]{ this ->update (); });
6459}
6560
66- void VideoOverlayWidget::update_boxes (const std::shared_ptr<const std::vector<OverlayBox>>& boxes){
61+ void VideoOverlayWidget::on_overlay_update_boxes (const std::shared_ptr<const std::vector<OverlayBox>>& boxes){
6762 WriteSpinLock lg (m_lock, " VideoOverlay::update_boxes()" );
6863 m_boxes = boxes;
6964}
70- void VideoOverlayWidget::update_text (const std::shared_ptr<const std::vector<OverlayText>>& texts){
65+ void VideoOverlayWidget::on_overlay_update_text (const std::shared_ptr<const std::vector<OverlayText>>& texts){
7166 WriteSpinLock lg (m_lock, " VideoOverlay::update_text()" );
7267 m_texts = texts;
7368}
74- void VideoOverlayWidget::update_log (const std::shared_ptr<const std::vector<OverlayLogLine>>& texts){
69+ void VideoOverlayWidget::on_overlay_update_images (const std::shared_ptr<const std::vector<OverlayImage>>& images){
70+ WriteSpinLock lg (m_lock, " VideoOverlay::update_images()" );
71+ m_images = images;
72+ }
73+
74+ void VideoOverlayWidget::on_overlay_update_log (const std::shared_ptr<const std::vector<OverlayLogLine>>& logs){
7575 WriteSpinLock lg (m_lock, " VideoOverlay::update_log_text()" );
76- m_log = texts ;
76+ m_log = logs ;
7777}
7878#if 0
7979void VideoOverlayWidget::update_log_background(const std::shared_ptr<const std::vector<VideoOverlaySession::Box>>& bg_boxes){
8080 WriteSpinLock lg(m_lock, "VideoOverlay::update_log_background()");
8181 m_log_text_bg_boxes = bg_boxes;
8282}
8383#endif
84- void VideoOverlayWidget::update_stats (const std::list<OverlayStat*>* stats){
84+ void VideoOverlayWidget::on_overlay_update_stats (const std::list<OverlayStat*>* stats){
8585 WriteSpinLock lg (m_lock, " VideoOverlay::update_stats()" );
8686 m_stats = stats;
8787}
@@ -94,33 +94,37 @@ void VideoOverlayWidget::on_watchdog_timeout(){
9494
9595
9696void VideoOverlayWidget::resizeEvent (QResizeEvent* event){}
97+
9798void VideoOverlayWidget::paintEvent (QPaintEvent*){
9899 QPainter painter (this );
99100
100101 {
101102 WriteSpinLock lg (m_lock, " VideoOverlay::paintEvent()" );
102103
103104 if (m_session.enabled_boxes ()){
104- update_boxes (painter);
105+ render_boxes (painter);
105106 }
106107 if (m_session.enabled_text ()){
107- update_text (painter);
108+ render_text (painter);
109+ }
110+ if (m_session.enabled_images ()){
111+ render_images (painter);
108112 }
109113 if (m_session.enabled_log ()){
110- update_log (painter);
114+ render_log (painter);
111115 }
112116 if (m_session.enabled_stats () && m_stats){
113- update_stats (painter);
117+ render_stats (painter);
114118 }
115119 }
116120
117121 global_watchdog ().delay (*this );
118122}
119123
120124
121- void VideoOverlayWidget::update_boxes (QPainter& painter){
122- int width = this ->width ();
123- int height = this ->height ();
125+ void VideoOverlayWidget::render_boxes (QPainter& painter){
126+ const int width = this ->width ();
127+ const int height = this ->height ();
124128 for (const auto & item : *m_boxes){
125129 QColor color = QColor ((uint32_t )item.color );
126130 painter.setPen (color);
@@ -196,9 +200,9 @@ void VideoOverlayWidget::update_boxes(QPainter& painter){
196200 painter.drawText (QPoint (xmin + padding_width, ymin - 2 *padding_height), text);
197201 }
198202}
199- void VideoOverlayWidget::update_text (QPainter& painter){
200- int width = this ->width ();
201- int height = this ->height ();
203+ void VideoOverlayWidget::render_text (QPainter& painter){
204+ const int width = this ->width ();
205+ const int height = this ->height ();
202206 for (const auto & item: *m_texts){
203207 painter.setPen (QColor ((uint32_t )item.color ));
204208 QFont text_font = this ->font ();
@@ -211,7 +215,25 @@ void VideoOverlayWidget::update_text(QPainter& painter){
211215 painter.drawText (QPoint (xmin, ymin), QString::fromStdString (item.message ));
212216 }
213217}
214- void VideoOverlayWidget::update_log (QPainter& painter){
218+ void VideoOverlayWidget::render_images (QPainter& painter){
219+ const double width = static_cast <double >(this ->width ());
220+ const double height = static_cast <double >(this ->height ());
221+
222+ for (const auto & image_overlay: *m_images){
223+ QImage q_image = image_overlay.image .to_QImage_ref ();
224+ // source rect is the entire portion of the q_image, in pixel units
225+ QRectF source_rect (0.0 , 0.0 , static_cast <double >(q_image.width ()), static_cast <double >(q_image.height ()));
226+ // build a target_rect. target_rect is what region the overlay image should appear inside the overlay viewport.
227+ // target_rect is in pixel units of the viewport
228+ const double target_start_x = width * image_overlay.x ;
229+ const double target_start_y = height * image_overlay.y ;
230+ const double target_width = width * image_overlay.width ;
231+ const double target_height = height * image_overlay.height ;
232+ QRectF target_rect (target_start_x, target_start_y, target_width, target_height);
233+ painter.drawImage (target_rect, q_image, source_rect);
234+ }
235+ }
236+ void VideoOverlayWidget::render_log (QPainter& painter){
215237 if (m_log->empty ()){
216238 return ;
217239 }
@@ -231,7 +253,9 @@ void VideoOverlayWidget::update_log(QPainter& painter){
231253
232254 // Draw the box.
233255 {
234- QColor box_color (10 , 10 , 10 , 200 );
256+ // set a semi-transparent dark color so that user can see the log lines while can also see
257+ // vaguely the video stream content behind it
258+ QColor box_color (10 , 10 , 10 , 200 ); // r=g=b=10, alpha=200
235259 painter.setPen (box_color);
236260 const int xmin = std::max ((int )(width * LOG_MIN_X + 0.5 ), 1 );
237261 const int ymin = std::max ((int )(height * (LOG_MAX_Y - log_bg_height) + 0.5 ), 1 );
@@ -257,7 +281,7 @@ void VideoOverlayWidget::update_log(QPainter& painter){
257281 y -= LOG_LINE_SPACING;
258282 }
259283}
260- void VideoOverlayWidget::update_stats (QPainter& painter){
284+ void VideoOverlayWidget::render_stats (QPainter& painter){
261285 const double TEXT_SIZE = 0.02 ;
262286 const double ROW_HEIGHT = 0.03 ;
263287
0 commit comments