SpriteKit - Selecting Node After Rotation - xcode

An SKSpriteNode, named “leaf” is added as a child to another SKSpriteNode, named “allObjects”.
allObjects is set to be the same width and height as the SKView.
I drag the leaf to a location on allObjects and click a distinctive part of its tip and using println get the following in the console.
touchBegan, touch.locationInNode(allObjects): (621.5, 156.75)
touchesEnded, touch.locationInNode: (621.5, 156.75)
touchesEnded, Leaf location: (695.375, 83.25)
touchesEnded, nodeAtPoint(location).name: Optional("leaf")
So far, so good. I can drag the leaf as much as I like at this point with no problem. The important part to note is that the nodeAtPoint is, as expected, ‘leaf’.
However, if I then rotate allObjects, like this:
var rotate = SKAction()
rotate = SKAction.rotateByAngle(0.4, duration: 0)
allObjects.runAction(rotate)
… And then click in the same location on the leaf (visually in IOS Simulator), I get the following in the console. I’m confused as to why I have rotated allObjects and clicked in the same location (and get the same co-ordinates) I am no longer selecting the leaf but missing it by a wide margin (nodeAtPoint shows I am hitting the background).
touchBegan, touch.locationInNode(allObjects): (620.813842773438,
156.470306396484)
touchesEnded, touch.locationInNode: (620.813842773438, 156.470306396484)
touchesEnded, Leaf location: (695.375, 83.25)
touchesEnded, nodeAtPoint(location).name: Optional("allObjects")
Can anyone help?

The node and coordinates used in the locationInNode and nodeAtPoint need to be consistent. In this case, the point returned by locationInNode is in allObjects coordinates while the nodeAtPoint call (i.e., self.nodeAtPoint) requires a point in scene coordinates. To resolve this, you can either replace
nodeAtPoint(location)
with
allObjects.nodeAtPoint(location)
or replace
let location = touch.locationInNode(allObjects)
with this
let location = touch.locationInNode(self)

Related

SkSpriteNodes are stacking on top of each other

I am writing a soccer app which I use an SKScene to display my players and so on. My player nodes are set up with an .sks but I want to add more nodes to the scene when I press a button. The code below is how I add my nodes to the scene and they are displayed,
I am able to drag all the nodes around but when these nodes added in the above function collide with any of the nodes they stick together Like in the image below. The zposition of the player node is 3. I have also to the scene to ignoreSiblingOrder.I have tried implementing physics bodies but that doesn't solve the problem, I have tried changing the zPosition, I have tried adding the nodes under different parents. The current parent of all the nodes is the SKScene.The nodes added in the .sks file do not stack on top each other this only affects the nodes which I have programmatically added. Any ideas on how to stop them from sticking or stacking on top each other?
func addDiagonal(image : UIImage, name : String){
arrowNode = SKSpriteNode()
arrowNode!.texture = SKTexture(image: image)
arrowNode!.size = CGSize(width: 65, height: 65)
arrowNode!.position = CGPoint(x: 153, y: 267)
arrowNode!.zPosition = 4
arrowNode!.name = name
myTrainigArr?.append(arrowNode!)
self.addChild(arrowNode!)
}
This is what happens when the nodes collide or touch each other

How to change the source anchor starting position in JsPlumb?

I'm developing an app using jsPlumb. Currently, if I create a shape, it puts the shape in the top left corner of the canvas. And If I connect from source to target point, it is working.
Now, I want to create the shape on the position where I right clicked and connect from source to target. I'm able to create the shape in the position where i right clicked.
But, if I drag from source to target, the source anchor is not starting from the source. Instead, it starts from the top left corner. In the screenshot below, I want to drag from 'Project' to 'No status' shape.
One more thing is, if I drag the 'Project' shape, endpoint is starting from source correctly.
I have figured the problem. Earlier, ,the if block (1) in the code was below the code (2). That's why even thought the shape moved to the new location, the starting location of the anchor didnt move. As soon as I move the if block(1) above (2), jsPlumb understands the shape's location as well as the anchor's starting point location.
So, if you are moving the shape, you should do it before you tell the shapes location to Jsplumb.
if (!!shape.location) { ------------------------------------> 1)
domEl.style.left = shape.location.left + 'px';
domEl.style.top = shape.location.top + 'px';
}
this.jsPlumbInstance.draggable(domEl, {
// to contain the shape within the canvas
// containment: true
});
this.jsPlumbInstance.makeSource(domEl, { ----------------------2)
filter: '.cp',
anchor: ['AutoDefault'],
connectorStyle: {
stroke: '#181919',
strokeWidth: 2,
outlineStroke: 'transparent',
outlineWidth: 4
}
});

Trouble with LibGDX resetting origin on an already rotated actor

If I do:
actor.setOrigin(0, 0);
actor.setRotation(45);
actor.setOrigin(actor.getWidth() / 2, actor.getHeight() / 2);
It appears that on the last setOrigin call, the actor gets repositioned to the location it would've been if actor.setRotation(45) would have been called after its latest origin was set.
What do I do to make it so that the latest origin of the actor is only used for future "scale" and "rotation" actions?
Okay so i looked in the source code of libgdx, and i'll tell you the short answer.
Basically when you set the origin or the rotation, you just change a variable named "originx", "originy" and "rotation". So every call to setOrigin will overwrite the values set in previous calls.
And every time you draw the actor, it recalculates the bounds using the current variable.
To be clear, setOrigin looks like this :
public void setOrigin (float originX, float originY) {
this.originX = originX;
this.originY = originY;
}
So the precedent setOrigin is lost.
The reposition of the actor itself in your case does not change, but the position of the displayed sprite or texture will change.
It is calculated in this order:
Position -> Origin -> Scale -> Rotation
See: Sprite.java (method: "getVertices ()")
When you change the Origin point of an already rotated element, the point in the plane around which the rotation occurs changes and the sprite will be drawn in a different place (the actor's position in this case does not change).

Change coordinates of view on Titanium

An animation in titanium doesn't change the coordinates of a view. Then what is the best way to change the coordinates (for example top) of a view and then keep track of where it is.
var t1 = Ti.UI.create2DMatrix();
var a1 = Ti.UI.createAnimation();
t1 = t1.translate(0, 10);//Translate on y coordinate
a1.transform = t1;
a1.duration = 800;
view.animate(a1); // Move the view, but the top property keeps the same
Thanks, and sorry if it is a silly question!!
animate() method does not change any coordinates for reason.
top, left, right, bottom are needed for layout mechanisms.
The easiest way to change the top coordinate is to set it like this.
$.getView().applyProperties({
top: newTopValue
});
And after you set it, it will automatically trigger layout re-calculation

Convert a given point from the window’s base coordinate system to the screen coordinate system

I am trying to figure out the way to convert a given point from the window’s base coordinate system to the screen coordinate system. I mean something like - (NSPoint)convertBaseToScreen:(NSPoint)point.
But I want it from quartz/carbon.
I have CGContextRef and its Bounds with me. But the bounds are with respect to Window to which CGContextRef belongs. For Example, if window is at location (100, 100, 50, 50) with respect to screen the contextRef for window would be (0,0, 50, 50). i.e. I am at location (0,0) but actually on screen I am at (100,100). I
Any suggestion are appreciated.
Thank you.
The window maintains its own position in global screen space and the compositor knows how to put that window's image at the correct location in screen space. The context itself, however doesn't have a location.
Quartz Compositor knows where the window is positioned on the screen, but Quartz 2D doesn't know anything more than how big the area it is supposed to draw in is. It has no idea where Quartz Compositor is going to put the drawing once it is done.
Similarly, when putting together the contents of a window, the frameworks provide the view system. The view system allows the OS to create contexts for drawing individual parts of a window and manages the placement of the results of drawing in those views, usually by manipulating the context's transform, or by creating temporary offscreen contexts. The context itself, however, doesn't know where the final graphic is going to be rendered.
I'm not sure if you can use directly CGContextRef, you need window or view reference or something like do the conversion.
The code I use does the opposite convert mouse coordinates from global (screen) to view local and it goes something like this:
Point mouseLoc; // point you want to convert to global coordinates
HIPoint where; // final coordinates
PixMapHandle portPixMap;
// portpixmap is needed to get correct offset otherwise y coord off at least by menu bar height
portPixMap = portPixMap = GetPortPixMap( GetWindowPort( GetControlOwner( view ) ) );
QDGlobalToLocalPoint(GetWindowPort( GetControlOwner( view ), &mouseLoc);
where.x = mouseLoc.h - (**portPixMap).bounds.left;
where.y = mouseLoc.v - (**portPixMap).bounds.top;
HIViewConvertPoint( &where, NULL, view );
so I guess the opposite is needed for you (haven't tested if it actually works):
void convert_point_to_screen(HIView view, HIPoint *point)
{
Point point; // used for QD calls
PixMapHandle portPixMap = GetPortPixMap( GetWindowPort( GetControlOwner( view ) ) );
HIViewConvertPoint( &where, view, NULL ); // view local to window local coordtinates
point.h = where->x + (**portPixMap).bounds.left;
point.w = where->y + (**portPixMap).bounds.top;
QDLocalToGlobalPoint(GetWindowPort( GetControlOwner( view ), &point);
// convert Point to HIPoint
where->x = point.h;
where->y = point.v;
}

Resources