Is it possible to use setTextureRect on CCAnimation in Cocos2d (cocos2d-x)? - cocos2d-iphone

I am using setTextureRecton CCSprite each frame, so it looks like it is being masked, etc..
I wanted to do the samething for a sprite with an animation, but it doesn't work, animation just disappears... Isn't it possible?

It is possible I think.
CCAnimation::addSpriteFrame(CCSpriteFrame *pFrame)
is used to add frame to animation manually.
And you can create the CCSpriteFrame by
CCSpriteFrame::createWithTexture(CCTexture2D* pobTexture, const CCRect& rect)
or
CCSpriteFrame* create(const char* filename, const CCRect& rect)
It should be the same as you create a CCSprite.

Related

QPainter keep previous drawings

This is my first time using Qt and I have to make a MSPaint equivalent with Qt. I am however having trouble with painting my lines. I can currently draw a line by clicking somewhere on the screen and releasing somewhere else, however when I draw a second line the previous line is erased. How could I keep the previously painted items when painting another item?
void Canvas::paintEvent(QPaintEvent *pe){
QWidget::paintEvent(pe);
QPainter p(this);
p.drawPicture(0,0,pic);
}
void Canvas::mousePressEvent(QMouseEvent *mp){
start = mp->pos();
}
void Canvas::mouseReleaseEvent(QMouseEvent *mr){
end = mr->pos();
addline();
}
void Canvas::addline()Q_DECL_OVERRIDE{
QPainter p(&pic);
p.drawLine(start,end);
p.end();
this->update();
}
Canvas is a class that derives QWidget, it has 2 QPoint attributes start and end.
Class body:
class Canvas : public QWidget{
Q_OBJECT
private:
QPoint start;
QPoint end;
QPicture pic;
public:
Canvas(){paint = false;setAttribute(Qt::WA_StaticContents);}
void addline();
protected:
void paintEvent(QPaintEvent *);
void mousePressEvent( QMouseEvent * );
//void mouseMoveEvent( QMouseEvent * );
void mouseReleaseEvent( QMouseEvent * );
};
QPicture records QPainter commands. Also from its documentation you can read this:
Note that the list of painter commands is reset on each call to the
QPainter::begin() function.
And the QPainter constructor with a paint device does call begin(). So each time the old recorded commands are deleted.
It may sound tempting to use it, since it does say a few good things, for example, that it is resolution independent, but this is not how drawing applications work in reality. Switch to a QPixmap and your drawings will persist.
Also, don't forget to initialize the pixmap, because by default it will be empty and you will not be able to draw on it.
Canvas() : pic(width,height) {...}
Furthermore, if you would like the introduce the concept of brushes as in artistic brushes and not QBrush, you might want to look at this approach to draw the line.
EDIT: Note that you should be able to prevent QPicture from losing its content by not calling begin() on it more than once. If you create a painter, dedicated to only drawing on it at class scope, and call begin in the constructor, different recorded drawing operations should persist. But as their number increases it will take more and more time to draw the QPicture to your widget. You could come around that by using both a QPicture and a QPixmap, and draw to both, use the picture to record the actions and the pixmap to avoid continuously redrawing the picture, even though you will do double the work it will still be more efficient, while you still retain the possibility to use the picture to re-rasterize in a different resolution or save the drawing history. But I doubt QPicture will do well as your drawing application begins to take shape of an actual drawing application, for example when you start using pixmap brushe stencils and such.

Determine which pixels of QImage were changed while painting on it with QPainter

I have class Paintable that is able to paint itself with QPainter provided as an argument:
class Paintable
{
public:
virtual void paint(QPainter*) = 0;
};
Instances of this class are being painted on a single QImage:
QImage paint(const std::vector<Paintable*>& paintables) {
QImage result;
QPainter p(&result);
for(int i = 0; i < paintables.size(); ++i) {
paintables[i]->paint(&p);
}
return result;
}
What I want to achieve is that function paint could also form a matrix of size equal to result image size in which each cell contains a pointer to Paintable which has drawn corresponding pixel in result image (something like z-buffer).
It could be achieved easily if draw methods of QPainter somehow let me know of which pixels of QPaintDevice were changed during last draw operation. Any ideas of how to do it? Should I create class derived from QPaintDevice or QPaintEngine?
I am using Qt 4.6.4.
Thanks.
Perhaps instead of having all your Paintables paint onto the same QImage, have each one paint onto a temporary blank QImage -- i.e. a QImage with all pixels set to RGBA=(0,0,0,0). That way, after a given Paintable's paint() method returns, you know that any pixels in the QImage that are now non-transparent must have been painted by that Paintable object. You could then update your own z-buffer like data-structure based on that information, and then drawImage() the QImage over to a separate "accumulation QImage" (assuming you also want the composited result), clear the temporary QImage again, and repeat as necessary.

Ignore drawForeground() from the scene on the 2nd graphicsview in qt

I have my own QGraphicsScene and two QGraphicView’s. In the QGraphicsScene I use the
drawForeground(QPainter *painter, const QRectF &rect)
function to draw a grid. Now I want the grid only to be visible in the first, but not in the second view…is this possible?
The QGraphicsView is a window into a world (the QGraphicsScene). What you're asking would be like saying that it's raining when I look outside my windows, but can I have it only rain when I look through one of them?!
However, you can change the curtains(!), so override the function of the QGraphicsView, rather than the QGraphicsScene. I suggest using this: -
QGraphicsView::drawForeground(QPainter *, const QRectF &);
Apply this just to the view you want to change. With two views, you'll need a flag to set which of the views you want to apply this to. For example: -
void MyGraphicsView::drawForeground(QPainter* painter, const QRectF& rect)
{
QGrahicsView::drawForeground(painter, rect);
if(m_bDrawGrid)
DrawGrid();
}

QGraphicsPixmapItem

QGraphicsPixmapItem, like QGraphicsItem, has a method update(x0, y0, width, height), in order to redraw a pixmap only partly on a QGraphicsScene. Calling this will schedule a paint() (in Qt's event loop) on the QGraphicsItem, and after this paint() is executed the boundingbox (x,y,width,height) will be redrawn to the QGraphcisScene.
The unfortunate part is that there is no way to schedule the paint-event with a boundingbox, meaning that QGraphicsPixmapItem::paint() is forced to repaint the whole QPixmap, therefore reimplementing this paint()-method in a subclass gives no way to only partly update the QPixmap, therefore making a small (local) update to the QPixmap unacceptably slow.
Such a subclass would look something like this:
class LocallyUdatablePixmapItem : public QGraphicsPixmapItem {
private:
QImage ℑ
public:
LocallyUdatablePixmapItem(QImage &img) : QGraphicsPixmapItem(), image(img) {}
paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QStyle *widget) {
//locall update, unfortunately without a boundig box :( therefore -> slow
}
};
Another option would be to keep the 'internal QPixmap' of the QGraphicsPixmapItem, and draw the QImage to it partly, like this:
//some initialization of variables
QGraphicsScene scene = ...;
QImage img = ...; //some image data that I wish to manipulate from time to time
QPixmap pixmap = QPixmap::fromImage(this->shown);
QPainter painter = new QPainter(&this->pixmap);
QGraphicsPixmapItem item = this->addPixmap(this->pixmap);
item->setPixmap(this->pixmap);
//this should not matter, but actually it does, as I will explain shortly
//delete painter;
//painter = new QPainter(item->pixmap());
//For some reason I decide to update (manimulate) img within a small boundigbox
int x0, y0, width, height; //bounding box, assume they are set to whatever is appropriate for the previous update
painter->drawImage (x0, y0, img, x0, y0, width, height);
//now the pixmap is updated, unfortunately the item is not. This does not affect it:
item->update(x0, y0, width, height);
//nor does this:
item->update();
//but this, which makes the whole thing slow, does:
item.setPixmap(&pixmap);
Given I that I needed to set the pixmap to fix it, I assumed it was somehow not set in the initialization, therefore uncommenting the mentioned lines before seemed like a nice idea. Unfortunately, the drawImage() call then segfaults into:
QPaintDevice: Cannot destroy paint device that is being painted
I would like to have an alternative to the "item.setPixmap(&pixmap);", which does not redraw the whole thing, but does work nicely. Any input is very well appreciated :)
Before I propose a solution, a few thoughts:
First, the Graphics View framework is intended to be a solution for displaying many graphic objects, so one large image isn't really that fitting. Of course, I realize your example is probably just a contrived one, so this point might not really apply. Second, since the framework is very transform-centric, it might not make sense to only redraw parts of a QGraphicsItem unless all the transforms are identity, there is no scrolling, etc.
Anyways, if you only want to draw part of a QGraphicsItem, you could simply store the rect that needs to be updated, and access it from inside your paint() method. For example:
CustomItem::setPaintRect(const QRectF &rect)
{
paintRect = rect;
update();
}
CustomItem::paint(QPainter *painter /* etc. */)
{
painter->fillRect(paintRect, brush);
}

How to draw an 'x' in Qt?

To draw an ellipse in Qt, we can simply go QGraphicsScene->addEllipse();
Is there an equivalent method to draw an 'x'? And when redrawing a scene, how would you delete said 'x' (say, to move it)?
Use QGraphicsScene::addSimpleText(const QString &text, const QFont &font=QFont()) to draw the letter "x".