Cocos2d-x - how to set part of CCLayer transparent? - c++

I'm newbie in cocos2d-x and I need your help.
I need to make transparent a touched portion of the layer.
How to make a portion of the layer transparent? I had thought to use ССClippingNode, but I'm not find examples or docs.
I use C++. Thanks.

In TestCpp, project that was added to all cocos2d-x version, you can find examples of CCClipingNode.
If you want to hide part of CCNode(for example "layer") using CCClipingNode, you should add your layer to CCClipingNode.
This is the example that you can paste in the HelloWorld init:
bool HelloWorld::init()
{
if ( !CCLayer::init() )
{
return false;
}
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
addChild(CCLayerColor::create(ccc4(122, 144, 0, 255), visibleSize.width, visibleSize.height));
//this is the layer that we want to "cut"
CCLayer *layer = CCLayer::create();
CCSprite* pSprite = CCSprite::create("HelloWorld.png");
pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
layer->addChild(pSprite, 0);
//we need to create a ccnode, which will be a stencil for ccclipingnode, draw node is a good choice for that
CCDrawNode * stecil = CCDrawNode::create();
stecil->drawDot(ccp(visibleSize.width/2 + origin.x - 100, visibleSize.height/2 + origin.y), 30, ccc4f(0, 0, 0, 255));
stecil->drawSegment(ccp(0, 0), ccp(visibleSize.width, visibleSize.height), 20, ccc4f(0, 0, 0, 255));
//CCClipingNode show the intersection of stencil and theirs children
CCClippingNode *cliper = CCClippingNode::create(stecil);
//you want to hide intersection so we setInverted to true
cliper->setInverted(true);
cliper->addChild(layer);
addChild(cliper);
return true;
}

Related

Qt- Moving a QGraphicsItem causes artifacts.Leaves trailes behind

When i move a QGraphicsItem, weird artifacts stay behind.Some parts of the item dont render,other render...
In the note.cpp i have a shape
QPainterPath Note::shape()const{
QPainterPath path;
// path.addRect(0, 0, 50, 20);
path.moveTo(0, -80.0);
path.lineTo(0.0, 80.0);
path.lineTo(80.0, 0.0);
// path.lineTo(75.0, -30.0);
path.closeSubpath();
return path;
}
In the paint function
QPointF *points = new QPointF[3];
points[0] = QPointF(0,-80);
points[1] = QPointF(0,80);
points[2] = QPointF(80,0);
painter->drawPolygon(points,3);
The first picture shows that all are fine when i start the app.
The second picture shows that when i move a triangle with the mouse, it gets sliced.Other times it leaves some trails and doesn't render all parts of the triangle
Here is the github link for the project.
Github link
To reproduce, just move a triangle.
QGraphicsItem for efficiency only repaint the section that returns boundingRect() method, in your case QRect(0, 0, 80, 80) only returns half the necessary area since the coordinate (0, -80) is outside the boundingRect. The solution is:
QRectF Note::boundingRect() const {
return QRectF(0, -80, 80, 160) ;
// or
// return shape().boundingRect();
}

In QGraphicscene why Enlarging widget restricted after some size? [duplicate]

I have added a widget to a graphic scene QGraphicScene through a QGraphicsProxyWidget. To move it I have set QGraphicsRectitem as its parent. The widget is resized with the use of a sizegrip.
The first time I create an object I can enlarge it upto some dimension. The second time I can enlarge it less than the first one. The third time less than the second one and so on.
It seems to me that it behaves randomly. Why is this happening?
Here is the code:
void GraphicsView::dropEvent(QDropEvent *event)// subclass of QGraphicsView
{
if(event->mimeData()->text() == "Dial")
{
auto *dial= new Dial; // The widget
auto *handle = new QGraphicsRectItem(QRect(event->pos().x(),event->pos().y(), 120, 120)); // Created to move and select on scene
auto *proxy = new QGraphicsProxyWidget(handle); // Adding the widget through the proxy
dial->setGeometry(event->pos().x()+10,event->pos().y()+10, 100, 100);
proxy->setWidget(dial);
QSizeGrip * sizeGrip = new QSizeGrip(dial);
QHBoxLayout *layout = new QHBoxLayout(dial);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(sizeGrip, 0, Qt::AlignRight | Qt::AlignBottom);
handle->setPen(QPen(Qt::transparent));
handle->setBrush(Qt::gray);
handle->setFlags(QGraphicsItem::ItemIsMovable |
QGraphicsItem::ItemIsSelectable);
scene->addItem(handle); // adding to scene
connect(dial, &Dial::sizeChanged, [dial, handle](){ handle->setRect(dial->geometry().adjusted(-10, -10, 10, 10));});
} }
I cannot enlarge the widget more than that, what is shown in the image.
Your Dial can't be resized past the GraphicView's right (horizonally) and bottom (vertically) edges. If you make the scene big enough, say 2000x2000 (setSceneRect(2000, 2000);), scrollbars will appear. If you move the scrollbars manually, you will be able to enlarge your widgets more.
You could also experiment with automatic scrollbar movement by changing the lambda function like this:
connect(dial, &Dial::sizeChanged, [this, dial, handle](){
handle->setRect(dial->geometry().adjusted(-10, -10, 10, 10));
int dx = handle->rect().bottomRight().x() > viewport()->rect().bottomRight().x();
int dy = handle->rect().bottomRight().y() > viewport()->rect().bottomRight().y();
if (dx > 0) {
horizontalScrollBar()->setValue(horizontalScrollBar()->value() + dx);
}
if (dy > 0) {
verticalScrollBar()->setValue(verticalScrollBar()->value() + dy);
}
});
Please note, that although this code works, is is very cumbersome. However, it could give you an idea how to start.

QPaintedTextureImage in Qt3D (Qt 5.8)

I want to create an entity with Qt3D that has a custom image as texture. I came across the QPaintedTextureImage (link leads to Qt 5.9 version for details. Here ist doc for 5.8), which can be written with a QPainter but I don't understand how.
First, this is how I imagine the entity could look like:
[EDIT]: code is edited and works now!
planeEntity = new Qt3DCore::QEntity(rootEntity);
planeMesh = new Qt3DExtras::QPlaneMesh;
planeMesh->setWidth(2);
planeMesh->setHeight(2);
image = new TextureImage; //see below
image->setSize(QSize(100,100));
painter = new QPainter;
image->paint(painter)
planeMaterial = new Qt3DExtras::QDiffuseMapMaterial;
planeMaterial->diffuse()->addTextureImage(image);
planeEntity->addComponent(planeMesh);
planeEntity->addComponent(planeMaterial);
TextureImage is the subclassed QPaintedTextureImage with paint function:
class TextureImage : public Qt3DRender::QPaintedTextureImage
{
public:
void paint(QPainter* painter);
};
What does the QPainter, passed to paint function, need to do in the implementation of paint if I just want to draw a big circle to the planeEntity?
[Edit] Implementation:
void TextureImage::paint(QPainter* painter)
{
//hardcoded values because there was no device()->width/heigth
painter->fillRect(0, 0, 100, 100, QColor(255, 255, 255));
/* Set pen and brush to whatever you want. */
painter->setPen(QPen(QBrush(QColor(255, 0, 255)) ,10));
painter->setBrush(QColor(0, 0, 255));
/*
* Draw a circle (or an ellipse -- the outcome depends very much on
* the aspect ratio of the bounding rectangle amongst other things).
*/
painter->drawEllipse(0, 0, 100, 100);
}
The short answer is... use QPainter exactly the same way you would normally.
void TextureImage::paint (QPainter* painter)
{
int w = painter->device()->width();
int h = painter->device()->height();
/* Clear to white. */
painter->fillRect(0, 0, w, h, QColor(255, 255, 255));
/* Set pen and brush to whatever you want. */
painter->setPen(QPen(QBrush(QColor(0, 0, 0)) ,10));
painter->setBrush(QColor(0, 0, 255));
/*
* Draw a circle (or an ellipse -- the outcome depends very much on
* the aspect ratio of the bounding rectangle amongst other things).
*/
painter->drawEllipse(0, 0, w, h);
}
However, note that you really shouldn't invoke the paint method directly. Instead use update which will cause Qt to schedule a repaint, initialize a QPainter and invoke your overridden paint method with a pointer to that painter.
It might be simpler to dynamically load the image you need in QML.
I had to do it not so long ago and opened a question on SO for it:
Qt3D dynamic texture

Drawing Rectangle in Cocos2dx

I am having trouble drawing a basic white rectangle using the Cocos2dx library in the iOS environment. I have looked at a couple of other implementations for guidance.
http://discuss.cocos2d-x.org/t/draw-rectangle-with-drawrect-in-cocos2dx-not-working/14836/3
Cocos2d-x: How can I draw a resizing rectangle?
It basically looks like I need to use the class method of DrawNode::create() to make the node, then establish the vertices like in openGL, then draw it with the DrawNode->drawPolygon method and add the child node to the scene with the addChild method of the cocos2d::Layer subclass.
Here is my code.
bool JFScene::init()
{
if ( !Layer::init() )
{
return false;
}
auto visibleSize = Director::getInstance()->getVisibleSize();
Vec2 origin = Director::getInstance()->getVisibleOrigin();
auto closeItem = MenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
CC_CALLBACK_1(JFScene::menuCloseCallback, this));
closeItem->setScale(2.0);
closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 ,
origin.y + closeItem->getContentSize().height/2));
auto menu = Menu::create(closeItem, NULL);
menu->setPosition(Vec2::ZERO);
this->addChild(menu, 1);
auto CButton = Sprite::create("CButton.png");
CButton->setPosition(
Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)
);
this->addChild(CButton, 1);
auto rectNode = DrawNode::create();
Vec2 vertices[4] = {
Vec2(-50, -50),
Vec2(50, -50),
Vec2(50, 50),
Vec2(-50, 50)
};
rectNode->drawPolygon(vertices, 4, Color4F::WHITE, 1, Color4F::WHITE);
this->addChild(rectNode);
return true;
}
The odd thing is that the CButton Node appears to render when I run it on my iPhone 5s as well as the close item that was included in the default file, but the white rectangle I am trying to draw does not render. Any ideas why?
You want to draw a rectangle... Look at this code snippet:
auto rectNode = DrawNode::create();
Vec2 rectangle[4];
rectangle[0] = Vec2(-50, -50);
rectangle[1] = Vec2(50, -50);
rectangle[2] = Vec2(50, 50);
rectangle[3] = Vec2(-50, 50);
Color4F white(1, 1, 1, 1);
rectNode->drawPolygon(rectangle, 4, white, 1, white);
this->addChild(rectNode);
I hope it works for you.
Reference: cocso2d-x forum
Besides, I recommend you take a look at this similar question if you didn't.

Setting swipe event to a sprite

I'm assinging a swipe event to a cocos2dx sprite but basically the problem is the event is assigned to the whole screen. I want it to be assigned only to the single sprite. Here is my code:
rect = Sprite::create();
rect->setTextureRect(Rect(0, 0, 180, 80));
// ekranın y ekseninde ortası | visibleSize.height / 2 + origin.y
rect->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height + 80));
auto grad = LayerGradient::create(Color4B(255, 255, 38, 255), Color4B(199, 173, 68, 255));
grad->changeHeight(rect->getContentSize().height);
grad->changeWidth(rect->getContentSize().width);
//grad->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y));
//grad->addChild(rect);
rect->addChild(grad);
this->addChild(rect);
auto listener = EventListenerTouchOneByOne::create();
listener->onTouchBegan = CC_CALLBACK_2(GameScene::onTouchBegan, this);
listener->onTouchMoved = CC_CALLBACK_2(GameScene::onTouchMoved, this);
listener->onTouchEnded = CC_CALLBACK_2(GameScene::onTouchEnded, this);
listener->onTouchCancelled = CC_CALLBACK_2(GameScene::onTouchCancelled, this);
listener->setSwallowTouches(true);
this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, rect);
A touch event is usually triggered when the player touches the screen. The best way to implement a listener on a sprite would be by sub-classing it:
http://www.cocos2d-x.org/wiki/How_To_Subclass_Sprite_And_Add_Event_Listeners
You can later check the collision of the touch within the sprite listener event (on Touch Began) and then perform your function