Pārlūkot izejas kodu

Started working on Windows gamepad support + Unicode fix for Windows

Ivan Safrin 14 gadi atpakaļ
vecāks
revīzija
5c34882c66

+ 60 - 1
Core/Contents/Include/PolyWinCore.h

@@ -32,6 +32,10 @@
 #include <windowsx.h>
 #include <WinUser.h>
 
+#include <MMSystem.h>
+#include <regstr.h>
+
+
 #include <vector>
 
 #ifndef VK_0
@@ -109,6 +113,54 @@ namespace Polycode {
 		static const int INPUT_EVENT = 0;
 	};
 	
+	
+	class HIDGamepadAxis {
+		public:
+		//IOHIDElementCookie cookie;
+		//CFIndex logicalMin;
+		//CFIndex logicalMax;
+		bool hasNullState;
+		bool isHatSwitch;
+		bool isHatSwitchSecondAxis;
+	};
+
+	class HIDGamepadButton {
+		public:
+		//IOHIDElementCookie cookie;
+		int something;
+	};	
+	
+class Gamepad_devicePrivate {
+public:
+	UINT joystickID;
+	JOYINFOEX lastState;
+	int xAxisIndex;
+	int yAxisIndex;
+	int zAxisIndex;
+	int rAxisIndex;
+	int uAxisIndex;
+	int vAxisIndex;
+	int povXAxisIndex;
+	int povYAxisIndex;
+	UINT (* axisRanges)[2];
+};
+
+
+	class GamepadDeviceEntry  {
+		public:
+			GamepadDeviceEntry() {
+				numAxes = 0;
+			}
+			std::vector<HIDGamepadAxis> axisElements;
+			std::vector<HIDGamepadButton> buttonElements;			
+			unsigned int deviceID;
+			//IOHIDDeviceRef device;
+			unsigned int numAxes;
+			unsigned int numButtons;	
+			Gamepad_devicePrivate *privateData;
+		//	CoreInput *input;		
+	};
+
 	class _PolyExport Win32Core : public Core {
 		
 	public:
@@ -120,7 +172,7 @@ namespace Polycode {
 		unsigned int getTicks();		
 		bool Update();
 
-		void handleKeyDown(LPARAM lParam, WPARAM wParam);
+		void handleKeyDown(LPARAM lParam, WPARAM wParam, wchar_t unicodeChar);
 		void handleKeyUp(LPARAM lParam, WPARAM wParam);
 		void handleMouseMove(LPARAM lParam, WPARAM wParam);
 		void handleMouseWheel(LPARAM lParam, WPARAM wParam);
@@ -147,6 +199,10 @@ namespace Polycode {
 
 		std::vector<Polycode::Rectangle> getVideoModes();
 
+		void initGamepad();
+		void shutdownGamepad();
+		void Gamepad_processEvents();
+
 		// NEED TO IMPLEMENT:
 
 		void setCursor(int cursorType){ }
@@ -161,8 +217,11 @@ namespace Polycode {
 		std::vector<String> openFilePicker(std::vector<CoreFileExtension> extensions, bool allowMultiple) { std::vector<String> ret; return ret;}
 		void resizeTo(int xRes, int yRes) { }
 		
+		std::vector<GamepadDeviceEntry*> gamepads;
+
 	private:
 
+		unsigned int nextDeviceID;
 		PolyKEY keyMap[1024];
 
 		CoreMutex *eventMutex;

+ 15 - 2
Core/Contents/PolycodeView/MSVC/PolycodeView.cpp

@@ -65,8 +65,21 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 			core->handleMouseUp(CoreInput::MOUSE_BUTTON3, lParam,wParam);
 	break;
 	case WM_KEYDOWN:
-		if(core)
-			core->handleKeyDown(lParam,wParam);
+		if(core) {
+				wchar_t unicodeChar = 0;
+				MSG m;
+				m.hwnd = hWnd;
+				m.message = message;
+				m.wParam = wParam;
+				m.lParam = lParam;
+				m.time = 0;
+				if ( PeekMessage(&m, hWnd, 0, WM_USER, PM_NOREMOVE) && (m.message == WM_CHAR) ) {
+					GetMessage(&m, hWnd, 0, WM_USER);
+			    		unicodeChar = (wchar_t)m.wParam;
+				}
+
+			core->handleKeyDown(lParam,wParam, unicodeChar);
+		}
 	break;
 	case WM_KEYUP:
 		if(core)

+ 3 - 2
Core/Contents/Source/PolyImage.cpp

@@ -455,7 +455,7 @@ void Image::fill(Number r, Number g, Number b, Number a) {
 }
 
 bool Image::saveImage(const String &fileName) {
-	savePNG(fileName);
+	return savePNG(fileName);
 }
 
 
@@ -503,7 +503,7 @@ bool Image::savePNG(const String &fileName) {
 	png_write_info(png_ptr, info_ptr);
 
    png_uint_32 k;
-   png_bytep row_pointers[height];
+   png_bytep *row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
 
    if (height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
      png_error (png_ptr, "Image is too tall to process in memory");
@@ -515,6 +515,7 @@ bool Image::savePNG(const String &fileName) {
 
    png_write_image(png_ptr, row_pointers);
 
+   free(row_pointers);
    png_free(png_ptr, 0);
    png_destroy_write_struct(&png_ptr, &info_ptr);
    fclose(fp);

+ 157 - 4
Core/Contents/Source/PolyWinCore.cpp

@@ -57,7 +57,9 @@ Win32Core::Win32Core(PolycodeViewBase *view, int xRes, int yRes, bool fullScreen
 
 	hWnd = *((HWND*)view->windowData);
 	core = this;
+
 	initKeymap();
+	initGamepad();
 
 	hDC = NULL;
 	hRC = NULL;
@@ -86,6 +88,7 @@ Win32Core::Win32Core(PolycodeViewBase *view, int xRes, int yRes, bool fullScreen
 }
 
 Win32Core::~Win32Core() {
+	shutdownGamepad();
 	destroyContext();
 }
 
@@ -102,6 +105,7 @@ bool Win32Core::Update() {
 		return false;
 
 	checkEvents();
+	Gamepad_processEvents();
 
 	renderer->BeginRender();
 	updateCore();
@@ -231,7 +235,6 @@ void Win32Core::initMultisample(int numSamples) {
 		return;
 	}
 	int pixelFormat;
-	bool valid;
 	UINT numFormats;
 	float fAttributes[] = {0,0};
 
@@ -403,13 +406,13 @@ PolyKEY Win32Core::mapKey(LPARAM lParam, WPARAM wParam) {
 	return keyMap[(unsigned int)wParam];
 }
 
-void Win32Core::handleKeyDown(LPARAM lParam, WPARAM wParam) {
+void Win32Core::handleKeyDown(LPARAM lParam, WPARAM wParam, wchar_t unicodeChar) {
 	lockMutex(eventMutex);
 	Win32Event newEvent;
 	newEvent.eventGroup = Win32Event::INPUT_EVENT;
 	newEvent.eventCode = InputEvent::EVENT_KEYDOWN;
 	newEvent.keyCode = mapKey(lParam, wParam);
-	newEvent.unicodeChar = ' ';
+	newEvent.unicodeChar = unicodeChar;
 	win32Events.push_back(newEvent);
 	unlockMutex(eventMutex);
 }
@@ -420,7 +423,7 @@ void Win32Core::handleKeyUp(LPARAM lParam, WPARAM wParam) {
 	newEvent.eventGroup = Win32Event::INPUT_EVENT;
 	newEvent.eventCode = InputEvent::EVENT_KEYUP;
 	newEvent.keyCode = mapKey(lParam, wParam);
-	newEvent.unicodeChar = ' ';
+	newEvent.unicodeChar = 0;
 	win32Events.push_back(newEvent);
 	unlockMutex(eventMutex);
 }
@@ -508,6 +511,156 @@ void Win32Core::checkEvents() {
 	unlockMutex(eventMutex);		
 }
 
+void Win32Core::Gamepad_processEvents() {
+	/*
+	unsigned int deviceIndex;
+	JOYINFOEX info;
+	MMRESULT result;
+	GamepadDeviceEntry * device;
+	Gamepad_devicePrivate * devicePrivate;
+	
+	for (deviceIndex = 0; deviceIndex < gamepads.size(); deviceIndex++) {
+		device = gamepads[deviceIndex];
+		devicePrivate = device->privateData;
+		
+		info.dwSize = sizeof(info);
+		info.dwFlags = JOY_RETURNALL;
+		result = joyGetPosEx(devicePrivate->joystickID, &info);
+		if (result == JOYERR_UNPLUGGED) {
+
+			Gamepad_eventDispatcher()->dispatchEvent(Gamepad_eventDispatcher(), GAMEPAD_EVENT_DEVICE_REMOVED, device);
+			disposeDevice(device);
+			numDevices--;
+			for (; deviceIndex < numDevices; deviceIndex++) {
+				devices[deviceIndex] = devices[deviceIndex + 1];
+			}
+			
+		} else if (result == JOYERR_NOERROR) {
+			if (info.dwXpos != devicePrivate->lastState.dwXpos) {
+				handleAxisChange(device, devicePrivate->xAxisIndex, info.dwXpos);
+			}
+			if (info.dwYpos != devicePrivate->lastState.dwYpos) {
+				handleAxisChange(device, devicePrivate->yAxisIndex, info.dwYpos);
+			}
+			if (info.dwZpos != devicePrivate->lastState.dwZpos) {
+				handleAxisChange(device, devicePrivate->zAxisIndex, info.dwZpos);
+			}
+			if (info.dwRpos != devicePrivate->lastState.dwRpos) {
+				handleAxisChange(device, devicePrivate->rAxisIndex, info.dwRpos);
+			}
+			if (info.dwUpos != devicePrivate->lastState.dwUpos) {
+				handleAxisChange(device, devicePrivate->uAxisIndex, info.dwUpos);
+			}
+			if (info.dwVpos != devicePrivate->lastState.dwVpos) {
+				handleAxisChange(device, devicePrivate->vAxisIndex, info.dwVpos);
+			}
+			if (info.dwPOV != devicePrivate->lastState.dwPOV) {
+				handlePOVChange(device, devicePrivate->lastState.dwPOV, info.dwPOV);
+			}
+			if (info.dwButtons != devicePrivate->lastState.dwButtons) {
+				handleButtonChange(device, devicePrivate->lastState.dwButtons, info.dwButtons);
+			}
+			devicePrivate->lastState = info;
+		}
+	}
+	*/
+}
+
+
+void Win32Core::initGamepad() {
+	
+	nextDeviceID = 0;
+
+	unsigned int numPadsSupported;
+	unsigned int deviceIndex, deviceIndex2;
+	JOYINFOEX info;
+	JOYCAPS caps;
+	bool duplicate;
+	Gamepad_devicePrivate * deviceRecordPrivate;
+	UINT joystickID;
+	int axisIndex;
+	
+	numPadsSupported = joyGetNumDevs();
+	for (deviceIndex = 0; deviceIndex < numPadsSupported; deviceIndex++) {
+		info.dwSize = sizeof(info);
+		info.dwFlags = JOY_RETURNALL;
+		joystickID = JOYSTICKID1 + deviceIndex;
+		if (joyGetPosEx(joystickID, &info) == JOYERR_NOERROR &&
+		    joyGetDevCaps(joystickID, &caps, sizeof(JOYCAPS)) == JOYERR_NOERROR) {
+			
+			duplicate = false;
+			for (deviceIndex2 = 0; deviceIndex2 < gamepads.size(); deviceIndex2++) {
+				if (((struct Gamepad_devicePrivate *) gamepads[deviceIndex2]->privateData)->joystickID == joystickID) {
+					duplicate = true;
+					break;
+				}
+			}
+			if (duplicate) {
+				continue;
+			}
+			
+			GamepadDeviceEntry *deviceRecord = new GamepadDeviceEntry();
+			deviceRecord->deviceID = nextDeviceID++;
+//			deviceRecord->description = getDeviceDescription(joystickID, caps);
+//			deviceRecord->vendorID = caps.wMid;
+//			deviceRecord->productID = caps.wPid;
+			deviceRecord->numAxes = caps.wNumAxes + ((caps.wCaps & JOYCAPS_HASPOV) ? 2 : 0);
+			deviceRecord->numButtons = caps.wNumButtons;
+//			deviceRecord->axisStates = calloc(sizeof(float), deviceRecord->numAxes);
+//			deviceRecord->buttonStates = calloc(sizeof(bool), deviceRecord->numButtons);
+//			deviceRecord->eventDispatcher = EventDispatcher_create(deviceRecord);
+//			devices = realloc(devices, sizeof(struct Gamepad_device *) * (numDevices + 1));
+			gamepads.push_back(deviceRecord);
+			
+			deviceRecordPrivate = new Gamepad_devicePrivate();
+			deviceRecordPrivate->joystickID = joystickID;
+			deviceRecordPrivate->lastState = info;
+			
+			deviceRecordPrivate->xAxisIndex = 0;
+			deviceRecordPrivate->yAxisIndex = 1;
+			axisIndex = 2;
+			deviceRecordPrivate->zAxisIndex = (caps.wCaps & JOYCAPS_HASZ) ? axisIndex++ : -1;
+			deviceRecordPrivate->rAxisIndex = (caps.wCaps & JOYCAPS_HASR) ? axisIndex++ : -1;
+			deviceRecordPrivate->uAxisIndex = (caps.wCaps & JOYCAPS_HASU) ? axisIndex++ : -1;
+			deviceRecordPrivate->vAxisIndex = (caps.wCaps & JOYCAPS_HASV) ? axisIndex++ : -1;
+			
+			deviceRecordPrivate->axisRanges = (UINT (*)[2]) malloc(sizeof(UINT[2]) * axisIndex);
+			deviceRecordPrivate->axisRanges[0][0] = caps.wXmin;
+			deviceRecordPrivate->axisRanges[0][1] = caps.wXmax;
+			deviceRecordPrivate->axisRanges[1][0] = caps.wYmin;
+			deviceRecordPrivate->axisRanges[1][1] = caps.wYmax;
+			if (deviceRecordPrivate->zAxisIndex != -1) {
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->zAxisIndex][0] = caps.wZmin;
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->zAxisIndex][1] = caps.wZmax;
+			}
+			if (deviceRecordPrivate->rAxisIndex != -1) {
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->rAxisIndex][0] = caps.wRmin;
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->rAxisIndex][1] = caps.wRmax;
+			}
+			if (deviceRecordPrivate->uAxisIndex != -1) {
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->uAxisIndex][0] = caps.wUmin;
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->uAxisIndex][1] = caps.wUmax;
+			}
+			if (deviceRecordPrivate->vAxisIndex != -1) {
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->vAxisIndex][0] = caps.wVmin;
+				deviceRecordPrivate->axisRanges[deviceRecordPrivate->vAxisIndex][1] = caps.wVmax;
+			}
+			
+			deviceRecordPrivate->povXAxisIndex = (caps.wCaps & JOYCAPS_HASPOV) ? axisIndex++ : -1;
+			deviceRecordPrivate->povYAxisIndex = (caps.wCaps & JOYCAPS_HASPOV) ? axisIndex++ : -1;
+			
+			deviceRecord->privateData = deviceRecordPrivate;
+			
+			input->addJoystick(deviceRecord->deviceID);
+			//Gamepad_eventDispatcher()->dispatchEvent(Gamepad_eventDispatcher(), GAMEPAD_EVENT_DEVICE_ATTACHED, deviceRecord);
+		}
+	}
+}
+
+void Win32Core::shutdownGamepad() {
+
+}
+
 DWORD WINAPI Win32LaunchThread(LPVOID data) {
 	Threaded *threaded = (Threaded*)data;
 	threaded->runThread();

+ 3 - 2
Modules/Contents/UI/Source/PolyUIScrollContainer.cpp

@@ -25,6 +25,7 @@
 #include "PolyInputEvent.h"
 #include "PolyLabel.h"
 #include "PolyCoreServices.h"
+#include <math.h>
 
 using namespace Polycode;
 
@@ -131,13 +132,13 @@ void UIScrollContainer::setContentSize(Number newContentWidth, Number newContent
 void UIScrollContainer::handleEvent(Event *event) {
 	if(event->getDispatcher() == vScrollBar) {
 		if(event->getEventCode() == Event::CHANGE_EVENT) {
-			scrollChild->setPositionY(round(-((contentHeight-height) )*vScrollBar->getScrollValue()));
+			scrollChild->setPositionY(floor(-((contentHeight-height) )*vScrollBar->getScrollValue()));
 		}
 	}
 	
 	if(event->getDispatcher() == hScrollBar) {
 		if(event->getEventCode() == Event::CHANGE_EVENT) {
-			scrollChild->setPositionX(round(-((contentWidth-width) )*hScrollBar->getScrollValue()));
+			scrollChild->setPositionX(floor(-((contentWidth-width) )*hScrollBar->getScrollValue()));
 		}
 	}