Handling Multi-Touch events in Emscripten in Safari - multi-touch

I am using Emscripten to get a number of C++ games running under HTML5. The client requires that these games also run in a mobile web browser, they do not want to make a native app.
The games require me to properly handle multitouch events - if the user applies three fingers to the screen, I have to react accordingly to all three fingers. However, I'm seeing an issue when testing on Safari on an iPad Mini, and I expect it happens elsewhere as well (though so far I'm not seeing it on Android).
What I'm finding is that when a touch callback is hit, for instance if I set a callback via emscripten_set_touchend_callback, then whenever a touchend event occurs, that callback gets hit with all active touchpoints included in the EmscriptenTouchEvent. As such, I don't know which touchpoint the event applies to. For instance if three fingers are down, and you lift the second finger, all three touchpoints are passed to the touchend callback. Is there a way for me to determine which touchpoint the touchend event applies to? If this is a bug, is there a known workaround?
Thank you in advance.

Okay, after doing some research I found a solution on this website:
https://github.com/kripken/emscripten/issues/5012
They suggest that you edit library_html5.js in the Emscripten code and change:
var touches = {};
for(var i = 0; i < e.touches.length; ++i) {
var touch = e.touches[i];
touches[touch.identifier] = touch;
}
for(var i = 0; i < e.changedTouches.length; ++i) {
var touch = e.changedTouches[i];
touches[touch.identifier] = touch;
touch.changed = true;
}
With this:
var touches = {};
for(var i = 0; i < e.touches.length; ++i) {
var touch = e.touches[i];
touches[touch.identifier] = touch;
touch.changed = 0;
}
for(var i = 0; i < e.changedTouches.length; ++i) {
var touch = e.changedTouches[i];
touches[touch.identifier] = touch;
touch.changed = 1;
}
I applied the change and confirmed that it fixes multi-touch on iOS platforms.

Related

In Unity, how to detect if window is being resized and if window has stopped resizing

I wanted my UI to not resize when user is still resizing the game (holding click in the window border) and only when the user has released the mouse the resize event will trigger.
I have tried to achieve it on Unity but so far I only able to detect windows size change, which my script checked every 0.5 second and if detected change it will resize the UI. But of course resizing everything caused a heavy lag, so resizing every 0.5 second is not a good option but resizing every 1 second is not a good idea either because 1 second is considered too long.
The question might be too broad but I have specified the problem as small as possible, how do I detect if user is still resizing the window? And how do I detect if user has stopped resizing the window (stop holding click at window border)?
You can't tell when someone stops dragging a window, unless you want to code a low level solution for ever desktop environment and every operating system.
Here's what worked for me with any MonoBehavior class, using the OnRectTransformDimensionsChange event:
public class StackOverflow : MonoBehaviour
{
private const float TimeBetweenScreenChangeCalculations = 0.5f;
private float _lastScreenChangeCalculationTime = 0;
private void Awake()
{
_lastScreenChangeCalculationTime = Time.time;
}
private void OnRectTransformDimensionsChange()
{
if (Time.time - _lastScreenChangeCalculationTime < TimeBetweenScreenChangeCalculations)
return;
_lastScreenChangeCalculationTime = Time.time;
Debug.Log($"Window dimensions changed to {Screen.width}x{Screen.height}");
}
}
I have some good news - sort of.
When the user resizes the window on Mac or PC,
Unity will AUTOMATICALLY re-layout everything.
BUT in fact ONLY when the user is "finished" resizing the Mac/PC window.
I believe that is what the OP is asking for - so the good news, what the OP is asking for is quite automatic.
However. A huge problem in Unity is Unity does not smoothly resize elements as the user is dragging the mouse to expand the Mac/PC window.
I have never found a solution to that problem. (A poor solution often mentioned is to check the size of the window every frame; that seems to be about the only approach.)
Again interestingly, what the OP mentions
" ..and if window has stopped resizing .."
is automatically done in Unity; in fact do nothing to achieve that.
I needed something like this for re generating a line chart, but as it has too many elements, it would be heavy to do it on every update, so I came up with this, which for me worked well:
public class ToRunOnResize : MonoBehaviour
{
private float screenWidth;
private bool screenStartedResizing = false;
private int updateCounter = 0;
private int numberOfUpdatesToRunXFunction = 15; // The number of frames you want your function to run after, (usually 60 per second, so 15 would be .25 seconds)
void Start()
{
screenWidth = Screen.width; // Identifies the screen width
}
private void Update()
{
if (Screen.width != screenWidth) // This will be run and repeated while you resize your screen
{
updateCounter = 0; // This will set 0 on every update, so the counter is reset until you release the resizing.
screenStartedResizing = true; // This lets the application know when to start counting the # of updates after you stopped resizing.
screenWidth = Screen.width;
}
if (screenStartedResizing)
{
updateCounter += 1; // This will count the updates until it gets to the numberOfUpdatesToRunXFunction
}
if (updateCounter == numberOfUpdatesToRunXFunction && screenStartedResizing)
{ // Finally we make the counter stop and run the code, in my case I use it for re-rendering a line chart.
screenStartedResizing = false;
// my re-rendering code...
// my re-rendering code...
}
}
}

Sketch Plugin Develop : Is there an API for Sketch to unlock the size of MSBitmapLayer?

The unlock size button in Sketh App
I can click this button to unlock the size of a layer in Sketch App.
And then I can change the width/height ratio of the image.
But I want my Sketch plugin to do this job instead of using my hand to click the button.
Is there an API for Sketch to unlock the size of MSBitmapLayer?
I've tried "[layer setIsLocked:false]", but it's not about the size lock.
Thank you very much.
The particular function you are looking for is
setConstrainProportions()
Here is an example for you, It might help you in understanding it
function toggleConstrainProportions(context) {
var doc = context.document
var selection = context.selection
// Toggles the currently selected item(s) 'Constrain Proportions'setting
for (var i = 0; i < [selection count]; i++) {
var s = [selection objectAtIndex: i]
s.frame().setConstrainProportions(!s.constrainProportions())
}
}
Hope this is helpful :)

Phaser multitouch (on laptop trackpad)

I'm confused by how to skip the following condition when 1) holding down, and then 2) another tap on the screen to release the aim. I think the secondary tap becomes the activePointer so I'm quite puzzled.
var holding_down = game.input.activePointer.isDown;
if (holding_down && game.input.pointer2.isUp) { cue.aiming = true; }
UPDATE: Please note that for the solution accepted, I had to differentiate between desktop and mobile usage. pointer1 & pointer2 work fine on mobile, but on desktop I had to do the following.
if (desktop) {
var holding_down = game.input.activePointer.leftButton.isDown;
var second_tap = spacebar.isDown;
} else {
var holding_down = game.input.pointer1.isDown;
var second_tap = game.input.pointer2.isDown;
}
Also note you need to declare the desktop var after intantating the game object. I then set the var in the preload() function: desktop = game.device.desktop;, otherwise it was giving the wrong value. Thanks!
You're correct in that the secondary tap becomes the activePointer. Per the documentation, activePointer is "[t]he most recently active Pointer object."
Therefore, you'll want to make your checks against game.input.pointer1 and game.input.pointer2 instead.
So replace activePointer in your code with pointer1 and that might get you closer to what you were looking for.

starling framework animation is choppy on enter frame

I have created a basic as3 web project with starling. All iam doing is creating a simple image and in onEnterframe moving the image along x. But it seems that the animation/movement is not smooth, there is a jump in frames/jerkiness after every few frames. Below is onEnterFrame and the test function used to create the image. Any help on this is much appreciated.
private function onEnterFrame(e:Event):void
{
if(!img)
return;
img.x += 1;
if(img.x >= 960)
img.x = 0;
}
private function test():void
{
img = new Image(sAssets.getTextureAtlas("atlas").getTexture("flight_00"));
addChild(img);
img.x = 0;
img.y = 320;
}
That's because the time of each frame is slightly different. To achieve smooth animation, declare onEnterFrame handler with passedTime argument (that stores the time passed since previous frame) and use this value to move objects, instead of assuming that each frame will last 1/frameRate sec.
private function onEnterFrame(passedTime:Number):void
{
if(!img)
return;
img.x += passedTime * 100; // speed is 100 px/sec
if(img.x >= 960)
img.x = 0;
}
Note: this form of event handlers (without event argument) is supported in recent versions of Starling, and should be more performant. If you use older version, you can obtain passed time from the corresponding property of event object.

System-wide tap simulation on iOS

I would like to achieve system-wide tap simulation on iOS, via a MobileSubstrate plugin. The idea is to be able to simulate touches (in a first time single touch, then multitouch) on a system-wide level, in iOS 5.1.1 .
I've been successful in implementing this article to simulate touches on a specific view, I now would like to be able to simulate them system-wide.
I understand I should use the private MobileServices framework to do so, and I've documented myself on GSEvent (I've also looked at Veency & MouseSupport sourcecodes).
I tried to hook up a view to intercept UIEvents and look at the underlying structure :
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
GSEventRef eventRef = (GSEventRef)[event performSelector:#selector( _gsEvent)];
GSEventRecord record = *_GSEventGetGSEventRecord(eventRef);
< breakpoint here to look at record >
}
and the result is extremely similar to the old (iOS 3) structure detailled above.
I then tried to fire up those events myself (on a Standalone app, not a MS tweak for now) :
+(void)simulateTouchDown:(CGPoint)point{
point.x = roundf(point.x);
point.y = roundf(point.y);
GSEventRecord record;
memset(&record, 0, sizeof(record));
record.type = kGSEventHand;
record.windowLocation = point;
record.timestamp = GSCurrentEventTimestamp();
GSSendSystemEvent(&record);
}
Now, that doesn't work at all (doesn't crash either).
Most codes (MouseSupport, Veency) look like this
// Create & populate a GSEvent
struct {
struct GSEventRecord record;
struct {
struct GSEventRecordInfo info;
struct GSPathInfo path;
} data;
} event;
memset(&event, 0, sizeof(event));
event.record.type = kGSEventHand;
event.record.windowLocation = point;
event.record.timestamp = GSCurrentEventTimestamp();
event.record.infoSize = sizeof(event.data);
event.data.info.handInfo.type = kGSHandInfoTypeTouchDown;
event.data.info.handInfo._0x44 = 0x1;
event.data.info.handInfo._0x48 = 0x1;
event.data.info.pathPositions = 1;
event.data.path.pathIndex = 0x01;
event.data.path.pathIdentity = 0x02;
event.data.path.pathProximity = 0x00;
event.data.path.pathLocation = event.record.windowLocation;
GSSendSystemEvent(&event.record);
Only :
GSEventRecordInfo is unknown (and I can't find where it might be defined)
I don't see the point of making a whole event to only pass the record
Please someone who's been through this on iOS 5 guide me.
GSEventRecordInfo may have been introduced since iOS 3.2 (that's where the Graphics Services headers you linked to are from). class-dump the framework that's actually on your device on iOS 5.1.1 and see if it's defined there?