how to capture an imagelayer click using playn? - playn

I created an image and added to the imagelayer as I get the click event with this picture? Using the pointer it returns only the value of x and y that was clicked. I want to identify which was clicked on the image, as I do that?

Your question is not totally clear, but I believe you're asking if you can listen for click events directly on a layer, and you can:
ImageLayer layer = ...
layer.addListener(new Pointer.Adapter() {
public void onPointerStart(Pointer.Event event) {
// event.localX() and event.localY() are the mouse position in the layer's
// coordinate system; event.x() and event.y() are the mouse position
// in screen coordinates
}
});
It appears from the comments that you want to test whether a pixel is transparent in an image, and you want an example. Here you go:
Image image = ...;
int[] argb = new int[1];
// this will copy the ARGB value of the pixel at x y into the argb array
image.getRgb(x, y, 1, 1, argb, 0, 1);
// this will extract the alpha value from the pixel
int alpha = (argb[0] >> 24) & 0xFF;

Related

How to place a Plane geometry button on top of a row of cubes without displacing the button along z axis?

I have a grid of cubes and I need to show a button while hovering over a row. I have created the button with a plane geometry but while setting is position.y such that it stands right on top of the row, it displaces along the z axis and appears against another row at the back giving the wrong appearance. Please see the code below for the button and also a screenshot of the issue. The white button should appear right on top of the orange row.
I have tried to do what this post talks about. But inspite of all that, I am unable to fix it. Not sure why making the object high enough should affect the depth. I have not added any translation or rotation to it. Please help.
function createButtonForEachRow(numCols, width, offsetX, rowIndex, cubeSize , cubePadding)
{
var geometry = new THREE.PlaneGeometry( width, 1);
var material = new THREE.MeshBasicMaterial( {map: buttonTexture, side:THREE.DoubleSide } );
material.map.minFilter = THREE.LinearFilter;
var plane = new THREE.Mesh(geometry, material);
var referenceZPos = 1- (rowIndex * (cubeSize + cubePadding));
plane.position.x = offsetX + cubeSize + cubePadding * numCols + 3 ;
plane.position.y = cubeSize*3;
plane.position.z = referenceZPos;
// plane.rotation.x = 3 * Math.PI/2;
plane.visible = false;
return plane;
}
Screenshot
Creating 2 scenes and adding the button on the second scene worked. The link mentioned in the question actually worked. I had forgotten to set autoclear to false.

Looping ground tile as character moves in unity 2D

I am trying to create a ground tile that, once is off screen moves to the forward position in front of the other ground tile that is currently in the screen.
I have barely tried anything in code that would be even slightly useful to add to this question. Could someone point me in the right direction to be able to get this done so I don't have to just duplicate hundreds of tiles?
Thanks!
Attach this scrip on your Tileobject.
using UnityEngine;
public class SpawnTiles : MonoBehaviour {
private Material currentTile;
public float speed;
private float offset;
// Use this for initialization
void Start () {
currentTile = GetComponent<Renderer>().material;
}
// Update is called once per frame
void Update () {
offset += 0.001f;
currentTile.SetTextureOffset ("_MainTex", new Vector2 (offset * speed, 0));
}
}
Edit
This is what you want?
If YES, follow theses steps.
Create > 3D Object > Quad (Resize as you want)
Select your tile sprite:
Texture type = texture
Wrap mode = repeat
Now creat new Material: Create > Material
Select: Shader = Unlit/Texture
Texture select your previous texture.
Drag and drop this Material inside Quadobject.
Adjust tiles at inspector.
Result
Creat new scrip SpawnTiles and attach at Quadobject.
using UnityEngine;
public class SpawnTiles : MonoBehaviour {
private Material currentTile;
public float speed;
private float offset;
// Update is called once per frame
void Update () {
GetComponent<Renderer>().material.mainTextureOffset = new Vector2 (Time.time * speed, 0f);
}
}
Ajust tiles movement speed at inspector.
Finish rename Quadobject as you want.
If you want to only move the back tile to the front, you probably don't need it, but I still highly suggest looking into object pooling.
To detect if a camera can't see the tile, use this: Renderer.isVisible
To move the tile, if all the tiles are the same dimensions, you could just increase it's position.x by the amount you need.
I have found one solution using WorldPointToViewport().
Here is my script:
using UnityEngine;
using System.Collections;
public class groundTilingScript : MonoBehaviour {
Transform ground; //For reference to the transform
Camera cam; //Reference to Main Camera
float groundWidth; //The width of the transform, used for calculating current max x position of transform and next placement x position
private float nextXPos = 0.0f; //Store next x position in variable for easier reading
// Use this for initialization
void Start () {
//Set up References
ground = transform;
cam = Camera.main;
//Store Ground width (Width of the ground tile)
groundWidth = ground.GetComponent<Renderer> ().bounds.size.x;
}
// Update is called once per frame
void Update () {
//Create new Vector3 to be used in WorldToViewportPoint so it doesn't use the middle of the ground as reference
Vector3 boxRightPos = new Vector3 (ground.position.x + groundWidth/2, ground.position.y, ground.position.z);
//Store view Position of ground
Vector3 viewPos = cam.WorldToViewportPoint (boxRightPos);
//If the ground tile is left of camera viewport
if (viewPos.x < 0) {
//gameObject is offscreen, destroy it and re-instantiate it at new xPosition
float currentRightX = ground.position.x + groundWidth;
nextXPos = currentRightX + groundWidth;
Instantiate (gameObject, new Vector3 (nextXPos, ground.position.y, ground.position.z), ground.rotation);
Destroy (gameObject);
}
}
}
NOTE: I have to set up two ground tiles initially to give room for camera to go further than the ground tile. (One tile on screen, one off)
Again, this is just my attempt. I am completely open to criticism.

How to scale the contents of a QGraphicsView using the QPinchGesture?

I'm implementing an image viewer on an embedded platform. The hardware is a sort of tablet and has a touch screen as input device. The Qt version I'm using is 5.4.3.
The QGraphicsView is used to display a QGraphicsScene which contains a QGraphicsPixmapItem. The QGraphicsPixmapItem containts the pixmap to display.
The relevant part of the code is the following:
void MyGraphicsView::pinchTriggered(QPinchGesture *gesture)
{
QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
if (changeFlags & QPinchGesture::ScaleFactorChanged) {
currentStepScaleFactor = gesture->totalScaleFactor();
}
if (gesture->state() == Qt::GestureFinished) {
scaleFactor *= currentStepScaleFactor;
currentStepScaleFactor = 1;
return;
}
// Compute the scale factor based on the current pinch level
qreal sxy = scaleFactor * currentStepScaleFactor;
// Get the pointer to the currently displayed picture
QList<QGraphicsItem *> listOfItems = items();
QGraphicsItem* item = listOfItems.at(0);
// Scale the picture
item.setScale(sxy);
// Adapt the scene to the scaled picture
setSceneRect(scene()->itemsBoundingRect());
}
As result of the pinch, the pixmap is scaled starting from the top-left corner of the view.
How to scale the pixmap respect to the center of the QPinchGesture?
From The Docs
The item is scaled around its transform origin point, which by default is (0, 0). You can select a different transformation origin by calling setTransformOriginPoint().
That function takes in a QPoint so you would need to find out your centre point first then set the origin point.
void QGraphicsItem::setTransformOriginPoint(const QPointF & origin)

QPainter mirror image not working

I have a program which functions similar to paint, and I have a change request as such:
Add a new function named mirror mode, in a mirror mode, the canvas is divided by left and right half. All the pictures that are drawn in one of the half should be mirrored to the opposite half.
I have added code such that the mirrored portion appears; however the original image does not appear to be drawn by QPainter. Is there a simple thing I'm missing to get QPainter to show both the mirrored image and drawn image. The relevant source code is as follows :
//
void ImageArea::paintEvent(QPaintEvent *event)
{
QPainter *painter = new QPainter();
painter->begin(this);
QRect *rect = new QRect(event->rect());
painter->setBrush(QBrush(QPixmap(":media/textures/transparent.jpg")));
painter->drawRect(0, 0,
mImage->rect().right() - 1,
mImage->rect().bottom() - 1);
painter->drawImage(event->rect(), *mImage, event->rect());
painter->setPen(Qt::NoPen);
painter->setBrush(QBrush(Qt::black));
painter->drawRect(QRect(mImage->rect().right(),
mImage->rect().bottom(), 6, 6));
painter->drawImage(event->rect(), *mImage, event->rect());
painter->end();
painter->begin(this);
QImage tmp(mImage->mirrored(true,false));
painter->drawImage(0, 0, tmp);
painter->end();
}

Zooming in/out on a mouser point ?

As seen in the pictures.
I have QWidget inside a QScrollArea.
QWidget act as a render widget for cell image and some vector based contour data.
User can performe zoom in/out and what simply happens is, it changes the QPainters scale and change the size of QWidget size accordinly.
Now I want to perform the zooming in/out on the point under the mouse. (like zooming action in GIMP).
How to calculate the new positions of the scrollbars according to the zoom level ?
Is it better to implement this using transformations without using a scrollarea?
One solution could be to derive a new class from QScrollArea and reimplementing wheelEvent for example so that zooming is performed with the mouse wheel and at the current mouse cursor position.
This method works by adjusting scroll bar positions accordingly to reflect the new zoom level. This means as long as there is no visible scroll bar, zooming does not take place under mouse cursor position. This is the behavior of most image viewer applications.
void wheelEvent(QWheelEvent* e) {
double OldScale = ... // Get old scale factor
double NewScale = ... // Set new scale, use QWheelEvent...
QPointF ScrollbarPos = QPointF(horizontalScrollBar()->value(), verticalScrollBar()->value());
QPointF DeltaToPos = e->posF() / OldScale - widget()->pos() / OldScale;
QPointF Delta = DeltaToPos * NewScale - DeltaToPos * OldScale;
widget()->resize(/* Resize according to new scale factor */);
horizontalScrollBar()->setValue(ScrollbarPos.x() + Delta.x());
verticalScrollBar()->setValue(ScrollbarPos.y() + Delta.y());
}
Will void QScrollArea::ensureVisible(int x, int y, int xmargin = 50, int ymargin = 50) do what you need?
You need to pick up the wheelEvent() on the QWidget, get the event.pos() and pass it into the QscrollArea.ensureVisible(), right after scaling your QWidget.
def wheelEvent(self, event):
self.setFixedSize(newWidth, newHeight)
self.parent().ensureVisible(event.pos())
That should more or less produce what you want.

Resources