Here's a possible solution for anyone that has run into issues getting Gamestudio games to work properly on Windows tablets.
The problem: Touch events != mouse events. Mouse inputs will lag behind, UI elements will barely work at all, and trying to tap a button will actually tap whatever you touched before that.
The solution: Grab window events as they happen and make your own input system.
First things first, you need to define an event handler.
#define TOUCH_MESSAGE 581
#define RELEASE_MESSAGE 514
#define RELEASE2_MESSAGE 123
var touchMouseDown = 0;
VECTOR touchMousePos;
VECTOR touchMickey;
LRESULT CALLBACK baseMessageHandler(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK handleTouch(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if(message == TOUCH_MESSAGE)
{
VECTOR temp;
getXYparam(lParam, temp);
if(!touchMouseDown)
{
vec_set(touchMousePos, mouse_pos);
vec_zero(touchMickey);
}
touchMouseDown = 1;
if(touchEnable)
{
mouse_pos.x = temp.x;
mouse_pos.y = temp.y;
}
}
if(message == RELEASE_MESSAGE || message == RELEASE2_MESSAGE)
{
touchMouseDown = 0;
}
return baseMessageHandler(hwnd,message,wParam,lParam);
}
void setMessageHandler_startup()
{
baseMessageHandler = on_message;
on_message = handleTouch;
}
Next, you may or may not need to break out the plugin API. If anyone has a lite-C alternative, feel free to provide that. Otherwise, we need this C++ function:
DLLFUNC void getXYparam(LPARAM in, VECTOR* out)
{
out->x = _VAR(GET_X_LPARAM(in));
out->y = _VAR(GET_Y_LPARAM(in));
}
Once we've finished that, here's where the magic happens. This is a portion of my main() loop, which supports both drag and tap. touchMickey is like the built-in mickey value but touch friendly, and can be used for panning the camera around. And we can fill in a function called uiMouseDown() that can do something useful with the touch position, such as seeking buttons to click. Note: This will NOT work with standard panel buttons and click events. You will need to iterate through clickable buttons manually and perform c_traces instead.
var mouse = 0;
var mouseClick = 0;
while(1)
{
vec_diff(touchMickey, mouse_pos, touchMousePos);
vec_set(touchMousePos, mouse_pos);
if(touchMouseDown)// || mouse_left)
{
if(!mouseClick)
{
mouseClick = 1;
uiMouseDown();
}
if(mouse > 2)
{
camera.pan -= touchMickey.x * 0.15;
camera.tilt = clamp(camera.tilt - touchMickey.y * 0.15, -85, 85);
}
else
{
++mouse;
}
}
else
{
mouseClick = 0;
mouse = 0;
}
wait(1);
}
This is from a working demo, so if this example does not work, complain about it and I will have a look and see what I missed. Hope this helps somebody!
Another note: This has been tested only on a full-screen application. The mouse coordinates are given as absolute screen positions and would need to have the window client area position subtracted if you want to allow for windowed games.