1 /* Originally created for KBoard 2 SPDX-FileCopyrightText: 2006 Maurizio Monge <maurizio.monge@gmail.com> 3 4 SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 #ifndef __KGAMECANVAS_H__ 8 #define __KGAMECANVAS_H__ 9 10 /* 11 * Author: Maurizio Monge <maurizio.monge@gmail.com> 12 */ 13 14 // own 15 #include "libkdegamesprivate_export.h" 16 #include "kgamerendererclient.h" 17 // Qt 18 #include <QList> 19 #include <QPoint> 20 #include <QPicture> 21 #include <QPixmap> 22 #include <QPainter> 23 #include <QRect> 24 #include <QRegion> 25 #include <QWidget> 26 27 class KGameCanvasItem; 28 29 /** 30 \class KGameCanvasAbstract kgamecanvas.h <KGameCanvas> 31 \brief Container class. 32 33 A KGameCanvasAbstract is a set of canvas items. 34 35 \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. 36 */ 37 class KDEGAMESPRIVATE_EXPORT KGameCanvasAbstract 38 { 39 protected: 40 friend class KGameCanvasItem; 41 42 QList<KGameCanvasItem*> m_items; 43 QList<KGameCanvasItem*> m_animated_items; 44 45 public: 46 /** The constructor */ 47 KGameCanvasAbstract(); 48 49 virtual ~KGameCanvasAbstract(); 50 51 /** Returns a const pointer to the list holding all the items in the canvas */ items()52 const QList<KGameCanvasItem*>* items() const { return &m_items; } 53 54 /** Helper function to retrieve the topmost item at the given position */ 55 KGameCanvasItem* itemAt(const QPoint &pos) const; 56 57 /** Overload, same as above */ itemAt(int x,int y)58 KGameCanvasItem* itemAt(int x, int y) const { return itemAt(QPoint(x,y)); } 59 60 /** Helper function to retrieve all the items at the given position, 61 starting from the topmost one. */ 62 QList<KGameCanvasItem*> itemsAt(const QPoint &pos) const; 63 64 /** Overload, same as above */ itemsAt(int x,int y)65 QList<KGameCanvasItem*> itemsAt(int x, int y) const { return itemsAt(QPoint(x,y)); } 66 67 /** Virtual function to let know the canvas that it has animated items in it */ 68 virtual void ensureAnimating() = 0; 69 70 /** Virtual function to ensure an update is pending, called from children */ 71 virtual void ensurePendingUpdate() = 0; 72 73 /** Virtual function to update a rect */ 74 virtual void invalidate(const QRect& r, bool translate = true) = 0; 75 76 /** Virtual function to update a region */ 77 virtual void invalidate(const QRegion& r, bool translate = true) = 0; 78 79 /** Returns the toplevel non-group KGameCanvasWidget object */ 80 virtual class KGameCanvasWidget* topLevelCanvas() = 0; 81 82 /** @return Position of the abstract canvas relative to the toplevel canvas. */ 83 virtual QPoint canvasPosition() const = 0; 84 }; 85 86 87 /** 88 \class KGameCanvasItem kgamecanvas.h <KGameCanvas> 89 \brief An abstract item. 90 91 A KGameCanvasItem is an abstract class to represent a generic item that can be 92 put in a canvas. 93 94 \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. 95 */ 96 class KDEGAMESPRIVATE_EXPORT KGameCanvasItem 97 { 98 private: 99 friend class KGameCanvasAbstract; 100 friend class KGameCanvasWidget; 101 friend class KGameCanvasGroup; 102 friend class KGameCanvasAdapter; 103 104 bool m_visible; 105 bool m_animated; 106 int m_opacity; 107 QPoint m_pos; 108 KGameCanvasAbstract *m_canvas; 109 110 bool m_changed; 111 QRect m_last_rect; 112 113 static QPixmap* transparence_pixmap_cache; 114 static QPixmap* getTransparenceCache(const QSize &s); 115 virtual void paintInternal(QPainter* p, const QRect& prect, const QRegion& preg, 116 const QPoint &delta, double cumulative_opacity); 117 118 void updateAfterRestack(int from, int to); 119 120 /* function to update pending changes, called from parent */ 121 virtual void updateChanges(); 122 123 public: 124 /** Constructor, it allows you to specify the reference canvas or to create 125 an orphan item that will be put into a canvas in a second moment. 126 The item is always hidden after being created. 127 Note that the restacking functions are quite intelligent and will only 128 repaint if there is an actual need of doing it. So if you call raise on 129 an item that is already (locally) on the top, no redraw will take place */ 130 explicit KGameCanvasItem(KGameCanvasAbstract* canvas = nullptr); 131 132 virtual ~KGameCanvasItem(); 133 134 /** schedule an update if the item */ 135 virtual void changed(); 136 137 /** Returns true if the item is visible */ visible()138 bool visible() const { return m_visible; } 139 140 /** Set the item as visible or hidden */ 141 void setVisible(bool v); 142 143 /** Returns true if the item is animated */ animated()144 bool animated() const { return m_animated; } 145 146 /** Set the item as animated or not */ 147 void setAnimated(bool a); 148 149 /** Returns the opacity of the item */ opacity()150 int opacity() const { return m_opacity; } 151 152 /** Set the item's opacity value (int the 0-255 range) */ 153 void setOpacity(int o); 154 155 /** Hides the item */ hide()156 void hide(){ setVisible(false); } 157 158 /** Shows the item */ show()159 void show(){ setVisible(true); } 160 161 /** Restacks the item on the top of the canvas */ 162 void raise(); 163 164 /** Restacks the item on the bottom of the canvas */ 165 void lower(); 166 167 /** Restacks the item immediately over ref */ 168 void stackOver(KGameCanvasItem* ref); 169 170 /** Restacks the item immediately under ref */ 171 void stackUnder(KGameCanvasItem* ref); 172 173 /** Returns the canvas that is actually "owning" the item */ canvas()174 KGameCanvasAbstract *canvas() const { return m_canvas; } 175 176 /** Returns the toplevel canvas widget, or NULL */ topLevelCanvas()177 KGameCanvasWidget *topLevelCanvas() const { return m_canvas ? m_canvas->topLevelCanvas() : nullptr; } 178 179 /** Lets you specify the owning canvas. Call this function with canvas 180 set to NULL to remove the item from the current canvas. */ 181 void putInCanvas(KGameCanvasAbstract *canvas); 182 183 /** Returns the position of the item */ pos()184 QPoint pos() const { return m_pos; } 185 186 /** @return Position of the item relative to the top level canvas. */ 187 QPoint absolutePosition() const; 188 189 /** Sets a new position. Note that an update will be posted to the parent 190 canvas, and if you move an item twice in very little time, a region 191 bigger than needed will be updated, causing a possible inefficiency */ 192 void moveTo(const QPoint &newpos); 193 194 /** Overload, same as above */ moveTo(int x,int y)195 void moveTo(int x, int y) { moveTo( QPoint(x,y)); } 196 197 /** Override this function to draw the item with the painter */ 198 virtual void paint(QPainter* p) = 0; 199 200 /** Override this function to return the rect the item will be drawn into */ 201 virtual QRect rect() const = 0; 202 203 /** Override this function to specify if the painting operations will paint over 204 each other. If not, the item will be drawn more quickly when opacity is != 255, 205 because it does not have to be painted onto a pixmap first. If you don't care 206 about the item's opacity, don't care about this function as well. */ 207 virtual bool layered() const; 208 209 /** Override this function to handle animations, the default function does nothing. 210 The argument is the number of milliseconds from the creation of the canvas, so 211 that you use it to handle the animation. */ 212 virtual void advance(int msecs); 213 }; 214 215 216 /** 217 \class KGameCanvasDummy kgamecanvas.h <KGameCanvas> 218 \brief A dummy (empty) item. 219 220 A KGameCanvasDummy is an empty, invisible item. 221 You can use it as reference for stacking items in the canvas using the 222 stackOver and stackUnder functions. 223 224 \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. 225 */ 226 class KDEGAMESPRIVATE_EXPORT KGameCanvasDummy : public KGameCanvasItem 227 { 228 public: 229 /** Constructor */ 230 explicit KGameCanvasDummy(KGameCanvasAbstract* canvas = nullptr); 231 232 ~KGameCanvasDummy() override; 233 234 /** This function does nothing (of course) */ 235 void paint(QPainter* p) override; 236 237 /** This returns an empty rectangle */ 238 QRect rect() const override; 239 }; 240 241 242 /** 243 \class KGameCanvasGroup kgamecanvas.h <KGameCanvas> 244 \brief An item containing other items. 245 246 A KGameCanvasGroup is an KGameCanvasItem, but it is also a KGameCanvasAbstract, 247 so you can add children items to it. Just an inner canvas, if you prefer. 248 249 \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. 250 */ 251 class KDEGAMESPRIVATE_EXPORT KGameCanvasGroup : public KGameCanvasItem, public KGameCanvasAbstract 252 { 253 private: 254 mutable bool m_child_rect_changed; 255 mutable QRect m_last_child_rect; 256 257 void paintInternal(QPainter* p, const QRect& prect, const QRegion& preg, 258 const QPoint& delta, double cumulative_opacity) override; 259 260 void ensureAnimating() override; 261 void ensurePendingUpdate() override; 262 void invalidate(const QRect& r, bool translate = true) override; 263 void invalidate(const QRegion& r, bool translate = true) override; 264 void updateChanges() override; 265 void changed() override; 266 267 public: 268 /** Constructor */ 269 explicit KGameCanvasGroup(KGameCanvasAbstract* canvas = nullptr); 270 271 ~KGameCanvasGroup() override; 272 273 /** This paints all the children */ 274 void paint(QPainter* p) override; 275 276 /** This returns the bouding rect of all children */ 277 QRect rect() const override; 278 279 /** Animations step, updates the animation for the children */ 280 void advance(int msecs) override; 281 282 /** returns the toplevel canvas (or null if it is in an orphan tree) */ 283 KGameCanvasWidget* topLevelCanvas() override; 284 285 QPoint canvasPosition() const override; 286 }; 287 288 /** 289 \class KGameCanvasPicture kgamecanvas.h <KGameCanvas> 290 \brief A picture, ie a collection of paint operations. 291 292 A KGameCanvasPicture is a picture that can be replayed on the canvas. 293 294 \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. 295 */ 296 class KDEGAMESPRIVATE_EXPORT KGameCanvasPicture : public KGameCanvasItem 297 { 298 private: 299 QPicture m_picture; 300 301 public: 302 /** Constructor, specifying the picture to use */ 303 explicit KGameCanvasPicture(const QPicture& picture, KGameCanvasAbstract* canvas = nullptr); 304 305 /** Constructor, creating with an empty picture */ 306 explicit KGameCanvasPicture(KGameCanvasAbstract* canvas = nullptr); 307 308 ~KGameCanvasPicture() override; 309 310 /** Returns the picture */ picture()311 QPicture picture() const { return m_picture; } 312 313 /** Sets the picture of the sprite */ 314 void setPicture(const QPicture& picture); 315 316 void paint(QPainter* p) override; 317 QRect rect() const override; 318 }; 319 320 /** 321 \class KGameCanvasPixmap kgamecanvas.h <KGameCanvas> 322 \brief A pixmap (sprite). 323 324 A KGameCanvasPixmap is a pixmap that can be put in the canvas. 325 326 \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. 327 */ 328 class KDEGAMESPRIVATE_EXPORT KGameCanvasPixmap : public KGameCanvasItem 329 { 330 private: 331 QPixmap m_pixmap; 332 333 public: 334 /** Constructor, specifying the pixmap to use */ 335 explicit KGameCanvasPixmap(const QPixmap& pixmap, KGameCanvasAbstract* canvas = nullptr); 336 337 /** Constructor, creating with an empty pixmap */ 338 explicit KGameCanvasPixmap(KGameCanvasAbstract* canvas = nullptr); 339 340 ~KGameCanvasPixmap() override; 341 342 /** Returns the pixmap */ pixmap()343 QPixmap pixmap() const { return m_pixmap; } 344 345 /** Sets the pixmap of the sprite */ 346 void setPixmap(const QPixmap& pixmap); 347 348 void paint(QPainter* p) override; 349 QRect rect() const override; layered()350 bool layered() const override { return false; } 351 }; 352 353 /** 354 \class KGameCanvasRenderedPixmap kgamecanvas.h <KGameCanvas> 355 \brief A sprite pixmap from KGameRenderer. 356 357 This canvas item behaves like KGameCanvasPixmap, but the pixmaps are served 358 from a KGameRenderer. This class exists solely for the purpose of porting 359 existing applications to KGameRenderer. 360 361 \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. 362 */ 363 class KDEGAMESPRIVATE_EXPORT KGameCanvasRenderedPixmap : public KGameCanvasPixmap, public KGameRendererClient 364 { 365 public: 366 KGameCanvasRenderedPixmap(KGameRenderer* renderer, const QString& spriteKey, KGameCanvasAbstract* canvas = nullptr); 367 protected: 368 void receivePixmap(const QPixmap& pixmap) override; 369 }; 370 371 /** 372 \class KGameCanvasTiledPixmap kgamecanvas.h <KGameCanvas> 373 \brief A tiled pixmap (brush). 374 375 A KGameCanvasTiledPixmap is a pixmap that can be put in the canvas. 376 377 \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. 378 */ 379 class KDEGAMESPRIVATE_EXPORT KGameCanvasTiledPixmap : public KGameCanvasItem 380 { 381 private: 382 QPixmap m_pixmap; 383 QSize m_size; 384 QPoint m_origin; 385 bool m_move_orig; 386 387 public: 388 /** Constructor, specifying the pixmap and the parameters to use */ 389 KGameCanvasTiledPixmap(const QPixmap& pixmap, const QSize &size, const QPoint &origin, 390 bool move_orig, KGameCanvasAbstract* canvas = nullptr); 391 392 /** Constructor, creating with an empty pixmap */ 393 explicit KGameCanvasTiledPixmap(KGameCanvasAbstract* canvas = nullptr); 394 395 ~KGameCanvasTiledPixmap() override; 396 397 /** Returns the pixmap */ pixmap()398 QPixmap pixmap() const { return m_pixmap; } 399 400 /** Sets the pixmap of the tile */ 401 void setPixmap(const QPixmap& pixmap); 402 403 /** Sets the size */ 404 void setSize(const QSize &size); 405 406 /** The origin */ origin()407 QPoint origin() const { return m_move_orig ? m_origin + pos() : m_origin; } 408 409 /** Sets the origin of the tiles */ 410 void setOrigin(const QPoint &size); 411 412 /** If the origin is moved */ moveOrigin()413 bool moveOrigin(){ return m_move_orig; } 414 415 /** Sets if the origin of the brush will be moved with the pixmap */ 416 void setMoveOrigin(bool move_orig); 417 418 void paint(QPainter* p) override; 419 QRect rect() const override; layered()420 bool layered() const override { return false; } 421 }; 422 423 424 /** 425 \class KGameCanvasRectangle kgamecanvas.h <KGameCanvas> 426 \brief A solid rectangle. 427 428 A KGameCanvasRectangle is a rectangle that can be put in the canvas. 429 430 \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. 431 */ 432 class KDEGAMESPRIVATE_EXPORT KGameCanvasRectangle : public KGameCanvasItem 433 { 434 private: 435 QColor m_color; 436 QSize m_size; 437 438 public: 439 /** Constructor, specifying the pixmap and the parameters to use */ 440 KGameCanvasRectangle(const QColor& color, const QSize &size, KGameCanvasAbstract* canvas = nullptr); 441 442 /** Constructor, creating with an empty pixmap */ 443 explicit KGameCanvasRectangle(KGameCanvasAbstract* canvas = nullptr); 444 445 ~KGameCanvasRectangle() override; 446 447 /** Returns the color */ color()448 QColor color() const { return m_color; } 449 450 /** Sets the color */ 451 void setColor(const QColor& color); 452 453 /** Sets the size */ 454 void setSize(const QSize &size); 455 456 void paint(QPainter* p) override; 457 QRect rect() const override; layered()458 bool layered() const override { return false; } 459 }; 460 461 /** 462 \class KGameCanvasText kgamecanvas.h <KGameCanvas> 463 \brief KGameCanvasText. 464 465 A KGameCanvasText is a text that can be put in the canvas. 466 467 \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. 468 */ 469 class KDEGAMESPRIVATE_EXPORT KGameCanvasText : public KGameCanvasItem 470 { 471 public: 472 /** Specifies the meaning of the x coordinate of the item. It can 473 refer to the start of the text, of the left, center, right of 474 the bounding rectangle. */ 475 enum HPos { 476 HStart, 477 HLeft, 478 HRight, 479 HCenter 480 }; 481 482 /** Specifies the meaning of the y coordinate of the item. It can 483 refer to the baseline of the text, of the top, center, bottom of 484 the bounding rectangle. */ 485 enum VPos { 486 VBaseline, 487 VTop, 488 VBottom, 489 VCenter 490 }; 491 492 private: 493 QString m_text; 494 QColor m_color; 495 QFont m_font; 496 HPos m_hpos; 497 VPos m_vpos; 498 QRect m_bounding_rect; 499 500 QPoint offsetToDrawPos() const; 501 void calcBoundingRect(); 502 503 public: 504 /** Constructor, specifying the text and the parameters to use */ 505 KGameCanvasText(const QString& text, const QColor& color, 506 const QFont& font, HPos hp, VPos vp, 507 KGameCanvasAbstract* canvas = nullptr); 508 509 /** Constructor, creating with an empty text */ 510 explicit KGameCanvasText(KGameCanvasAbstract* canvas = nullptr); 511 512 ~KGameCanvasText() override; 513 514 /** Returns the text */ text()515 QString text() const { return m_text; } 516 517 /** Sets the text */ 518 void setText(const QString& text); 519 520 /** Returns the color */ color()521 QColor color() const { return m_color; } 522 523 /** Sets the color */ 524 void setColor(const QColor& color); 525 526 /** Returns the font */ font()527 QFont font() const { return m_font; } 528 529 /** Sets the font */ 530 void setFont(const QFont& font); 531 532 /** Returns the horizontal positioning style */ hPositioning()533 HPos hPositioning() const { return m_hpos; } 534 535 /** Returns the vertical positioning style */ vPositioning()536 VPos vPositioning() const { return m_vpos; } 537 538 /** Sets the positioning style */ 539 void setPositioning(HPos hp, VPos vp); 540 541 void paint(QPainter* p) override; 542 QRect rect() const override; layered()543 bool layered() const override { return false; } 544 }; 545 546 /** 547 \class KGameCanvasWidget kgamecanvas.h <KGameCanvas> 548 \brief Container widget. 549 550 A KGameCanvasWidget is a widget that can contain many KGameCanvasItem (images, rectangles, lines, etc). 551 Portions of the widget are automatically redrawn to update the changes made to the items. 552 553 \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. 554 */ 555 class KDEGAMESPRIVATE_EXPORT KGameCanvasWidget : public QWidget, public KGameCanvasAbstract 556 { 557 Q_OBJECT 558 private: 559 friend class KGameCanvasItem; 560 friend class AnimationNotifier; 561 562 class KGameCanvasWidgetPrivate *priv; 563 564 void ensureAnimating() override; 565 void ensurePendingUpdate() override; 566 void invalidate(const QRect& r, bool translate = true) override; 567 void invalidate(const QRegion& r, bool translate = true) override; 568 569 void paintEvent(QPaintEvent *event) override; 570 571 private Q_SLOTS: 572 void processAnimations(); 573 void updateChanges(); 574 575 public: 576 /** The constructor */ 577 explicit KGameCanvasWidget(QWidget* parent = nullptr); 578 579 ~KGameCanvasWidget() override; 580 581 /** Set the delay of the animation, in milliseconds */ 582 void setAnimationDelay(int d); 583 584 /** Return the number of milliseconds from the creation of the canvas 585 (see also KGameCanvasItem::advance)*/ 586 int mSecs(); 587 588 /** returns 'this' */ 589 KGameCanvasWidget* topLevelCanvas() override; 590 591 /** @return 0 */ 592 QPoint canvasPosition() const override; 593 }; 594 595 /** 596 \class KGameCanvasAdapter kgamecanvas.h <KGameCanvas> 597 598 \brief A generic adapter for KGameCanvas 599 600 KGameCanvasAdapter can be used to draw content managed by KGameCanvas 601 inside systems which do not use KGameCanvas internally for their 602 rendering. 603 604 For example, suppose you have a widget CustomDisplay which paints itself 605 with direct QPainter calls in its paintEvent, and you want to add a 606 complex element to its rendering, which is best implemented via the KGameCanvas 607 abstractions. What you can do is to create a KGameCanvasAdapter subclass, 608 use it just like a KGameCanvasGroup, then call its render member function 609 to have a QPainter object draw it. 610 611 A KGameCanvas adapter notifies its parent using the pure virtual function 612 updateParent, which is called when the adapter content is invalidated. 613 614 \todo Support animations 615 616 \deprecated For new applications, use Qt's Graphics View framework or Qt Quick. 617 */ 618 class KDEGAMESPRIVATE_EXPORT KGameCanvasAdapter : public KGameCanvasAbstract 619 { 620 QRect m_child_rect; 621 bool m_child_rect_valid; 622 QRect m_invalidated_rect; 623 ensureAnimating()624 void ensureAnimating() override { } 625 void ensurePendingUpdate() override; 626 void invalidate(const QRect& r, bool translate = true) override; 627 void invalidate(const QRegion& r, bool translate = true) override; 628 629 QRect childRect(); 630 public: 631 /** Constructor */ 632 KGameCanvasAdapter(); 633 634 /** 635 * An adapter is not associated to any canvas, so this function 636 * simply returns 0. 637 */ topLevelCanvas()638 class KGameCanvasWidget* topLevelCanvas() override { return nullptr; } 639 640 /** 641 * The absolute position of the rendered content is not well 642 * defined for KGameCanvasAdapter. We assume that the adapter 643 * will be rendered at (0,0), and leave it to the user to perform 644 * the necessary adjustments, which will depend on the chosen 645 * rendering method. 646 * 647 * @return The point (0, 0). 648 */ canvasPosition()649 QPoint canvasPosition() const override { return QPoint(0, 0); } 650 651 /** 652 * Draw the items of the adapter using the specified painter. 653 * \param p The QPainter object to be used for rendering. 654 */ 655 virtual void render(QPainter* p); 656 657 /** 658 * Notify the parent that the adapter content inside \a rect needs 659 * to be redrawn. 660 * 661 * \a rect The bounding rectangle of the region that needs repainting. 662 */ 663 virtual void updateParent(const QRect& rect) = 0; 664 }; 665 666 #endif //__KGRGAMECANVAS_H__ 667