KDEGames

kgamecanvas.cpp
1 /* Originally created for KBoard
2  SPDX-FileCopyrightText: 2006 Maurizio Monge <[email protected]>
3 
4  SPDX-License-Identifier: BSD-2-Clause
5 */
6 
7 // KGame namespace changes: [email protected]
8 
9 #include "kgamecanvas.h"
10 
11 // Qt
12 #include <QPaintEvent>
13 #include <QApplication>
14 #include <QTimer>
15 #include <QTime>
16 #include <QElapsedTimer>
17 
18 /*
19  TODO:
20  - (maybe) allow an item to be destroyed while calling KGameCanvasItem::advance.
21  - When a group is hidden/destroyed should only update items (optimize for sparse groups)
22 */
23 
24 #define DEBUG_DONT_MERGE_UPDATES 0
25 #define DEBUG_CANVAS_PAINTS 0
26 
27 /*
28  KGameCanvasAbstract
29 */
31 
32 }
33 
34 KGameCanvasAbstract::~KGameCanvasAbstract() {
35  //Note: this does not delete the items, be sure not to leak memory!
36  for(int i=0;i<m_items.size();i++)
37  m_items[i]->m_canvas = nullptr;
38 }
39 
41  for(int i=m_items.size()-1;i>=0;i--) {
42  KGameCanvasItem *el = m_items[i];
43  if(el->m_visible && el->rect().contains(pt))
44  return el;
45  }
46  return nullptr;
47 }
48 
51 
52  for(int i=m_items.size()-1;i>=0;i--) {
53  KGameCanvasItem *el = m_items[i];
54  if(el->m_visible && el->rect().contains(pt))
55  retv.append(el);
56  }
57 
58  return retv;
59 }
60 
61 
62 /*
63  KGameCanvasWidget
64 */
65 class KGameCanvasWidgetPrivate {
66 public:
67  QTimer m_anim_timer;
68  QElapsedTimer m_anim_time;
69  bool m_pending_update;
70  QRegion m_pending_update_reg;
71 
72 #if DEBUG_CANVAS_PAINTS
73  bool debug_paints;
74 #endif //DEBUG_CANVAS_PAINTS
75 
76  KGameCanvasWidgetPrivate()
77  : m_pending_update(false)
78 #if DEBUG_CANVAS_PAINTS
79  , debug_paints(false)
80 #endif //DEBUG_CANVAS_PAINTS
81  {}
82 };
83 
85 : QWidget(parent)
86 , priv(new KGameCanvasWidgetPrivate()) {
87  priv->m_anim_time.start();
88  connect(&priv->m_anim_timer, &QTimer::timeout, this, &KGameCanvasWidget::processAnimations);
89 }
90 
91 KGameCanvasWidget::~KGameCanvasWidget() {
92  delete priv;
93 }
94 
95 void KGameCanvasWidget::ensureAnimating() {
96  if(!priv->m_anim_timer.isActive() )
97  priv->m_anim_timer.start();
98 }
99 
100 void KGameCanvasWidget::ensurePendingUpdate() {
101  if(priv->m_pending_update)
102  return;
103  priv->m_pending_update = true;
104 
105 #if DEBUG_DONT_MERGE_UPDATES
106  updateChanges();
107 #else //DEBUG_DONT_MERGE_UPDATES
108  QTimer::singleShot( 0, this, &KGameCanvasWidget::updateChanges );
109 #endif //DEBUG_DONT_MERGE_UPDATES
110 }
111 
112 void KGameCanvasWidget::updateChanges() {
113  for(int i=0;i<m_items.size();i++) {
114  KGameCanvasItem *el = m_items.at(i);
115 
116  if(el->m_changed)
117  el->updateChanges();
118  }
119  priv->m_pending_update = false;
120 
121 #if DEBUG_CANVAS_PAINTS
122  repaint();
123  priv->debug_paints = true;
124  repaint( priv->m_pending_update_reg );
125  QApplication::syncX();
126  priv->debug_paints = false;
127  usleep(100000);
128  repaint( priv->m_pending_update_reg );
129  QApplication::syncX();
130  usleep(100000);
131 #else //DEBUG_CANVAS_PAINTS
132  repaint( priv->m_pending_update_reg );
133 #endif //DEBUG_CANVAS_PAINTS
134 
135  priv->m_pending_update_reg = QRegion();
136 }
137 
138 void KGameCanvasWidget::invalidate(const QRect& r, bool /*translate*/) {
139  priv->m_pending_update_reg |= r;
140  ensurePendingUpdate();
141 }
142 
143 void KGameCanvasWidget::invalidate(const QRegion& r, bool /*translate*/) {
144  priv->m_pending_update_reg |= r;
145  ensurePendingUpdate();
146 }
147 
148 void KGameCanvasWidget::paintEvent(QPaintEvent *event) {
149 #if DEBUG_CANVAS_PAINTS
150  if(priv->debug_paints)
151  {
152  QPainter p(this);
153  p.fillRect(event->rect(), Qt::magenta);
154  return;
155  }
156 #endif //DEBUG_CANVAS_PAINTS
157 
158  {QPainter p(this);
159  QRect evr = event->rect();
160  QRegion evreg = event->region();
161 
162  for(int i=0;i<m_items.size();i++) {
163  KGameCanvasItem *el = m_items.at(i);
164  if( el->m_visible && evr.intersects( el->rect() )
165  && evreg.contains( el->rect() ) ) {
166  el->m_last_rect = el->rect();
167  el->paintInternal(&p, evr, evreg, QPoint(), 1.0 );
168  }
169  }}
170 }
171 
172 void KGameCanvasWidget::processAnimations() {
173  if(m_animated_items.empty() ) {
174  priv->m_anim_timer.stop();
175  return;
176  }
177 
178  int tm = priv->m_anim_time.elapsed();
179 
180  // The list MUST be copied, because it could be modified calling advance.
181  // After all since it is implicitly shared the copy will not happen unless
182  // is it actually modified
183  QList<KGameCanvasItem*> ait = m_animated_items;
184  for(int i=0;i<ait.size();i++) {
185  KGameCanvasItem *el = ait[i];
186  el->advance(tm);
187  }
188 
189  if(m_animated_items.empty() )
190  priv->m_anim_timer.stop();
191 }
192 
194  priv->m_anim_timer.setInterval(d);
195 }
196 
198  return priv->m_anim_time.elapsed();
199 }
200 
202  return this;
203 }
204 
206  return QPoint(0, 0);
207 }
208 
209 /*
210  KGameCanvasItem
211 */
213 : m_visible(false)
214 , m_animated(false)
215 , m_opacity(255)
216 , m_pos(0,0)
217 , m_canvas(KGameCanvas)
218 , m_changed(false) {
219  if(m_canvas) m_canvas->m_items.append(this);
220 }
221 
222 KGameCanvasItem::~KGameCanvasItem() {
223  if(m_canvas) {
224  m_canvas->m_items.removeAll(this);
225  if(m_animated)
226  m_canvas->m_animated_items.removeAll(this);
227  if(m_visible)
228  m_canvas->invalidate(m_last_rect, false);
229  }
230 }
231 
233  m_changed = true;
234 
235  //even if m_changed was already true we cannot optimize away this call, because maybe the
236  //item has been reparented, etc. It is a very quick call anyway.
237  if(m_canvas)
238  m_canvas->ensurePendingUpdate();
239 }
240 
241 void KGameCanvasItem::updateChanges() {
242  if(!m_changed)
243  return;
244  if(m_canvas) {
245  m_canvas->invalidate(m_last_rect, false);
246  if(m_visible)
247  m_canvas->invalidate(rect());
248  }
249  m_changed = false;
250 }
251 
252 QPixmap *KGameCanvasItem::transparence_pixmap_cache = nullptr;
253 
254 QPixmap* KGameCanvasItem::getTransparenceCache(const QSize &s) {
255  if(!transparence_pixmap_cache)
256  transparence_pixmap_cache = new QPixmap();
257  if(s.width()>transparence_pixmap_cache->width() ||
258  s.height()>transparence_pixmap_cache->height()) {
259 
260  /* Strange that a pixmap with alpha should be created this way, i think a qt bug */
261  *transparence_pixmap_cache = QPixmap::fromImage( QImage(
262  s.expandedTo(transparence_pixmap_cache->size()), QImage::Format_ARGB32 ) );
263  }
264 
265  return transparence_pixmap_cache;
266 }
267 
268 void KGameCanvasItem::paintInternal(QPainter* pp, const QRect& /*prect*/,
269  const QRegion& /*preg*/, const QPoint& /*delta*/, double cumulative_opacity) {
270  int opacity = int(cumulative_opacity*m_opacity + 0.5);
271 
272  if(opacity <= 0)
273  return;
274 
275  if(opacity >= 255) {
276  paint(pp);
277  return;
278  }
279 
280  if(!layered()) {
281  pp->setOpacity(opacity/255.0);
282  paint(pp);
283  pp->setOpacity(1.0);
284  return;
285  }
286 
287  QRect mr = rect();
288  QPixmap* cache = getTransparenceCache(mr.size());
289 
290  {
291  QPainter p(cache);
292 
293  /* clear */
294  p.setBrush(QColor(255,255,255,0));
295  p.setPen(Qt::NoPen);
297  p.drawRect(QRect(QPoint(),mr.size()));
298 
299  /* paint on the item */
300  p.translate(-mr.topLeft());
301  paint(&p);
302  p.translate(mr.topLeft());
303 
304  /* make the opacity */
305  p.setBrush( QColor(255,255,255,255-opacity) );
306  p.setPen( Qt::NoPen );
308  p.drawRect( QRect(QPoint(),mr.size()) );
309  }
310 
311  pp->drawPixmap(mr.topLeft(), *cache, QRect(QPoint(),mr.size()) );
312 }
313 
315  if(m_canvas == c)
316  return;
317 
318  if(m_canvas) {
319  if(m_visible)
320  m_canvas->invalidate(m_last_rect, false); //invalidate the previously drawn rectangle
321  m_canvas->m_items.removeAll(this);
322  if(m_animated)
323  m_canvas->m_animated_items.removeAll(this);
324  }
325 
326  m_canvas = c;
327 
328  if(m_canvas) {
329  m_canvas->m_items.append(this);
330  if(m_animated) {
331  m_canvas->m_animated_items.append(this);
332  m_canvas->ensureAnimating();
333  }
334  if(m_visible)
335  changed();
336  }
337 }
338 
340  if(m_visible == v)
341  return;
342 
343  m_visible = v;
344  if(m_canvas) {
345  if(!v)
346  m_canvas->invalidate(m_last_rect, false);
347  else
348  changed();
349  }
350  if(!v)
351  m_last_rect = QRect();
352 }
353 
355  if(m_animated == a)
356  return;
357 
358  m_animated = a;
359  if(m_canvas) {
360  if(a) {
361  m_canvas->m_animated_items.append(this);
362  m_canvas->ensureAnimating();
363  }
364  else
365  m_canvas->m_animated_items.removeAll(this);
366  }
367 }
368 
370  if (o<0) o=0;
371  if (o>255) o = 255;
372  m_opacity = o;
373 
374  if(m_canvas && m_visible)
375  changed();
376 }
377 
378 bool KGameCanvasItem::layered() const { return true; }
379 
380 void KGameCanvasItem::advance(int /*msecs*/) { }
381 
382 void KGameCanvasItem::updateAfterRestack(int from, int to)
383 {
384  int inc = from>to ? -1 : 1;
385 
386  QRegion upd;
387  for(int i=from; i!=to;i+=inc)
388  {
389  KGameCanvasItem *el = m_canvas->m_items.at(i);
390  if(!el->m_visible)
391  continue;
392 
393  QRect r = el->rect() & rect();
394  if(!r.isEmpty())
395  upd |= r;
396  }
397 
398  if(!upd.isEmpty())
399  m_canvas->invalidate(upd);
400 }
401 
403 {
404  if(!m_canvas || m_canvas->m_items.last() == this)
405  return;
406 
407  int old_pos = m_canvas->m_items.indexOf(this);
408  m_canvas->m_items.removeAt(old_pos);
409  m_canvas->m_items.append(this);
410  if(m_visible)
411  updateAfterRestack(old_pos, m_canvas->m_items.size()-1);
412 }
413 
415 {
416  if(!m_canvas || m_canvas->m_items.first() == this)
417  return;
418 
419  int old_pos = m_canvas->m_items.indexOf(this);
420  m_canvas->m_items.removeAt(old_pos);
421  m_canvas->m_items.prepend(this);
422 
423  if(m_visible)
424  updateAfterRestack(old_pos, 0);
425 }
426 
428 {
429  if(!m_canvas)
430  return;
431 
432  if(ref->m_canvas != m_canvas)
433  {
434  qCritical("KGameCanvasItem::stackOver: Argument must be a sibling item!\n");
435  return;
436  }
437 
438  int i = m_canvas->m_items.indexOf( ref );
439  if(i < m_canvas->m_items.size()-2 && m_canvas->m_items[i+1] == this)
440  return;
441 
442  int old_pos = m_canvas->m_items.indexOf(this);
443  m_canvas->m_items.removeAt(old_pos);
444  i = m_canvas->m_items.indexOf(ref);
445  m_canvas->m_items.insert(i+1,this);
446 
447  if(m_visible)
448  updateAfterRestack(old_pos, i+1);
449 }
450 
452 {
453  if(!m_canvas)
454  return;
455 
456 
457  if(ref->m_canvas != m_canvas)
458  {
459  qCritical("KGameCanvasItem::stackUnder: Argument must be a sibling item!\n");
460  return;
461  }
462 
463  int i = m_canvas->m_items.indexOf( ref );
464  if(i >= 1 && m_canvas->m_items[i-1] == this)
465  return;
466 
467  int old_pos = m_canvas->m_items.indexOf(this);
468  m_canvas->m_items.removeAt(old_pos);
469  i = m_canvas->m_items.indexOf(ref);
470  m_canvas->m_items.insert(i,this);
471 
472  if(m_visible)
473  updateAfterRestack(old_pos, i);
474 }
475 
476 void KGameCanvasItem::moveTo(const QPoint &newpos)
477 {
478  if(m_pos == newpos)
479  return;
480  m_pos = newpos;
481  if(m_visible && m_canvas)
482  changed();
483 }
484 
486 {
487  if (m_canvas) {
488  return m_canvas->canvasPosition() + m_pos;
489  }
490  else {
491  return m_pos;
492  }
493 }
494 
495 /*
496  KGameCanvasGroup
497 */
499 : KGameCanvasItem(KGameCanvas)
501 , m_child_rect_changed(true) {
502 
503 }
504 
505 KGameCanvasGroup::~KGameCanvasGroup() {
506 
507 }
508 
509 void KGameCanvasGroup::ensureAnimating() {
510  setAnimated(true);
511 }
512 
513 void KGameCanvasGroup::ensurePendingUpdate() {
514  if(!m_changed || !m_child_rect_changed) {
515  m_child_rect_changed = true;
517  }
518 }
519 
520 void KGameCanvasGroup::updateChanges() {
521  if(!m_changed)
522  return;
523  for(int i=0;i<m_items.size();i++) {
524  KGameCanvasItem *el = m_items.at(i);
525 
526  if(el->m_changed)
527  el->updateChanges();
528  }
529  m_changed = false;
530 }
531 
532 void KGameCanvasGroup::changed() {
533  if(!m_changed) {
535 
536  for(int i=0;i<m_items.size();i++)
537  m_items[i]->changed();
538  }
539 }
540 
541 void KGameCanvasGroup::invalidate(const QRect& r, bool translate) {
542  if(m_canvas)
543  m_canvas->invalidate(translate ? r.translated(m_pos) : r, translate);
544  if(!m_changed)
545  ensurePendingUpdate();
546 }
547 
548 void KGameCanvasGroup::invalidate(const QRegion& r, bool translate) {
549  if(m_canvas)
550  m_canvas->invalidate(translate ? r.translated(m_pos) : r, translate);
551  if(!m_changed)
552  ensurePendingUpdate();
553 }
554 
555 void KGameCanvasGroup::advance(int msecs) {
556 
557  // The list MUST be copied, because it could be modified calling advance.
558  // After all since it is implicitly shared the copy will not happen unless
559  // is it actually modified
560  QList<KGameCanvasItem*> ait = m_animated_items;
561  for(int i=0;i<ait.size();i++)
562  {
563  KGameCanvasItem *el = ait[i];
564  el->advance(msecs);
565  }
566 
567  if(m_animated_items.empty())
568  setAnimated(false);
569 }
570 
571 void KGameCanvasGroup::paintInternal(QPainter* p, const QRect& prect,
572  const QRegion& preg, const QPoint& delta, double cumulative_opacity) {
573  cumulative_opacity *= (m_opacity/255.0);
574 
575  QPoint adelta = delta;
576  adelta += m_pos;
577  p->translate(m_pos);
578 
579  for(int i=0;i<m_items.size();i++) {
580  KGameCanvasItem *el = m_items.at(i);
581  QRect r = el->rect().translated(adelta);
582 
583  if( el->m_visible && prect.intersects( r ) && preg.contains( r ) ) {
584  el->m_last_rect = r;
585  el->paintInternal(p,prect,preg,adelta,cumulative_opacity);
586  }
587  }
588 
589  p->translate(-m_pos);
590 }
591 
593  Q_ASSERT(!"This function should never be called");
594 }
595 
597 {
598  if(!m_child_rect_changed)
599  return m_last_child_rect.translated(m_pos);
600 
601  m_child_rect_changed = false;
602  m_last_child_rect = QRect();
603  for(int i=0;i<m_items.size();i++)
604  {
605  KGameCanvasItem *el = m_items[i];
606  if(el->m_visible)
607  m_last_child_rect |= el->rect();
608  }
609 
610  return m_last_child_rect.translated(m_pos);
611 }
612 
614 {
615  return m_canvas ? m_canvas->topLevelCanvas() : nullptr;
616 }
617 
620 }
621 
622 /*
623  KGameCanvasDummy
624 */
626  : KGameCanvasItem(KGameCanvas)
627 {
628 
629 }
630 
631 KGameCanvasDummy::~KGameCanvasDummy()
632 {
633 
634 }
635 
637 }
638 
640 {
641  return QRect();
642 }
643 
644 
645 /*
646  KGameCanvasPixmap
647 */
649  : KGameCanvasItem(KGameCanvas), m_pixmap(p) {
650 
651 }
652 
654  : KGameCanvasItem(KGameCanvas) {
655 
656 }
657 
658 KGameCanvasPixmap::~KGameCanvasPixmap() {
659 
660 }
661 
663  m_pixmap = p;
664  if(visible() && canvas() )
665  changed();
666 }
667 
669  p->drawPixmap(pos(), m_pixmap);
670 }
671 
673  return QRect(pos(), m_pixmap.size());
674 }
675 
676 KGameCanvasRenderedPixmap::KGameCanvasRenderedPixmap(KGameRenderer* renderer, const QString& spriteKey, KGameCanvasAbstract* canvas)
677  : KGameCanvasPixmap(canvas)
678  , KGameRendererClient(renderer, spriteKey)
679 {
680 }
681 
683 {
685 }
686 
687 /*
688  KGameCanvasTiledPixmap
689 */
691  bool move_orig, KGameCanvasAbstract* KGameCanvas)
692  : KGameCanvasItem(KGameCanvas)
693  , m_pixmap(pixmap)
694  , m_size(size)
695  , m_origin(origin)
696  , m_move_orig(move_orig) {
697 
698 }
699 
701  : KGameCanvasItem(KGameCanvas)
702  , m_size(0,0)
703  , m_origin(0,0)
704  , m_move_orig(false) {
705 
706 }
707 
708 KGameCanvasTiledPixmap::~KGameCanvasTiledPixmap() {
709 
710 }
711 
713  m_pixmap = pixmap;
714  if(visible() && canvas() )
715  changed();
716 }
717 
719  m_size = size;
720  if(visible() && canvas() )
721  changed();
722 }
723 
725 {
726  m_origin = m_move_orig ? origin - pos() : origin;
727 
728  if(visible() && canvas() )
729  changed();
730 }
731 
732 
734 {
735  if(move_orig && !m_move_orig)
736  m_origin -= pos();
737  if(move_orig && !m_move_orig)
738  m_origin += pos();
739  m_move_orig = move_orig;
740 }
741 
743 {
744  if(m_move_orig)
745  p->drawTiledPixmap( rect(), m_pixmap, m_origin);
746  else
747  p->drawTiledPixmap( rect(), m_pixmap, m_origin+pos() );
748 }
749 
751 {
752  return QRect(pos(), m_size);
753 }
754 
755 
756 /*
757  KGameCanvasRectangle
758 */
760  : KGameCanvasItem(KGameCanvas)
761  , m_color(color)
762  , m_size(size)
763 {
764 
765 }
766 
768  : KGameCanvasItem(KGameCanvas)
769  , m_size(0,0)
770 {
771 
772 }
773 
774 KGameCanvasRectangle::~KGameCanvasRectangle()
775 {
776 
777 }
778 
780 {
781  m_color = color;
782  if(visible() && canvas() )
783  changed();
784 }
785 
787 {
788  m_size = size;
789  if(visible() && canvas() )
790  changed();
791 }
792 
794  p->fillRect( rect(), m_color );
795 }
796 
798  return QRect(pos(), m_size);
799 }
800 
801 
802 /*
803  KGameCanvasText
804 */
806  const QFont& font, HPos hp, VPos vp,
807  KGameCanvasAbstract* KGameCanvas)
808  : KGameCanvasItem(KGameCanvas)
809  , m_text(text)
810  , m_color(color)
811  , m_font(font)
812  , m_hpos(hp)
813  , m_vpos(vp) {
814  calcBoundingRect();
815 }
816 
818  : KGameCanvasItem(KGameCanvas)
819  //, m_text("")
820  , m_color(Qt::black)
821  , m_font(QApplication::font())
822  , m_hpos(HStart)
823  , m_vpos(VBaseline) {
824 
825 }
826 
827 KGameCanvasText::~KGameCanvasText() {
828 
829 }
830 
831 void KGameCanvasText::calcBoundingRect() {
832  m_bounding_rect = QFontMetrics(m_font).boundingRect(m_text);
833  /*printf("b rect is %d %d %d %d\n",
834  m_bounding_rect.x(),
835  m_bounding_rect.y(),
836  m_bounding_rect.width(),
837  m_bounding_rect.height() );*/
838 }
839 
841  if(m_text == text)
842  return;
843  m_text = text;
844  calcBoundingRect();
845 
846  if(visible() && canvas() )
847  changed();
848 }
849 
851  m_color = color;
852 }
853 
855  m_font = font;
856  calcBoundingRect();
857 
858  if(visible() && canvas() )
859  changed();
860 }
861 
863  pos() += offsetToDrawPos();
864  m_hpos = hp;
865  m_vpos = vp;
866  pos() -= offsetToDrawPos();
867 }
868 
869 QPoint KGameCanvasText::offsetToDrawPos() const {
870  QPoint retv;
871 
872  switch(m_hpos) {
873  case HStart:
874  retv.setX(0);
875  break;
876  case HLeft:
877  retv.setX(-m_bounding_rect.left());
878  break;
879  case HRight:
880  retv.setX(-m_bounding_rect.right());
881  break;
882  case HCenter:
883  retv.setX(-(m_bounding_rect.left()+m_bounding_rect.right())/2);
884  break;
885  }
886 
887  switch(m_vpos) {
888  case VBaseline:
889  retv.setY(0);
890  break;
891  case VTop:
892  retv.setY(-m_bounding_rect.top());
893  break;
894  case VBottom:
895  retv.setY(-m_bounding_rect.bottom());
896  break;
897  case VCenter:
898  retv.setY(-(m_bounding_rect.top()+m_bounding_rect.bottom())/2);
899  break;
900  }
901 
902  return retv;
903 }
904 
906  p->setPen(m_color);
907  p->setFont(m_font);
908  p->drawText( pos() + offsetToDrawPos(), m_text);
909 }
910 
912  return m_bounding_rect.translated( pos() + offsetToDrawPos() );
913 }
914 
915 
916 /*
917  KGameCanvasPicture
918 */
920  : KGameCanvasItem(KGameCanvas), m_picture(p)
921 {
922 
923 }
924 
926  : KGameCanvasItem(KGameCanvas)
927 {
928 
929 }
930 
931 KGameCanvasPicture::~KGameCanvasPicture()
932 {
933 
934 }
935 
937 {
938  m_picture = p;
939 
940  if(visible() && canvas() )
941  changed();
942 }
943 
945 {
946  p->drawPicture(pos(), m_picture);
947 }
948 
950 {
951  return m_picture.boundingRect().translated( pos());
952 }
953 
955 : m_child_rect_valid(false)
956 {
957 }
958 
959 QRect KGameCanvasAdapter::childRect()
960 {
961  if (!m_child_rect_valid) {
962  m_child_rect = QRect();
963  for (KGameCanvasItem* el : qAsConst(m_items)) {
964  m_child_rect |= el->rect();
965  }
966  m_child_rect_valid = true;
967  }
968 
969  return m_child_rect;
970 }
971 
973 {
974  for (KGameCanvasItem* el : qAsConst(m_items)) {
975  if (el->m_visible) {
976  el->m_last_rect = el->rect();
977  el->paintInternal(painter, childRect(), childRect(), QPoint(), 1.0);
978  }
979  }
980 }
981 
982 void KGameCanvasAdapter::ensurePendingUpdate()
983 {
984  m_child_rect_valid = false;
985 
986  for (KGameCanvasItem* el : qAsConst(m_items)) {
987  if (el->m_changed) {
988  el->updateChanges();
989  }
990  }
991 
992  updateParent(m_invalidated_rect);
993  m_invalidated_rect = QRect();
994 }
995 
996 void KGameCanvasAdapter::invalidate(const QRegion& r, bool)
997 {
998  invalidate(r.boundingRect());
999 }
1000 
1001 void KGameCanvasAdapter::invalidate(const QRect& r, bool)
1002 {
1003  m_invalidated_rect |= r;
1004 }
1005 
1006 
QRect rect() const override
This returns the bouding rect of all children.
void stackUnder(KGameCanvasItem *ref)
Restacks the item immediately under ref.
KGameCanvasTiledPixmap(const QPixmap &pixmap, const QSize &size, const QPoint &origin, bool move_orig, KGameCanvasAbstract *canvas=nullptr)
Constructor, specifying the pixmap and the parameters to use.
QFont font() const
Returns the font.
Definition: kgamecanvas.h:527
void setOpacity(qreal opacity)
QSize size() const const
void setAnimated(bool a)
Set the item as animated or not.
QSize size() const const
void setMoveOrigin(bool move_orig)
Sets if the origin of the brush will be moved with the pixmap.
void setAnimationDelay(int d)
Set the delay of the animation, in milliseconds.
An abstract item.
Definition: kgamecanvas.h:96
int width() const const
VPos
Specifies the meaning of the y coordinate of the item.
Definition: kgamecanvas.h:485
int width() const const
void receivePixmap(const QPixmap &pixmap) override
This method is called when the KGameRenderer has provided a new pixmap for this client (esp...
QRect boundingRect() const const
Container widget.
Definition: kgamecanvas.h:555
void fillRect(const QRectF &rectangle, const QBrush &brush)
void setCompositionMode(QPainter::CompositionMode mode)
void setFont(const QFont &font)
Sets the font.
void paint(QPainter *p) override
Override this function to draw the item with the painter.
Container class.
Definition: kgamecanvas.h:37
int right() const const
KGameCanvasPicture(const QPicture &picture, KGameCanvasAbstract *canvas=nullptr)
Constructor, specifying the picture to use.
KGameCanvasWidget(QWidget *parent=nullptr)
The constructor.
Definition: kgamecanvas.cpp:84
QRect rect() const override
Override this function to return the rect the item will be drawn into.
virtual void ensurePendingUpdate()=0
Virtual function to ensure an update is pending, called from children.
QList< KGameCanvasItem * > itemsAt(const QPoint &pos) const
Helper function to retrieve all the items at the given position, starting from the topmost one...
Definition: kgamecanvas.cpp:49
void moveTo(const QPoint &newpos)
Sets a new position.
QColor color() const
Returns the color.
Definition: kgamecanvas.h:521
QPixmap pixmap() const
Returns the pixmap.
Definition: kgamecanvas.h:398
const T & at(int i) const const
void removeAt(int i)
bool intersects(const QRect &rectangle) const const
QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags)
void drawTiledPixmap(const QRectF &rectangle, const QPixmap &pixmap, const QPointF &position)
QPoint canvasPosition() const override
QRect boundingRect() const const
KGameCanvasText(const QString &text, const QColor &color, const QFont &font, HPos hp, VPos vp, KGameCanvasAbstract *canvas=nullptr)
Constructor, specifying the text and the parameters to use.
void setVisible(bool v)
Set the item as visible or hidden.
virtual void paint(QPainter *p)=0
Override this function to draw the item with the painter.
void raise()
Restacks the item on the top of the canvas.
virtual bool layered() const
Override this function to specify if the painting operations will paint over each other...
QRect rect() const override
This returns an empty rectangle.
void setSize(const QSize &size)
Sets the size.
KGameCanvasAbstract()
The constructor.
Definition: kgamecanvas.cpp:30
virtual QPoint canvasPosition() const =0
int mSecs()
Return the number of milliseconds from the creation of the canvas (see also KGameCanvasItem::advance)...
int size() const const
void setColor(const QColor &color)
Sets the color.
void setColor(const QColor &color)
Sets the color.
QPoint absolutePosition() const
KGameCanvasAbstract * canvas() const
Returns the canvas that is actually "owning" the item.
Definition: kgamecanvas.h:174
int indexOf(const T &value, int from) const const
KGameCanvasDummy(KGameCanvasAbstract *canvas=nullptr)
Constructor.
const QRect & rect() const const
KGameCanvasItem * itemAt(const QPoint &pos) const
Helper function to retrieve the topmost item at the given position.
Definition: kgamecanvas.cpp:40
void timeout()
void drawRect(const QRectF &rectangle)
QRect boundingRect(QChar ch) const const
void setFont(const QFont &font)
QRect rect() const override
Override this function to return the rect the item will be drawn into.
void append(const T &value)
void setSize(const QSize &size)
Sets the size.
bool empty() const const
KGameCanvasGroup(KGameCanvasAbstract *canvas=nullptr)
Constructor.
void paint(QPainter *p) override
Override this function to draw the item with the painter.
int top() const const
void setPen(const QColor &color)
int left() const const
QRegion translated(int dx, int dy) const const
Cache-enabled rendering of SVG themes.
Definition: kgamerenderer.h:86
void drawPixmap(const QRectF &target, const QPixmap &pixmap, const QRectF &source)
int removeAll(const T &value)
void setBrush(const QBrush &brush)
void drawText(const QPointF &position, const QString &text)
QString text() const
Returns the text.
Definition: kgamecanvas.h:515
virtual void changed()
schedule an update if the item
QRect translated(int dx, int dy) const const
T & first()
KGameCanvasWidget * topLevelCanvas() override
returns &#39;this&#39;
void paint(QPainter *p) override
Override this function to draw the item with the painter.
virtual QRect rect() const =0
Override this function to return the rect the item will be drawn into.
void paint(QPainter *p) override
Override this function to draw the item with the painter.
KGameCanvasRectangle(const QColor &color, const QSize &size, KGameCanvasAbstract *canvas=nullptr)
Constructor, specifying the pixmap and the parameters to use.
void stackOver(KGameCanvasItem *ref)
Restacks the item immediately over ref.
bool contains(const QPoint &p) const const
CompositionMode_Source
int height() const const
void putInCanvas(KGameCanvasAbstract *canvas)
Lets you specify the owning canvas.
bool isEmpty() const const
QRect rect() const override
Override this function to return the rect the item will be drawn into.
virtual void invalidate(const QRect &r, bool translate=true)=0
Virtual function to update a rect.
void repaint()
QColor color() const
Returns the color.
Definition: kgamecanvas.h:448
An object that receives pixmaps from a KGameRenderer.
void paint(QPainter *p) override
This paints all the children.
bool contains(const QRect &rectangle, bool proper) const const
void setPositioning(HPos hp, VPos vp)
Sets the positioning style.
void setPixmap(const QPixmap &pixmap)
Sets the pixmap of the sprite.
QPixmap pixmap() const
Returns the pixmap.
Definition: kgamecanvas.h:343
void setOrigin(const QPoint &size)
Sets the origin of the tiles.
virtual void advance(int msecs)
Override this function to handle animations, the default function does nothing.
QSize expandedTo(const QSize &otherSize) const const
void insert(int i, const T &value)
QPoint pos() const
Returns the position of the item.
Definition: kgamecanvas.h:184
int opacity() const
Returns the opacity of the item.
Definition: kgamecanvas.h:150
HPos
Specifies the meaning of the x coordinate of the item.
Definition: kgamecanvas.h:475
bool visible() const
Returns true if the item is visible.
Definition: kgamecanvas.h:138
T & last()
void setOpacity(int o)
Set the item&#39;s opacity value (int the 0-255 range)
virtual void ensureAnimating()=0
Virtual function to let know the canvas that it has animated items in it.
int height() const const
int bottom() const const
void setText(const QString &text)
Sets the text.
QPoint topLeft() const const
void setX(int x)
void setY(int y)
void translate(const QPointF &offset)
bool isEmpty() const const
void lower()
Restacks the item on the bottom of the canvas.
void prepend(const T &value)
KGameCanvasAdapter()
Constructor.
void drawPicture(const QPointF &point, const QPicture &picture)
QRect rect() const override
Override this function to return the rect the item will be drawn into.
KGameCanvasPixmap(const QPixmap &pixmap, KGameCanvasAbstract *canvas=nullptr)
Constructor, specifying the pixmap to use.
void advance(int msecs) override
Animations step, updates the animation for the children.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
virtual void updateParent(const QRect &rect)=0
Notify the parent that the adapter content inside rect needs to be redrawn.
void paint(QPainter *p) override
This function does nothing (of course)
virtual bool event(QEvent *event) override
void paint(QPainter *p) override
Override this function to draw the item with the painter.
void setPixmap(const QPixmap &pixmap)
Sets the pixmap of the tile.
QPoint origin() const
The origin.
Definition: kgamecanvas.h:407
KGameCanvasItem(KGameCanvasAbstract *canvas=nullptr)
Constructor, it allows you to specify the reference canvas or to create an orphan item that will be p...
virtual void render(QPainter *p)
Draw the items of the adapter using the specified painter.
KGameCanvasWidget * topLevelCanvas() override
returns the toplevel canvas (or null if it is in an orphan tree)
void setPicture(const QPicture &picture)
Sets the picture of the sprite.
QRect rect() const override
Override this function to return the rect the item will be drawn into.
QPoint canvasPosition() const override
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Dec 7 2021 22:34:14 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.