User Tools

Site Tools


c_tutorial

GestureWorks 2 C++ Samples and Tutorials

C++ Samples

Qt Sample

A sample using the popular Qt library is in the GestureWorks 2 install at: Samples\Qt Quick\GestureWorks. This sample using Qt Quick and has a QML MultiPointGestureArea class which can be used for Qt Quick applications.

Visual Studio C++ Sample

A simpler C++ sample using Visual Studio and some basic helper classes for rendering is located at: Samples\C++\GestureWorks-tutorial-scene.
This sample is described in the tutorials below.

C++ Tutorials

The following tutorials goes through adding GestureWorks to a C++ project. The starting code for this project is in the GestureWorks build at Samples\C++\GestureWorks-tutorial-start.

This project creates a blank scene with an image. We will look at how to have this image respond to gestures using GestureWorks.

Adding gestures will be done using two techniques. First we will look at setting up GestureWorks in the simpler screen mode and then in its scene mode.

C++ Screen Tutorial

C++ Scene Tutorial

Below is the main starting code for this project. The Re_* functions are in “render.h” and are simple rendering functions for DirectX to draw the image. We will not be modifying this base code, knowledge of the Windows API calls will not be required, as we will be only adding GestureWorks calls.

#include <Windows.h>
#include <iostream>
#include "render.h"

// Some variables to display our test image
static int s_window_width, s_window_height;
static float s_image_x, s_image_y;
static float s_image_rotation;
static float s_image_scale;

HWND CreateAdjustedWindow(char *windowTitle, WNDPROC wndProc, bool windowed = false, int width = CW_USEDEFAULT, int height = CW_USEDEFAULT, int x = CW_USEDEFAULT, int y = CW_USEDEFAULT)
{
	WNDCLASSEXA wc;
	ZeroMemory(&wc, sizeof(wc));
	wc.style = CS_OWNDC;
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.lpfnWndProc = wndProc;
	wc.hInstance = GetModuleHandle(0);
	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
	wc.lpszClassName = windowTitle;
	RegisterClassExA(&wc);

	RECT windowRect;
	DWORD style;
	if (windowed)
	{
		style = WS_OVERLAPPED;
		windowRect = { 0, 0, width, height };
		AdjustWindowRectEx(&windowRect, style, FALSE, 0);
	}
	else
	{
		style = WS_POPUPWINDOW ^ WS_BORDER;
		HWND desktop = GetDesktopWindow();
		GetWindowRect(desktop, &windowRect);
		x = 0;
		y = 0;
	}

	width = windowRect.right - windowRect.left;
	height = windowRect.bottom - windowRect.top;
	HWND hWnd = CreateWindowExA(0, wc.lpszClassName, windowTitle, style, x, y, width, height, NULL, NULL, wc.hInstance, NULL);
	ShowWindow(hWnd, SW_NORMAL);
	s_window_width = width;
	s_window_height = height;

	return hWnd;
}

void PumpEvents()
{
	MSG msg;
	while (PeekMessageA(&msg, NULL, 0, 0, 1) > 0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
}

static bool g_running = true;
static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
	case WM_POINTERDOWN:
	{
		POINTER_INFO pi;
		GetPointerInfo(GET_POINTERID_WPARAM(wParam), &pi);

		break;
	}
	case WM_POINTERUP:
	{
		POINTER_INFO pi;
		GetPointerInfo(GET_POINTERID_WPARAM(wParam), &pi);

		break;
	}
	case WM_POINTERUPDATE:
	{
		POINTER_INFO pi;
		GetPointerInfo(GET_POINTERID_WPARAM(wParam), &pi);

		break;
	}

	case WM_CREATE:
		Re_Init(hWnd);
		break;
	case WM_DESTROY:
		g_running = false;
		break;
	case WM_KEYDOWN:
		if (wParam == VK_ESCAPE)
			g_running = false;
		break;
	case WM_SIZE:
		Re_SizeToClientArea();
		break;
	}
	return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	HWND hWnd = CreateAdjustedWindow("GestureWorks Demo", WndProc, false);

	RECT clientRect;
	GetClientRect(hWnd, &clientRect);

	Re_Image *testImage = Re_LoadImage(L"GestureWorks.png");

	float screenCenterX = clientRect.right / 2.0f;
	float screenCenterY = clientRect.bottom / 2.0f;
	s_image_x = clientRect.right / 2.0f - testImage->width / 2.0f;
	s_image_y = clientRect.bottom / 2.0f - testImage->height / 2.0f;
	s_image_rotation = 0.0f;
	s_image_scale = 1.0f;

	float angle = 0;
	while (g_running)
	{
		PumpEvents();

		Re_ClearScreen(0.52f, 0.80f, 0.98f, 0);

		Re_BeginDraw();
		Re_Identity();

		Re_Scale(s_image_scale, s_image_scale, s_image_x + testImage->width / 2.0f, s_image_y + testImage->height / 2.0f);
		Re_Rotate(s_image_rotation, s_image_x + testImage->width / 2.0f, s_image_y + testImage->height / 2.0f);
		Re_DrawImage(testImage, s_image_x, s_image_y);

		Re_EndDraw();

		// waits for vsync
		Re_PresentBackBuffer();
	}

	Re_ReleaseImage(testImage);
	Re_Cleanup();
}
c_tutorial.txt · Last modified: 2019/01/21 16:34 (external edit)