From ebefcc885f74461cd0e3f19b5ae3622dc6cf6dbc Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 27 Jun 2013 11:25:32 -0800 Subject: SDK 0.2.2 --- Samples/CommonSrc/Platform/Gamepad.h | 102 +++++ Samples/CommonSrc/Platform/OSX_Gamepad.cpp | 424 ++++++++++++++++++ Samples/CommonSrc/Platform/OSX_Gamepad.h | 67 +++ Samples/CommonSrc/Platform/OSX_Platform.h | 80 ++++ Samples/CommonSrc/Platform/OSX_Platform.mm | 514 ++++++++++++++++++++++ Samples/CommonSrc/Platform/OSX_PlatformObjc.h | 31 ++ Samples/CommonSrc/Platform/OSX_WavPlayer.cpp | 242 +++++++++++ Samples/CommonSrc/Platform/OSX_WavPlayer.h | 64 +++ Samples/CommonSrc/Platform/Platform.cpp | 75 ++++ Samples/CommonSrc/Platform/Platform.h | 190 ++++++++ Samples/CommonSrc/Platform/Platform_Default.h | 59 +++ Samples/CommonSrc/Platform/Win32_Gamepad.cpp | 101 +++++ Samples/CommonSrc/Platform/Win32_Gamepad.h | 54 +++ Samples/CommonSrc/Platform/Win32_Platform.cpp | 600 ++++++++++++++++++++++++++ Samples/CommonSrc/Platform/Win32_Platform.h | 101 +++++ 15 files changed, 2704 insertions(+) create mode 100644 Samples/CommonSrc/Platform/Gamepad.h create mode 100644 Samples/CommonSrc/Platform/OSX_Gamepad.cpp create mode 100644 Samples/CommonSrc/Platform/OSX_Gamepad.h create mode 100644 Samples/CommonSrc/Platform/OSX_Platform.h create mode 100644 Samples/CommonSrc/Platform/OSX_Platform.mm create mode 100644 Samples/CommonSrc/Platform/OSX_PlatformObjc.h create mode 100644 Samples/CommonSrc/Platform/OSX_WavPlayer.cpp create mode 100644 Samples/CommonSrc/Platform/OSX_WavPlayer.h create mode 100644 Samples/CommonSrc/Platform/Platform.cpp create mode 100644 Samples/CommonSrc/Platform/Platform.h create mode 100644 Samples/CommonSrc/Platform/Platform_Default.h create mode 100644 Samples/CommonSrc/Platform/Win32_Gamepad.cpp create mode 100644 Samples/CommonSrc/Platform/Win32_Gamepad.h create mode 100644 Samples/CommonSrc/Platform/Win32_Platform.cpp create mode 100644 Samples/CommonSrc/Platform/Win32_Platform.h (limited to 'Samples/CommonSrc/Platform') diff --git a/Samples/CommonSrc/Platform/Gamepad.h b/Samples/CommonSrc/Platform/Gamepad.h new file mode 100644 index 0000000..01eaab4 --- /dev/null +++ b/Samples/CommonSrc/Platform/Gamepad.h @@ -0,0 +1,102 @@ +/************************************************************************************ + +Filename : Gamepad.h +Content : Cross platform Gamepad interface. +Created : May 6, 2013 +Authors : Lee Cooper + +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_Gamepad_h +#define OVR_Gamepad_h + +#include "OVR.h" + +namespace OVR { namespace Platform { + +// Buttons on a typical gamepad controller. +enum GamepadButtons +{ + Gamepad_A = 0x1000, + Gamepad_CROSS = 0x1000, + Gamepad_B = 0x2000, + Gamepad_CIRCLE = 0x2000, + Gamepad_X = 0x4000, + Gamepad_SQUARE = 0x4000, + Gamepad_Y = 0x8000, + Gamepad_TRIANGLE = 0x8000, + Gamepad_Up = 0x0001, + Gamepad_Down = 0x0002, + Gamepad_Left = 0x0004, + Gamepad_Right = 0x0008, + Gamepad_Start = 0x0010, + Gamepad_Back = 0x0020, + Gamepad_LStick = 0x0040, + Gamepad_RStick = 0x0080, + Gamepad_L1 = 0x0100, + Gamepad_R1 = 0x0200, +}; + +//------------------------------------------------------------------------------------- +// ***** GamepadState + +// Describes the state of the controller buttons and analog inputs. +struct GamepadState +{ + UInt32 Buttons; // Bitfield representing button state. + float LX; // Left stick X axis [-1,1] + float LY; // Left stick Y axis [-1,1] + float RX; // Right stick X axis [-1,1] + float RY; // Right stick Y axis [-1,1] + float LT; // Left trigger [0,1] + float RT; // Right trigger [0,1] + + GamepadState() : Buttons(0), LX(0), LY(0), RX(0), RY(0), LT(0), RT(0) {} + + bool operator==(const GamepadState& b) const + { + return Buttons == b.Buttons && LX == b.LX && LY == b.LY && RX == b.RX && RY == b.RY && LT == b.LT && RT == b.RT; + } + bool operator!=(const GamepadState& b) const + { + return !(*this == b); + } + void Debug() + { + OVR_DEBUG_LOG(("Buttons:0x%4x LX:%.2f LY:%.2f RX:%.2f RY:%.2f LT:%.2f RT:%.2f", Buttons, LX, LY, RX, RY, LT, RT)); + } +}; + +//------------------------------------------------------------------------------------- +// ***** GamepadManager + +// GamepadManager provides a cross platform interface for accessing gamepad controller +// state. +class GamepadManager : public RefCountBase +{ +public: + + // Get the number of connected gamepads. + virtual UInt32 GetGamepadCount() = 0; + + // Get the state of the gamepad with a given index. + virtual bool GetGamepadState(UInt32 index, GamepadState* pState) = 0; +}; + +}} // OVR::Platform + +#endif // OVR_Gamepad_h diff --git a/Samples/CommonSrc/Platform/OSX_Gamepad.cpp b/Samples/CommonSrc/Platform/OSX_Gamepad.cpp new file mode 100644 index 0000000..3ac53ab --- /dev/null +++ b/Samples/CommonSrc/Platform/OSX_Gamepad.cpp @@ -0,0 +1,424 @@ +/************************************************************************************ + +Filename : OSX_Gamepad.cpp +Content : OSX implementation of Gamepad functionality. +Created : May 6, 2013 +Authors : Lee Cooper + +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#include "OSX_Gamepad.h" + + +static const UInt32 Logitech_F710_VendorID = 0x046D; +static const UInt32 Logitech_F710_ProductID = 0xC219; + +static const UInt32 Sony_DualShock3_VendorID = 0x054C; +static const UInt32 Sony_DualShock3_ProductID = 0x0268; + + +namespace OVR { namespace Platform { namespace OSX { + + +GamepadManager::GamepadManager() + : bStateChanged(false) +{ + + HidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + IOHIDManagerOpen(HidManager, kIOHIDOptionsTypeNone); + IOHIDManagerScheduleWithRunLoop(HidManager, + CFRunLoopGetCurrent(), + kCFRunLoopDefaultMode); + + + // Setup device matching. + CFStringRef keys[] = { CFSTR(kIOHIDDeviceUsagePageKey), + CFSTR(kIOHIDDeviceUsageKey)}; + + int value; + CFNumberRef values[2]; + CFDictionaryRef dictionaries[2]; + + // Match joysticks. + value = kHIDPage_GenericDesktop; + values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value); + + value = kHIDUsage_GD_Joystick; + values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value); + + dictionaries[0] = CFDictionaryCreate(kCFAllocatorDefault, + (const void **) keys, + (const void **) values, + 2, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFRelease(values[0]); + CFRelease(values[1]); + + // Match gamepads. + value = kHIDPage_GenericDesktop; + values[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value); + + value = kHIDUsage_GD_GamePad; + values[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &value); + + dictionaries[1] = CFDictionaryCreate(kCFAllocatorDefault, + (const void **) keys, + (const void **) values, + 2, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + CFRelease(values[0]); + CFRelease(values[1]); + + CFArrayRef array = CFArrayCreate( kCFAllocatorDefault, + (const void **) dictionaries, + 2, + &kCFTypeArrayCallBacks); + CFRelease(dictionaries[0]); + CFRelease(dictionaries[1]); + + IOHIDManagerSetDeviceMatchingMultiple(HidManager, array); + + CFRelease(array); + + + IOHIDManagerRegisterDeviceMatchingCallback(HidManager, staticOnDeviceMatched, this); + IOHIDManagerRegisterDeviceRemovalCallback(HidManager, staticOnDeviceRemoved, this); + +} + +GamepadManager::~GamepadManager() +{ + CFRelease(HidManager); +} + +UInt32 GamepadManager::GetGamepadCount() +{ + return 1; +} + +bool GamepadManager::GetGamepadState(UInt32 index, GamepadState* pState) +{ + // For now we just support one gamepad. + OVR_UNUSED(index); + + if (!bStateChanged) + { + return false; + } + + bStateChanged = false; +// State.Debug(); + + *pState = State; + return true; +} + +int GamepadManager::getIntDeviceProperty(IOHIDDeviceRef device, CFStringRef key) +{ + CFTypeRef type = IOHIDDeviceGetProperty(device, key); + OVR_ASSERT(type != NULL && CFGetTypeID(type) == CFNumberGetTypeID()); + + int value; + CFNumberGetValue((CFNumberRef) type, kCFNumberSInt32Type, &value); + + return value; +} + +void GamepadManager::staticOnDeviceMatched(void* context, IOReturn result, void* sender, IOHIDDeviceRef device) +{ + GamepadManager* pManager = (GamepadManager*) context; + pManager->onDeviceMatched(device); +} + +void GamepadManager::onDeviceMatched(IOHIDDeviceRef device) +{ + IOHIDDeviceRegisterInputValueCallback(device, staticOnDeviceValueChanged, this); +} + +void GamepadManager::staticOnDeviceRemoved(void* context, IOReturn result, void* sender, IOHIDDeviceRef device) +{ + GamepadManager* pManager = (GamepadManager*) context; + pManager->onDeviceRemoved(device); +} + +void GamepadManager::onDeviceRemoved(IOHIDDeviceRef device) +{ + IOHIDDeviceRegisterInputValueCallback(device, NULL, NULL); +} + +void GamepadManager::staticOnDeviceValueChanged(void* context, IOReturn result, void* sender, IOHIDValueRef value) +{ + GamepadManager* pManager = (GamepadManager*) context; + pManager->onDeviceValueChanged(value); +} + +float GamepadManager::mapAnalogAxis(IOHIDValueRef value, IOHIDElementRef element) +{ + + CFIndex val = IOHIDValueGetIntegerValue(value); + CFIndex min = IOHIDElementGetLogicalMin(element); + CFIndex max = IOHIDElementGetLogicalMax(element); + + float v = (float) (val - min) / (float) (max - min); + v = v * 2.0f - 1.0f; + + // Dead zone. + if (v < 0.1f && v > -0.1f) + { + v = 0.0f; + } + + return v; +} + +bool GamepadManager::setStateIfDifferent(float& state, float newState) +{ + if (state == newState) + return false; + + state = newState; + + return true; +} + +void GamepadManager::onDeviceValueChanged(IOHIDValueRef value) +{ + + IOHIDElementRef element = IOHIDValueGetElement(value); + IOHIDDeviceRef device = IOHIDElementGetDevice(element); + + int vendorID = getIntDeviceProperty(device, CFSTR(kIOHIDVendorIDKey)); + int productID = getIntDeviceProperty(device, CFSTR(kIOHIDProductIDKey)); + OVR_UNUSED(productID); + + uint32_t usagePage = IOHIDElementGetUsagePage(element); + uint32_t usage = IOHIDElementGetUsage(element); + + // The following controller mapping is based on the Logitech F710, however we use it for + // all Logitech devices on the assumption that they're likely to share the same mapping. + if (vendorID == Logitech_F710_VendorID) + { + // Logitech F710 mapping. + if (usagePage == kHIDPage_Button) + { + bool buttonState = IOHIDValueGetIntegerValue(value); + + switch(usage) + { + case kHIDUsage_Button_1: + manipulateBitField(State.Buttons, Gamepad_X, buttonState); + break; + case kHIDUsage_Button_2: + manipulateBitField(State.Buttons, Gamepad_A, buttonState); + break; + case kHIDUsage_Button_3: + manipulateBitField(State.Buttons, Gamepad_B, buttonState); + break; + case kHIDUsage_Button_4: + manipulateBitField(State.Buttons, Gamepad_Y, buttonState); + break; + case 0x05: + manipulateBitField(State.Buttons, Gamepad_L1, buttonState); + break; + case 0x06: + manipulateBitField(State.Buttons, Gamepad_R1, buttonState); + break; + case 0x07: + State.LT = buttonState ? 1.0f:0.0f; + break; + case 0x08: + State.RT = buttonState ? 1.0f:0.0f; + break; + case 0x09: + manipulateBitField(State.Buttons, Gamepad_Back, buttonState); + break; + case 0x0A: + manipulateBitField(State.Buttons, Gamepad_Start, buttonState); + break; + case 0x0B: + manipulateBitField(State.Buttons, Gamepad_LStick, buttonState); + break; + case 0x0C: + manipulateBitField(State.Buttons, Gamepad_RStick, buttonState); + break; + default: + return; + } + } + else if (usagePage == kHIDPage_GenericDesktop) + { + float v; + switch(usage) + { + case kHIDUsage_GD_X: + v = mapAnalogAxis(value, element); + if (!setStateIfDifferent(State.LX, v)) + return; + break; + case kHIDUsage_GD_Y: + v = mapAnalogAxis(value, element); + if (!setStateIfDifferent(State.LY, -v)) + return; + break; + case kHIDUsage_GD_Z: + v = mapAnalogAxis(value, element); + if (!setStateIfDifferent(State.RX, v)) + return; + break; + case kHIDUsage_GD_Rz: + v = mapAnalogAxis(value, element); + if (!setStateIfDifferent(State.RY, -v)) + return; + break; + case kHIDUsage_GD_Hatswitch: + { + CFIndex integerValue = IOHIDValueGetIntegerValue(value); + + manipulateBitField(State.Buttons, + Gamepad_Up, + integerValue == 7 || integerValue == 0 || integerValue == 1); + manipulateBitField(State.Buttons, + Gamepad_Down, + integerValue == 3 || integerValue == 4 || integerValue == 5); + manipulateBitField(State.Buttons, + Gamepad_Left, + integerValue == 5 || integerValue == 6 || integerValue == 7); + manipulateBitField(State.Buttons, + Gamepad_Right, + integerValue == 1 || integerValue == 2 || integerValue == 3); + } + break; + default: + return; + } + } + } + // The following controller mapping is based on the Sony DualShock3, however we use it for + // all Sony devices on the assumption that they're likely to share the same mapping. + else if (vendorID == Sony_DualShock3_VendorID) + { + // PS3 Controller. + if (usagePage == kHIDPage_Button) + { + bool buttonState = IOHIDValueGetIntegerValue(value); + + switch(usage) + { + case kHIDUsage_Button_1: + manipulateBitField(State.Buttons, Gamepad_Back, buttonState); + break; + case kHIDUsage_Button_2: + manipulateBitField(State.Buttons, Gamepad_LStick, buttonState); + break; + case kHIDUsage_Button_3: + manipulateBitField(State.Buttons, Gamepad_RStick, buttonState); + break; + case kHIDUsage_Button_4: + manipulateBitField(State.Buttons, Gamepad_Start, buttonState); + break; + case 0x05: + manipulateBitField(State.Buttons, Gamepad_Up, buttonState); + break; + case 0x06: + manipulateBitField(State.Buttons, Gamepad_Right, buttonState); + break; + case 0x07: + manipulateBitField(State.Buttons, Gamepad_Down, buttonState); + break; + case 0x08: + manipulateBitField(State.Buttons, Gamepad_Left, buttonState); + break; + case 0x09: + State.LT = buttonState ? 1.0f:0.0f; + break; + case 0x0A: + State.RT = buttonState ? 1.0f:0.0f; + break; + case 0x0B: + manipulateBitField(State.Buttons, Gamepad_L1, buttonState); + break; + case 0x0C: + manipulateBitField(State.Buttons, Gamepad_R1, buttonState); + break; + case 0x0D: + // PS3 Triangle. + manipulateBitField(State.Buttons, Gamepad_TRIANGLE, buttonState); + break; + case 0x0E: + // PS3 Circle + manipulateBitField(State.Buttons, Gamepad_CIRCLE, buttonState); + break; + case 0x0F: + // PS3 Cross + manipulateBitField(State.Buttons, Gamepad_CROSS, buttonState); + break; + case 0x10: + // PS3 Square + manipulateBitField(State.Buttons, Gamepad_SQUARE, buttonState); + break; + default: + return; + } + } + else if (usagePage == kHIDPage_GenericDesktop) + { + float v; + switch(usage) + { + case kHIDUsage_GD_X: + v = mapAnalogAxis(value, element); + if (!setStateIfDifferent(State.LX, v)) + return; + break; + case kHIDUsage_GD_Y: + v = mapAnalogAxis(value, element); + if (!setStateIfDifferent(State.LY, -v)) + return; + break; + case kHIDUsage_GD_Z: + v = mapAnalogAxis(value, element); + if (!setStateIfDifferent(State.RX, v)) + return; + break; + case kHIDUsage_GD_Rz: + v = mapAnalogAxis(value, element); + if (!setStateIfDifferent(State.RY, -v)) + return; + break; + default: + return; + } + } + } + + bStateChanged = true; +} + +void GamepadManager::manipulateBitField(unsigned int& bitfield, unsigned int mask, bool val) +{ + if (val) + { + bitfield |= mask; + } + else + { + bitfield &= ~mask; + } +} + +}}} // OVR::Platform::OSX diff --git a/Samples/CommonSrc/Platform/OSX_Gamepad.h b/Samples/CommonSrc/Platform/OSX_Gamepad.h new file mode 100644 index 0000000..6d3344c --- /dev/null +++ b/Samples/CommonSrc/Platform/OSX_Gamepad.h @@ -0,0 +1,67 @@ +/************************************************************************************ + +Filename : OSX_Gamepad.h +Content : OSX implementation of Gamepad functionality. +Created : May 6, 2013 +Authors : Lee Cooper + +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_OSX_Gamepad_h +#define OVR_OSX_Gamepad_h + +#include "Gamepad.h" + +#include +#include + + +namespace OVR { namespace Platform { namespace OSX { + + +class GamepadManager : public Platform::GamepadManager +{ +public: + GamepadManager(); + ~GamepadManager(); + + virtual UInt32 GetGamepadCount(); + virtual bool GetGamepadState(UInt32 index, GamepadState* pState); + +private: + static void staticOnDeviceMatched(void* context, IOReturn result, void* sender, IOHIDDeviceRef device); + void onDeviceMatched(IOHIDDeviceRef device); + + static void staticOnDeviceRemoved(void* context, IOReturn result, void* sender, IOHIDDeviceRef device); + void onDeviceRemoved(IOHIDDeviceRef device); + + static void staticOnDeviceValueChanged(void* context, IOReturn result, void* sender, IOHIDValueRef value); + void onDeviceValueChanged(IOHIDValueRef value); + + int getIntDeviceProperty(IOHIDDeviceRef device, CFStringRef key); + float mapAnalogAxis(IOHIDValueRef value, IOHIDElementRef element); + void manipulateBitField(unsigned int& bitfield, unsigned int mask, bool val); + bool setStateIfDifferent(float& state, float newState); + + IOHIDManagerRef HidManager; + GamepadState State; + bool bStateChanged; +}; + +}}} + +#endif // OVR_OSX_Gamepad_h diff --git a/Samples/CommonSrc/Platform/OSX_Platform.h b/Samples/CommonSrc/Platform/OSX_Platform.h new file mode 100644 index 0000000..748c5fa --- /dev/null +++ b/Samples/CommonSrc/Platform/OSX_Platform.h @@ -0,0 +1,80 @@ + +#include "../Platform/Platform.h" +#include "../Render/Render_GL_Device.h" + +namespace OVR { namespace Platform { namespace OSX { + +class PlatformCore : public Platform::PlatformCore +{ +public: + void* Win; + void* View; + void* NsApp; + bool Quit; + int ExitCode; + int Width, Height; + MouseMode MMode; + + void RunIdle(); + +public: + PlatformCore(Application* app, void* nsapp); + ~PlatformCore(); + + bool SetupWindow(int w, int h); + void Exit(int exitcode); + + RenderDevice* SetupGraphics(const SetupGraphicsDeviceSet& setupGraphicsDesc, + const char* gtype, const Render::RendererParams& rp); + + void SetMouseMode(MouseMode mm); + void GetWindowSize(int* w, int* h) const; + + void SetWindowTitle(const char*title); + + void ShowWindow(bool show); + void DestroyWindow(); + bool SetFullscreen(const Render::RendererParams& rp, int fullscreen); + int GetDisplayCount(); + Render::DisplayId GetDisplay(int screen); + + String GetContentDirectory() const; +}; + +}} +namespace Render { namespace GL { namespace OSX { + +class RenderDevice : public Render::GL::RenderDevice +{ +public: + void* Context; + + RenderDevice(const Render::RendererParams& p, void* context) + : GL::RenderDevice(p), Context(context) {} + + virtual void Shutdown(); + virtual void Present(); + + virtual bool SetFullscreen(DisplayMode fullscreen); + + // oswnd = X11::PlatformCore* + static Render::RenderDevice* CreateDevice(const RendererParams& rp, void* oswnd); +}; + +}}}} + + +// OVR_PLATFORM_APP_ARGS specifies the Application class to use for startup, +// providing it with startup arguments. +#define OVR_PLATFORM_APP_ARGS(AppClass, args) \ +OVR::Platform::Application* OVR::Platform::Application::CreateApplication() \ +{ OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All)); \ +return new AppClass args; } \ +void OVR::Platform::Application::DestroyApplication(OVR::Platform::Application* app) \ +{ OVR::Platform::PlatformCore* platform = app->pPlatform; \ +delete app; delete platform; OVR::System::Destroy(); }; + +// OVR_PLATFORM_APP_ARGS specifies the Application startup class with no args. +#define OVR_PLATFORM_APP(AppClass) OVR_PLATFORM_APP_ARGS(AppClass, ()) + + diff --git a/Samples/CommonSrc/Platform/OSX_Platform.mm b/Samples/CommonSrc/Platform/OSX_Platform.mm new file mode 100644 index 0000000..4c7010f --- /dev/null +++ b/Samples/CommonSrc/Platform/OSX_Platform.mm @@ -0,0 +1,514 @@ + +#import "../Platform/OSX_PlatformObjc.h" + +using namespace OVR; +using namespace OVR::Platform; + +@implementation OVRApp + +- (void)dealloc +{ + [super dealloc]; +} + +- (void)run +{ + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + _running = YES; + OVR::Platform::Application* app; + { + using namespace OVR; + using namespace OVR::Platform; + + // CreateApplication must be the first call since it does OVR::System::Initialize. + app = Application::CreateApplication(); + OSX::PlatformCore* platform = new OSX::PlatformCore(app, self); + // The platform attached to an app will be deleted by DestroyApplication. + app->SetPlatformCore(platform); + + [self setApp:app]; + [self setPlatform:platform]; + + const char* argv[] = {"OVRApp"}; + int exitCode = app->OnStartup(1, argv); + if (exitCode) + { + Application::DestroyApplication(app); + exit(exitCode); + } + } + [self finishLaunching]; + [pool drain]; + + while ([self isRunning]) + { + pool = [[NSAutoreleasePool alloc] init]; + NSEvent* event = [self nextEventMatchingMask:NSAnyEventMask untilDate:nil inMode:NSDefaultRunLoopMode dequeue:YES]; + if (event) + { + [self sendEvent:event]; + } + _App->OnIdle(); + [pool drain]; + } + OVR::Platform::Application::DestroyApplication(app); +} + +@end + +static int KeyMap[][2] = +{ + { NSDeleteFunctionKey, OVR::Key_Delete }, + { '\t', OVR::Key_Tab }, + { '\n', OVR::Key_Return }, + { NSPauseFunctionKey, OVR::Key_Pause }, + { 27, OVR::Key_Escape }, + { 127, OVR::Key_Backspace }, + { ' ', OVR::Key_Space }, + { NSPageUpFunctionKey, OVR::Key_PageUp }, + { NSPageDownFunctionKey, OVR::Key_PageDown }, + { NSNextFunctionKey, OVR::Key_PageDown }, + { NSEndFunctionKey, OVR::Key_End }, + { NSHomeFunctionKey, OVR::Key_Home }, + { NSLeftArrowFunctionKey, OVR::Key_Left }, + { NSUpArrowFunctionKey, OVR::Key_Up }, + { NSRightArrowFunctionKey, OVR::Key_Right }, + { NSDownArrowFunctionKey, OVR::Key_Down }, + { NSInsertFunctionKey, OVR::Key_Insert }, + { NSDeleteFunctionKey, OVR::Key_Delete }, + { NSHelpFunctionKey, OVR::Key_Insert }, +}; + + +static KeyCode MapToKeyCode(wchar_t vk) +{ + unsigned key = Key_None; + + if ((vk >= 'a') && (vk <= 'z')) + { + key = vk - 'a' + Key_A; + } + else if ((vk >= ' ') && (vk <= '~')) + { + key = vk; + } + else if ((vk >= '0') && (vk <= '9')) + { + key = vk - '0' + Key_Num0; + } + else if ((vk >= NSF1FunctionKey) && (vk <= NSF15FunctionKey)) + { + key = vk - NSF1FunctionKey + Key_F1; + } + else + { + for (unsigned i = 0; i< (sizeof(KeyMap) / sizeof(KeyMap[1])); i++) + { + if (vk == KeyMap[i][0]) + { + key = KeyMap[i][1]; + break; + } + } + } + + return (KeyCode)key; +} + +static int MapModifiers(unsigned long xmod) +{ + int mod = 0; + if (xmod & NSShiftKeyMask) + mod |= OVR::Platform::Mod_Shift; + if (xmod & NSCommandKeyMask) + mod |= OVR::Platform::Mod_Control; + if (xmod & NSAlternateKeyMask) + mod |= OVR::Platform::Mod_Alt; + if (xmod & NSControlKeyMask) + mod |= OVR::Platform::Mod_Meta; + return mod; +} + +@implementation OVRView + +-(BOOL) acceptsFirstResponder +{ + return YES; +} +-(BOOL) acceptsFirstMouse:(NSEvent *)ev +{ + return YES; +} + ++(CGDirectDisplayID) displayFromScreen:(NSScreen *)s +{ + NSNumber* didref = (NSNumber*)[[s deviceDescription] objectForKey:@"NSScreenNumber"]; + CGDirectDisplayID disp = (CGDirectDisplayID)[didref longValue]; + return disp; +} + +-(void) warpMouseToCenter +{ + NSPoint w; + w.x = _Platform->Width/2.0f; + w.y = _Platform->Height/2.0f; + w = [[self window] convertBaseToScreen:w]; + CGDirectDisplayID disp = [OVRView displayFromScreen:[[self window] screen]]; + CGPoint p = {w.x, CGDisplayPixelsHigh(disp)-w.y}; + CGDisplayMoveCursorToPoint(disp, p); +} + +static bool LookupKey(NSEvent* ev, wchar_t& ch, OVR::KeyCode& key, unsigned& mods) +{ + NSString* chars = [ev charactersIgnoringModifiers]; + if ([chars length] == 0) + return false; + ch = [chars characterAtIndex:0]; + mods = MapModifiers([ev modifierFlags]); + + // check for Cmd+Latin Letter + NSString* modchars = [ev characters]; + if ([modchars length]) + { + wchar_t modch = [modchars characterAtIndex:0]; + if (modch >= 'a' && modch <= 'z') + ch = modch; + } + key = MapToKeyCode(ch); + return true; +} + +-(void) keyDown:(NSEvent*)ev +{ + OVR::KeyCode key; + unsigned mods; + wchar_t ch; + if (!LookupKey(ev, ch, key, mods)) + return; + if (key == Key_Escape && _Platform->MMode == Mouse_Relative) + { + [self warpMouseToCenter]; + CGAssociateMouseAndMouseCursorPosition(true); + [NSCursor unhide]; + _Platform->MMode = Mouse_RelativeEscaped; + } + _App->OnKey(key, ch, true, mods); +} +-(void) keyUp:(NSEvent*)ev +{ + OVR::KeyCode key; + unsigned mods; + wchar_t ch; + if (LookupKey(ev, ch, key, mods)) + _App->OnKey(key, ch, false, mods); +} + +static const OVR::KeyCode ModifierKeys[] = {OVR::Key_None, OVR::Key_Shift, OVR::Key_Control, OVR::Key_Alt, OVR::Key_Meta}; + +-(void)flagsChanged:(NSEvent *)ev +{ + unsigned long cmods = [ev modifierFlags]; + if ((cmods & 0xffff0000) != _Modifiers) + { + uint32_t mods = MapModifiers(cmods); + for (int i = 1; i <= 4; i++) + { + unsigned long m = (1 << (16+i)); + if ((cmods & m) != (_Modifiers & m)) + { + if (cmods & m) + _App->OnKey(ModifierKeys[i], 0, true, mods); + else + _App->OnKey(ModifierKeys[i], 0, false, mods); + } + } + _Modifiers = cmods & 0xffff0000; + } +} + +-(void)ProcessMouse:(NSEvent*)ev +{ + switch ([ev type]) + { + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: + case NSMouseMoved: + { + if (_Platform->MMode == OVR::Platform::Mouse_Relative) + { + int dx = [ev deltaX]; + int dy = [ev deltaY]; + + if (dx != 0 || dy != 0) + { + _App->OnMouseMove(dx, dy, Mod_MouseRelative|MapModifiers([ev modifierFlags])); + [self warpMouseToCenter]; + } + } + else + { + NSPoint p = [ev locationInWindow]; + _App->OnMouseMove(p.x, p.y, MapModifiers([ev modifierFlags])); + } + } + break; + case NSLeftMouseDown: + case NSRightMouseDown: + case NSOtherMouseDown: + break; + } +} + +-(void) mouseMoved:(NSEvent*)ev +{ + [self ProcessMouse:ev]; +} +-(void) mouseDragged:(NSEvent*)ev +{ + [self ProcessMouse:ev]; +} +-(void) mouseDown:(NSEvent*)ev +{ + if (_Platform->MMode == Mouse_RelativeEscaped) + { + [self warpMouseToCenter]; + CGAssociateMouseAndMouseCursorPosition(false); + [NSCursor hide]; + _Platform->MMode = Mouse_Relative; + } +} + +//-(void) + +-(id) initWithFrame:(NSRect)frameRect +{ + NSOpenGLPixelFormatAttribute attr[] = + {NSOpenGLPFAWindow, NSOpenGLPFADoubleBuffer, NSOpenGLPFADepthSize, 24, nil}; + + NSOpenGLPixelFormat *pf = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attr] autorelease]; + + self = [super initWithFrame:frameRect pixelFormat:pf]; + GLint swap = 0; + [[self openGLContext] setValues:&swap forParameter:NSOpenGLCPSwapInterval]; + //[self setWantsBestResolutionOpenGLSurface:YES]; + return self; +} + +-(void) reshape +{ + NSRect bounds = [self bounds]; + _App->OnResize(bounds.size.width, bounds.size.height); + + _Platform->Width = bounds.size.width; + _Platform->Height = bounds.size.height; + + if (_Platform->GetRenderer()) + _Platform->GetRenderer()->SetWindowSize(bounds.size.width, bounds.size.height); +} + +-(BOOL)windowShouldClose:(id)sender +{ + if (_Platform) + _Platform->Exit(0); + else + exit(0); + return 1; +} + +@end + +namespace OVR { namespace Platform { namespace OSX { + +PlatformCore::PlatformCore(Application* app, void* nsapp) + : Platform::PlatformCore(app), NsApp(nsapp), Win(NULL), View(NULL), Quit(0), MMode(Mouse_Normal) +{ + pGamepadManager = *new OSX::GamepadManager(); +} +PlatformCore::~PlatformCore() +{ +} + +void PlatformCore::Exit(int exitcode) +{ + OVRApp* nsApp = (OVRApp*)NsApp; + [nsApp stop:nil]; +} + +String PlatformCore::GetContentDirectory() const +{ + NSBundle* bundle = [NSBundle mainBundle]; + if (bundle) + return String([[bundle bundlePath] UTF8String]) + "/Contents/Resources"; + else + return "."; +} + + +void PlatformCore::SetMouseMode(MouseMode mm) +{ + if (mm == MMode) + return; + + if (Win) + { + if (mm == Mouse_Relative) + { + [NSCursor hide]; + [(OVRView*)View warpMouseToCenter]; + CGAssociateMouseAndMouseCursorPosition(false); + } + else + { + if (MMode == Mouse_Relative) + { + CGAssociateMouseAndMouseCursorPosition(true); + [NSCursor unhide]; + [(OVRView*)View warpMouseToCenter]; + } + } + } + MMode = mm; +} + + +void PlatformCore::GetWindowSize(int* w, int* h) const +{ + *w = Width; + *h = Height; +} + +bool PlatformCore::SetupWindow(int w, int h) +{ + NSRect winrect; + winrect.origin.x = 0; + winrect.origin.y = 1000; + winrect.size.width = w; + winrect.size.height = h; + NSWindow* win = [[NSWindow alloc] initWithContentRect:winrect styleMask:NSTitledWindowMask|NSClosableWindowMask backing:NSBackingStoreBuffered defer:NO]; + + OVRView* view = [[OVRView alloc] initWithFrame:winrect]; + [view setPlatform:this]; + [win setContentView:view]; + [win setAcceptsMouseMovedEvents:YES]; + [win setDelegate:view]; + [view setApp:pApp]; + Win = win; + View = view; + return 1; +} + +void PlatformCore::SetWindowTitle(const char* title) +{ + [((NSWindow*)Win) setTitle:[[NSString alloc] initWithBytes:title length:strlen(title) encoding:NSUTF8StringEncoding]]; +} + +void PlatformCore::ShowWindow(bool show) +{ + if (show) + [((NSWindow*)Win) makeKeyAndOrderFront:nil]; + else + [((NSWindow*)Win) orderOut:nil]; +} + +void PlatformCore::DestroyWindow() +{ + [((NSWindow*)Win) close]; + Win = NULL; +} + +RenderDevice* PlatformCore::SetupGraphics(const SetupGraphicsDeviceSet& setupGraphicsDesc, + const char* type, const Render::RendererParams& rp) +{ + const SetupGraphicsDeviceSet* setupDesc = setupGraphicsDesc.PickSetupDevice(type); + OVR_ASSERT(setupDesc); + + pRender = *setupDesc->pCreateDevice(rp, this); + if (pRender) + pRender->SetWindowSize(Width, Height); + + return pRender.GetPtr(); +} + +int PlatformCore::GetDisplayCount() +{ + return (int)[[NSScreen screens] count]; +} + +Render::DisplayId PlatformCore::GetDisplay(int i) +{ + NSScreen* s = (NSScreen*)[[NSScreen screens] objectAtIndex:i]; + return Render::DisplayId([OVRView displayFromScreen:s]); +} + +bool PlatformCore::SetFullscreen(const Render::RendererParams& rp, int fullscreen) +{ + if (fullscreen == Render::Display_Window) + [(OVRView*)View exitFullScreenModeWithOptions:nil]; + else + { + NSScreen* usescreen = [NSScreen mainScreen]; + NSArray* screens = [NSScreen screens]; + for (int i = 0; i < [screens count]; i++) + { + NSScreen* s = (NSScreen*)[screens objectAtIndex:i]; + CGDirectDisplayID disp = [OVRView displayFromScreen:s]; + + if (disp == rp.Display.CgDisplayId) + usescreen = s; + } + + [(OVRView*)View enterFullScreenMode:usescreen withOptions:nil]; + } + + if (pRender) + pRender->SetFullscreen((Render::DisplayMode)fullscreen); + return 1; +} + +}} +// GL +namespace Render { namespace GL { namespace OSX { + +Render::RenderDevice* RenderDevice::CreateDevice(const RendererParams& rp, void* oswnd) +{ + Platform::OSX::PlatformCore* PC = (Platform::OSX::PlatformCore*)oswnd; + + OVRView* view = (OVRView*)PC->View; + NSOpenGLContext *context = [view openGLContext]; + if (!context) + return NULL; + + [context makeCurrentContext]; + [((NSWindow*)PC->Win) makeKeyAndOrderFront:nil]; + + return new Render::GL::OSX::RenderDevice(rp, context); +} + +void RenderDevice::Present() +{ + NSOpenGLContext *context = (NSOpenGLContext*)Context; + [context flushBuffer]; +} + +void RenderDevice::Shutdown() +{ + Context = NULL; +} + +bool RenderDevice::SetFullscreen(DisplayMode fullscreen) +{ + Params.Fullscreen = fullscreen; + return 1; +} + +}}}} + + +int main(int argc, char *argv[]) +{ + NSApplication* nsapp = [OVRApp sharedApplication]; + [nsapp run]; + return 0; +} + diff --git a/Samples/CommonSrc/Platform/OSX_PlatformObjc.h b/Samples/CommonSrc/Platform/OSX_PlatformObjc.h new file mode 100644 index 0000000..7e69a4d --- /dev/null +++ b/Samples/CommonSrc/Platform/OSX_PlatformObjc.h @@ -0,0 +1,31 @@ + +#import +#import "OSX_Platform.h" +#import "OSX_Gamepad.h" + +#import +#import + +@interface OVRApp : NSApplication + +@property (assign) IBOutlet NSWindow* win; +@property (assign) OVR::Platform::OSX::PlatformCore* Platform; +@property (assign) OVR::Platform::Application* App; + +-(void) run; + +@end + +@interface OVRView : NSOpenGLView + +@property (assign) OVR::Platform::OSX::PlatformCore* Platform; +@property (assign) OVR::Platform::Application* App; +@property unsigned long Modifiers; + +-(void)ProcessMouse:(NSEvent*)event; +-(void)warpMouseToCenter; + ++(CGDirectDisplayID) displayFromScreen:(NSScreen*)s; + +@end + diff --git a/Samples/CommonSrc/Platform/OSX_WavPlayer.cpp b/Samples/CommonSrc/Platform/OSX_WavPlayer.cpp new file mode 100644 index 0000000..6119888 --- /dev/null +++ b/Samples/CommonSrc/Platform/OSX_WavPlayer.cpp @@ -0,0 +1,242 @@ +/************************************************************************************ + +Filename : WavPlayer_OSX.cpp +Content : An Apple OSX audio handler. +Created : March 5, 2013 +Authors : Robotic Arm Software - Peter Hoff, Dan Goodman, Bryan Croteau + +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. + +Use of this software is subject to the terms of the Oculus LLC license +agreement provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +************************************************************************************/ + +#include "OSX_WavPlayer.h" + +namespace OVR { namespace Platform { namespace OSX { + +WavPlayer::WavPlayer(const char* fileName) +{ + FileName = fileName; +} + +bool WavPlayer::isDataChunk(unsigned char* buffer, int index) +{ + unsigned char a = buffer[index]; + unsigned char b = buffer[index + 1]; + unsigned char c = buffer[index + 2]; + unsigned char d = buffer[index + 3]; + return (a == 'D' || a == 'd') && (b == 'A' || b == 'a') && + (c == 'T' || c == 't') && (d == 'A' || d == 'a'); +} + +int WavPlayer::getWord(unsigned char* buffer, int index) +{ + unsigned char a = buffer[index]; + unsigned char b = buffer[index + 1]; + unsigned char c = buffer[index + 2]; + unsigned char d = buffer[index + 3]; + int result = 0; + result |= a; + result |= b << 8; + result |= c << 16; + result |= d << 24; + return result; +} + +short WavPlayer::getHalf(unsigned char* buffer, int index) +{ + unsigned char a = buffer[index]; + unsigned char b = buffer[index + 1]; + short result = 0; + result |= a; + result |= b << 8; + return result; +} + +void *WavPlayer::LoadPCM(const char *filename, unsigned long *len) +{ + FILE *file; + struct stat s; + void *pcm; + + if(stat(filename, &s)) + { + return NULL; + } + *len = s.st_size; + pcm = (void *) malloc(s.st_size); + if(!pcm) + { + return NULL; + } + file = fopen(filename, "rb"); + if(!file) + { + free(pcm); + return NULL; + } + fread(pcm, s.st_size, 1, file); + fclose(file); + return pcm; +} + +int WavPlayer::PlayBuffer(void *pcmbuffer, unsigned long len) +{ + AQCallbackStruct aqc; + UInt32 err, bufferSize; + int i; + + aqc.DataFormat.mSampleRate = SampleRate; + aqc.DataFormat.mFormatID = kAudioFormatLinearPCM; + if(BitsPerSample == 16) + { + aqc.DataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger + | kAudioFormatFlagIsPacked; + } + aqc.DataFormat.mBytesPerPacket = NumChannels * (BitsPerSample / 8); + aqc.DataFormat.mFramesPerPacket = 1; + aqc.DataFormat.mBytesPerFrame = NumChannels * (BitsPerSample / 8); + aqc.DataFormat.mChannelsPerFrame = NumChannels; + aqc.DataFormat.mBitsPerChannel = BitsPerSample; + aqc.FrameCount = SampleRate / 60; + aqc.SampleLen = (UInt32)(len); + aqc.PlayPtr = 0; + aqc.PCMBuffer = static_cast(pcmbuffer); + + err = AudioQueueNewOutput(&aqc.DataFormat, + aqBufferCallback, + &aqc, + NULL, + kCFRunLoopCommonModes, + 0, + &aqc.Queue); + if(err) + { + return err; + } + + aqc.FrameCount = SampleRate / 60; + bufferSize = aqc.FrameCount * aqc.DataFormat.mBytesPerPacket; + + for(i = 0; i < AUDIO_BUFFERS; i++) + { + err = AudioQueueAllocateBuffer(aqc.Queue, bufferSize, + &aqc.Buffers[i]); + if(err) + { + return err; + } + aqBufferCallback(&aqc, aqc.Queue, aqc.Buffers[i]); + } + + err = AudioQueueStart(aqc.Queue, NULL); + if(err) + { + return err; + } + + while(true) + { + } + sleep(1); + return 0; +} + +void WavPlayer::aqBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB) +{ + AQCallbackStruct *aqc; + unsigned char *coreAudioBuffer; + + aqc = (AQCallbackStruct *) in; + coreAudioBuffer = (unsigned char*) outQB->mAudioData; + + printf("Sync: %u / %u\n", aqc->PlayPtr, aqc->SampleLen); + + if(aqc->FrameCount > 0) + { + outQB->mAudioDataByteSize = aqc->DataFormat.mBytesPerFrame * aqc->FrameCount; + for(int i = 0; i < aqc->FrameCount * aqc->DataFormat.mBytesPerFrame; i++) + { + if(aqc->PlayPtr > aqc->SampleLen) + { + aqc->PlayPtr = 0; + i = 0; + } + coreAudioBuffer[i] = aqc->PCMBuffer[aqc->PlayPtr]; + aqc->PlayPtr++; + } + AudioQueueEnqueueBuffer(inQ, outQB, 0, NULL); + } +} + +int WavPlayer::PlayAudio() +{ + unsigned long len; + void *pcmbuffer; + int ret; + + pcmbuffer = LoadPCM(FileName, &len); + if(!pcmbuffer) + { + fprintf(stderr, "%s: %s\n", FileName, strerror(errno)); + exit(EXIT_FAILURE); + } + + unsigned char* bytes = (unsigned char*)pcmbuffer; + int index = 0; + + // 'RIFF' + getWord(bytes, index); + index += 4; + // int Length + getWord(bytes, index); + index += 4; + // 'WAVE' + getWord(bytes, index); + index += 4; + // 'fmt ' + getWord(bytes, index); + index += 4; + + // int Format Length + int fmtLen = getWord(bytes, index); + index += 4; + AudioFormat = getHalf(bytes, index); + index += 2; + NumChannels = getHalf(bytes, index); + index += 2; + SampleRate = getWord(bytes, index); + index += 4; + ByteRate = getWord(bytes, index); + index += 4; + BlockAlign = getHalf(bytes, index); + index += 2; + BitsPerSample = getHalf(bytes, index); + index += 2; + index += fmtLen - 16; + while(!isDataChunk(bytes, index)) + { + // Any Chunk + getWord(bytes, index); + index += 4; + // Any Chunk Length + int anyChunkLen = getWord(bytes, index); + index += 4 + anyChunkLen; + } + // 'data' + getWord(bytes, index); + index += 4; + // int Data Length + unsigned long dataLen = getWord(bytes, index); + index += 4; + unsigned char* target = &bytes[index]; + + ret = PlayBuffer((void *)target, dataLen); + free(pcmbuffer); + return ret; +} + +}}} diff --git a/Samples/CommonSrc/Platform/OSX_WavPlayer.h b/Samples/CommonSrc/Platform/OSX_WavPlayer.h new file mode 100644 index 0000000..1b88b8c --- /dev/null +++ b/Samples/CommonSrc/Platform/OSX_WavPlayer.h @@ -0,0 +1,64 @@ +/************************************************************************************ + +Filename : WavPlayer_OSX.h +Content : An Apple OSX audio handler. +Created : March 5, 2013 +Authors : Robotic Arm Software - Peter Hoff, Dan Goodman, Bryan Croteau + +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. + +Use of this software is subject to the terms of the Oculus LLC license +agreement provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +************************************************************************************/ + +#ifndef OVR_WavPlayer_h +#define OVR_WavPlayer_h + +#include +#include +#include +#include +#include + +#define AUDIO_BUFFERS 4 + +namespace OVR { namespace Platform { namespace OSX { + +typedef struct AQCallbackStruct +{ + AudioQueueRef Queue; + UInt32 FrameCount; + AudioQueueBufferRef Buffers[AUDIO_BUFFERS]; + AudioStreamBasicDescription DataFormat; + UInt32 PlayPtr; + UInt32 SampleLen; + unsigned char* PCMBuffer; +} AQCallbackStruct; + +class WavPlayer +{ +public: + WavPlayer(const char* fileName); + int PlayAudio(); +private: + bool isDataChunk(unsigned char* buffer, int index); + int getWord(unsigned char* buffer, int index); + short getHalf(unsigned char* buffer, int index); + void *LoadPCM(const char *filename, unsigned long *len); + int PlayBuffer(void *pcm, unsigned long len); + static void aqBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB); + + short AudioFormat; + short NumChannels; + int SampleRate; + int ByteRate; + short BlockAlign; + short BitsPerSample; + const char* FileName; +}; + +}}} + +#endif diff --git a/Samples/CommonSrc/Platform/Platform.cpp b/Samples/CommonSrc/Platform/Platform.cpp new file mode 100644 index 0000000..bf5b8a5 --- /dev/null +++ b/Samples/CommonSrc/Platform/Platform.cpp @@ -0,0 +1,75 @@ +/************************************************************************************ + +Filename : Platform.cpp +Content : Platform-independent app framework for Oculus samples +Created : September 6, 2012 +Authors : Andrew Reisse + +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + + + +#include "Platform.h" +#include +#include +#include "../Render/Render_Device.h" +#include "Gamepad.h" + +namespace OVR { namespace Platform { + + +const SetupGraphicsDeviceSet* SetupGraphicsDeviceSet::PickSetupDevice(const char* typeArg) const +{ + // Search for graphics creation object that matches type arg. + if (typeArg) + { + for (const SetupGraphicsDeviceSet* p = this; p != 0; p = p->pNext) + { + if (!OVR_stricmp(p->pTypeArg, typeArg)) + return p; + } + } + return this; +} + +//------------------------------------------------------------------------------------- + +PlatformCore::PlatformCore(Application *app) +{ + pApp = app; + pApp->SetPlatformCore(this); + StartupTicks = OVR::Timer::GetTicks(); +} + +double PlatformCore::GetAppTime() const +{ + return (OVR::Timer::GetTicks() - StartupTicks) * (1.0 / (double)OVR::Timer::MksPerSecond); +} + +bool PlatformCore::SetFullscreen(const Render::RendererParams&, int fullscreen) +{ + if (pRender) + return pRender->SetFullscreen((Render::DisplayMode)fullscreen); + return 0; +} + +Render::DisplayId PlatformCore::GetDisplay(int screen) +{ + OVR_UNUSED(screen); return Render::DisplayId(); +} + +}} diff --git a/Samples/CommonSrc/Platform/Platform.h b/Samples/CommonSrc/Platform/Platform.h new file mode 100644 index 0000000..8ef4593 --- /dev/null +++ b/Samples/CommonSrc/Platform/Platform.h @@ -0,0 +1,190 @@ +/************************************************************************************ + +Filename : Platform.h +Content : Platform-independent app and rendering framework for Oculus samples +Created : September 6, 2012 +Authors : Andrew Reisse + +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_Platform_h +#define OVR_Platform_h + +#include "OVR.h" + +#include "Kernel/OVR_KeyCodes.h" + +namespace OVR { namespace Render { + class RenderDevice; + struct DisplayId; + struct RendererParams; +}} + +namespace OVR { namespace Platform { + +using Render::RenderDevice; + +class PlatformCore; +class Application; +class GamepadManager; + +// MouseMode configures mouse input behavior of the app. Three states are +// currently supported: +// Normal - Reports absolute coordinates with cursor shown. +// Relative - Reports relative delta coordinates with cursor hidden +// until 'Esc' key is pressed or window loses focus. +// RelativeEscaped - Relative input is desired, but has been escaped until +// mouse is clicked in the window, which will return the state +// to relative. Absolute coordinates are reported. + +enum MouseMode +{ + Mouse_Normal, + Mouse_Relative, // Cursor hidden, mouse grab, OnMouseMove reports relative deltas. + Mouse_RelativeEscaped, // Clicking in window will return to Relative state. +}; + + +enum Modifiers +{ + Mod_Shift = 0x001, + Mod_Control = 0x002, + Mod_Meta = 0x004, + Mod_Alt = 0x008, + + // Set for input Mouse_Relative mode, indicating that x,y are relative deltas. + Mod_MouseRelative = 0x100, +}; + +//------------------------------------------------------------------------------------- +// ***** SetupGraphicsDeviceSet + +typedef RenderDevice* (*RenderDeviceCreateFunc)(const Render::RendererParams&, void*); + +// SetupGraphicsDeviceSet is a PlatformCore::SetupGraphics initialization helper class, +// used to build up a list of RenderDevices that can be used for rendering. +// Specifying a smaller set allows application to avoid linking unused graphics devices. +struct SetupGraphicsDeviceSet +{ + SetupGraphicsDeviceSet(const char* typeArg, RenderDeviceCreateFunc createFunc) + : pTypeArg(typeArg), pCreateDevice(createFunc), pNext(0) { } + SetupGraphicsDeviceSet(const char* typeArg, RenderDeviceCreateFunc createFunc, + const SetupGraphicsDeviceSet& next) + : pTypeArg(typeArg), pCreateDevice(createFunc), pNext(&next) { } + + // Selects graphics object based on type string; returns 'this' if not found. + const SetupGraphicsDeviceSet* PickSetupDevice(const char* typeArg) const; + + const char* pTypeArg; + RenderDeviceCreateFunc pCreateDevice; + +private: + const SetupGraphicsDeviceSet* pNext; +}; + +//------------------------------------------------------------------------------------- +// ***** PlatformCore + +// PlatformCore defines abstract system window/viewport setup functionality and +// maintains a renderer. This class is separated from Application because it can have +// derived platform-specific implementations. +// Specific implementation classes are hidden within platform-specific versions +// such as Win32::PlatformCore. + +class PlatformCore : public NewOverrideBase +{ +protected: + Application* pApp; + Ptr pRender; + Ptr pGamepadManager; + UInt64 StartupTicks; + +public: + PlatformCore(Application *app); + virtual ~PlatformCore() { } + Application* GetApp() { return pApp; } + RenderDevice* GetRenderer() const { return pRender; } + GamepadManager* GetGamepadManager() const { return pGamepadManager; } + + virtual bool SetupWindow(int w, int h) = 0; + // Destroys window and also releases renderer. + virtual void DestroyWindow() = 0; + virtual void Exit(int exitcode) = 0; + + virtual void ShowWindow(bool visible) = 0; + + virtual bool SetFullscreen(const Render::RendererParams& rp, int fullscreen); + + // Search for a matching graphics renderer based on type argument and initializes it. + virtual RenderDevice* SetupGraphics(const SetupGraphicsDeviceSet& setupGraphicsDesc, + const char* gtype, + const Render::RendererParams& rp) = 0; + + virtual void SetMouseMode(MouseMode mm) { OVR_UNUSED(mm); } + + virtual void GetWindowSize(int* w, int* h) const = 0; + + virtual void SetWindowTitle(const char*title) = 0; + virtual void PlayMusicFile(const char *fileName) { OVR_UNUSED(fileName); } + virtual int GetDisplayCount() { return 0; } + virtual Render::DisplayId GetDisplay(int screen); + + // Get time since start of application in seconds. + double GetAppTime() const; + + virtual String GetContentDirectory() const { return "."; } +}; + +//------------------------------------------------------------------------------------- +// PlatformApp is a base application class from which end-user application +// classes derive. + +class Application : public NewOverrideBase +{ +protected: + class PlatformCore* pPlatform; + +public: + virtual ~Application() { } + + virtual int OnStartup(int argc, const char** argv) = 0; + virtual void OnQuitRequest() { pPlatform->Exit(0); } + + virtual void OnIdle() {} + + virtual void OnKey(KeyCode key, int chr, bool down, int modifiers) + { OVR_UNUSED4(key, chr, down, modifiers); } + virtual void OnMouseMove(int x, int y, int modifiers) + { OVR_UNUSED3(x, y, modifiers); } + + virtual void OnResize(int width, int height) + { OVR_UNUSED2(width, height); } + + void SetPlatformCore(PlatformCore* p) { pPlatform = p; } + PlatformCore* GetPlatformCore() const { return pPlatform; } + + + // Static functions defined by OVR_PLATFORM_APP and used to initialize and + // shut down the application class. + static Application* CreateApplication(); + static void DestroyApplication(Application* app); +}; + + +}} + +#endif diff --git a/Samples/CommonSrc/Platform/Platform_Default.h b/Samples/CommonSrc/Platform/Platform_Default.h new file mode 100644 index 0000000..d82be10 --- /dev/null +++ b/Samples/CommonSrc/Platform/Platform_Default.h @@ -0,0 +1,59 @@ +/************************************************************************************ + +Filename : Platform_Default.h +Content : Default Platform class and RenderDevice selection file +Created : October 4, 2012 +Authors : + +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*************************************************************************************/ + +#ifndef OVR_Platform_Default_h +#define OVR_Platform_Default_h + +// This should select proper header file for the platform/compiler. +#include + +#if defined(OVR_OS_WIN32) + #include "Win32_Platform.h" + + #include "../Render/Render_D3D11_Device.h" + #undef OVR_D3D_VERSION + #include "../Render/Render_D3D10_Device.h" +// #include "../Render/Render_GL_Win32_Device.h" + +// Modify this list or pass a smaller set to select a specific render device, +// while avoiding linking extra classes. + #define OVR_DEFAULT_RENDER_DEVICE_SET \ + SetupGraphicsDeviceSet("D3D11", &OVR::Render::D3D11::RenderDevice::CreateDevice, \ + SetupGraphicsDeviceSet("D3D10", &OVR::Render::D3D10::RenderDevice::CreateDevice) ) + +#elif defined(OVR_OS_MAC) && !defined(OVR_MAC_X11) + #include "OSX_Platform.h" + + #define OVR_DEFAULT_RENDER_DEVICE_SET \ + SetupGraphicsDeviceSet("GL", &OVR::Render::GL::OSX::RenderDevice::CreateDevice) + +#else + + #include "X11_Platform.h" + + #define OVR_DEFAULT_RENDER_DEVICE_SET \ + SetupGraphicsDeviceSet("GL", &OVR::Render::GL::X11::RenderDevice::CreateDevice) + +#endif + +#endif // OVR_Platform_Default_h diff --git a/Samples/CommonSrc/Platform/Win32_Gamepad.cpp b/Samples/CommonSrc/Platform/Win32_Gamepad.cpp new file mode 100644 index 0000000..db6524a --- /dev/null +++ b/Samples/CommonSrc/Platform/Win32_Gamepad.cpp @@ -0,0 +1,101 @@ +/************************************************************************************ + +Filename : Win32_Gamepad.cpp +Content : Win32 implementation of Platform app infrastructure +Created : May 6, 2013 +Authors : Lee Cooper + +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#include "Win32_Gamepad.h" + +namespace OVR { namespace Platform { namespace Win32 { + +GamepadManager::GamepadManager() +{ + hXInputModule = ::LoadLibraryA("Xinput9_1_0.dll"); + if (hXInputModule) + { + pXInputGetState = (PFn_XInputGetState) + ::GetProcAddress(hXInputModule, "XInputGetState"); + } +} + +GamepadManager::~GamepadManager() +{ + if (hXInputModule) + ::FreeLibrary(hXInputModule); +} + +static inline float GamepadStick(short in) +{ + float v; + if (abs(in) < 9000) + return 0; + else if (in > 9000) + v = (float) in - 9000; + else + v = (float) in + 9000; + return v / (32767 - 9000); +} + +static inline float GamepadTrigger(BYTE in) +{ + if (in < 30) + return 0; + else + return float(in-30) / 225; +} + +UInt32 GamepadManager::GetGamepadCount() +{ + return 1; +} + +bool GamepadManager::GetGamepadState(UInt32 index, GamepadState* pState) +{ + // For now we just support one gamepad. + OVR_UNUSED(index); + + if (pXInputGetState) + { + XINPUT_STATE xis; + + if (pXInputGetState(0, &xis)) + return false; + + if (xis.dwPacketNumber == LastPadPacketNo) + return false; + + // State changed. + pState->Buttons = xis.Gamepad.wButtons; // Currently matches Xinput + pState->LT = GamepadTrigger(xis.Gamepad.bLeftTrigger); + pState->RT = GamepadTrigger(xis.Gamepad.bRightTrigger); + pState->LX = GamepadStick(xis.Gamepad.sThumbLX); + pState->LY = GamepadStick(xis.Gamepad.sThumbLY); + pState->RX = GamepadStick(xis.Gamepad.sThumbRX); + pState->RY = GamepadStick(xis.Gamepad.sThumbRY); + + LastPadPacketNo = xis.dwPacketNumber; + + return true; + } + + return false; +} + +}}} // OVR::Platform::Win32 diff --git a/Samples/CommonSrc/Platform/Win32_Gamepad.h b/Samples/CommonSrc/Platform/Win32_Gamepad.h new file mode 100644 index 0000000..9066798 --- /dev/null +++ b/Samples/CommonSrc/Platform/Win32_Gamepad.h @@ -0,0 +1,54 @@ +/************************************************************************************ + +Filename : Win32_Gamepad.h +Content : Win32 implementation of Gamepad functionality. +Created : May 6, 2013 +Authors : Lee Cooper + +Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_Win32_Gamepad_h +#define OVR_Win32_Gamepad_h + +#include "Gamepad.h" + +#include +#include + +namespace OVR { namespace Platform { namespace Win32 { + +class GamepadManager : public Platform::GamepadManager +{ +public: + GamepadManager(); + ~GamepadManager(); + + virtual UInt32 GetGamepadCount(); + virtual bool GetGamepadState(UInt32 index, GamepadState* pState); + +private: + // Dynamically ink to XInput to simplify projects. + HMODULE hXInputModule; + typedef DWORD (WINAPI *PFn_XInputGetState)(DWORD dwUserIndex, XINPUT_STATE* pState); + PFn_XInputGetState pXInputGetState; + + UInt32 LastPadPacketNo; +}; + +}}} + +#endif // OVR_Win32_Gamepad_h diff --git a/Samples/CommonSrc/Platform/Win32_Platform.cpp b/Samples/CommonSrc/Platform/Win32_Platform.cpp new file mode 100644 index 0000000..cdd1e1f --- /dev/null +++ b/Samples/CommonSrc/Platform/Win32_Platform.cpp @@ -0,0 +1,600 @@ +/************************************************************************************ + +Filename : Win32_Platform.cpp +Content : Win32 implementation of Platform app infrastructure +Created : September 6, 2012 +Authors : Andrew Reisse + +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#include "Kernel/OVR_System.h" +#include "Kernel/OVR_Array.h" +#include "Kernel/OVR_String.h" + +#include "Win32_Platform.h" +#include "Win32_Gamepad.h" +#include "../Render/Render_Device.h" + +namespace OVR { namespace Platform { namespace Win32 { + + +PlatformCore::PlatformCore(Application* app, HINSTANCE hinst) + : Platform::PlatformCore(app), hWnd(NULL), hInstance(hinst), Quit(0), MMode(Mouse_Normal), + Cursor(0), Modifiers(0), WindowTitle("App") +{ + pGamepadManager = *new Win32::GamepadManager(); +} + +PlatformCore::~PlatformCore() +{ +} + +bool PlatformCore::SetupWindow(int w, int h) +{ + WNDCLASS wc; + memset(&wc, 0, sizeof(wc)); + wc.lpszClassName = L"OVRAppWindow"; + wc.style = CS_OWNDC; + wc.lpfnWndProc = systemWindowProc; + wc.cbWndExtra = sizeof(PlatformCore*); + + RegisterClass(&wc); + + Width = w; + Height = h; + RECT winSize; + winSize.left = winSize.top = 0; + winSize.right = Width; + winSize.bottom = Height; + AdjustWindowRect(&winSize, WS_OVERLAPPEDWINDOW, false); + hWnd = CreateWindowA("OVRAppWindow", WindowTitle.ToCStr(), WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, + // 1950, 10, + winSize.right-winSize.left, winSize.bottom-winSize.top, + NULL, NULL, hInstance, (LPVOID)this); + Modifiers = 0; + + Cursor = LoadCursor(NULL, IDC_CROSS); + + // Initialize Window center in screen coordinates + POINT center = { Width / 2, Height / 2 }; + ::ClientToScreen(hWnd, ¢er); + WindowCenter = center; + + if (MMode == Mouse_Relative) + { + ::SetCursorPos(WindowCenter.x, WindowCenter.y); + ShowCursor(FALSE); + } + ::SetFocus(hWnd); + + return (hWnd != NULL); +} + +void PlatformCore::DestroyWindow() +{ + // Release renderer. + pRender.Clear(); + + // Release gamepad. + pGamepadManager.Clear(); + + // Release window resources. + ::DestroyWindow(hWnd); + UnregisterClass(L"OVRAppWindow", hInstance); + hWnd = 0; + Width = Height = 0; + + //DestroyCursor(Cursor); + Cursor = 0; +} + +void PlatformCore::ShowWindow(bool visible) +{ + ::ShowWindow(hWnd, visible ? SW_SHOW : SW_HIDE); +} + +void PlatformCore::SetMouseMode(MouseMode mm) +{ + if (mm == MMode) + return; + + if (hWnd) + { + if (mm == Mouse_Relative) + { + ShowCursor(FALSE); + ::SetCursorPos(WindowCenter.x, WindowCenter.y); + } + else + { + if (MMode == Mouse_Relative) + ShowCursor(TRUE); + } + } + MMode = mm; +} + +void PlatformCore::GetWindowSize(int* w, int* h) const +{ + *w = Width; + *h = Height; +} + + +void PlatformCore::SetWindowTitle(const char* title) +{ + WindowTitle = title; + if (hWnd) + ::SetWindowTextA(hWnd, title); +} + +static UByte KeyMap[][2] = +{ + { VK_BACK, Key_Backspace }, + { VK_TAB, Key_Tab }, + { VK_CLEAR, Key_Clear }, + { VK_RETURN, Key_Return }, + { VK_SHIFT, Key_Shift }, + { VK_CONTROL, Key_Control }, + { VK_MENU, Key_Alt }, + { VK_PAUSE, Key_Pause }, + { VK_CAPITAL, Key_CapsLock }, + { VK_ESCAPE, Key_Escape }, + { VK_SPACE, Key_Space }, + { VK_PRIOR, Key_PageUp }, + { VK_NEXT, Key_PageDown }, + { VK_END, Key_End }, + { VK_HOME, Key_Home }, + { VK_LEFT, Key_Left }, + { VK_UP, Key_Up }, + { VK_RIGHT, Key_Right }, + { VK_DOWN, Key_Down }, + { VK_INSERT, Key_Insert }, + { VK_DELETE, Key_Delete }, + { VK_HELP, Key_Help }, + + { VK_NUMLOCK, Key_NumLock }, + { VK_SCROLL, Key_ScrollLock }, + + { VK_OEM_1, Key_Semicolon }, + { VK_OEM_PLUS, Key_Equal }, + { VK_OEM_COMMA, Key_Comma }, + { VK_OEM_MINUS, Key_Minus }, + { VK_OEM_PERIOD,Key_Period }, + { VK_OEM_2, Key_Slash }, + { VK_OEM_3, Key_Bar }, + { VK_OEM_4, Key_BracketLeft }, + { VK_OEM_5, Key_Backslash }, + { VK_OEM_6, Key_BracketRight }, + { VK_OEM_7, Key_Quote }, + + { VK_OEM_AX, Key_OEM_AX }, // 'AX' key on Japanese AX keyboard. + { VK_OEM_102, Key_OEM_102 }, // "<>" or "\|" on RT 102-key keyboard. + { VK_ICO_HELP, Key_ICO_HELP }, + { VK_ICO_00, Key_ICO_00 } +}; + + +KeyCode MapVKToKeyCode(unsigned vk) +{ + unsigned key = Key_None; + + if ((vk >= '0') && (vk <= '9')) + { + key = vk - '0' + Key_Num0; + } + else if ((vk >= 'A') && (vk <= 'Z')) + { + key = vk - 'A' + Key_A; + } + else if ((vk >= VK_NUMPAD0) && (vk <= VK_DIVIDE)) + { + key = vk - VK_NUMPAD0 + Key_KP_0; + } + else if ((vk >= VK_F1) && (vk <= VK_F15)) + { + key = vk - VK_F1 + Key_F1; + } + else + { + for (unsigned i = 0; i< (sizeof(KeyMap) / sizeof(KeyMap[1])); i++) + { + if (vk == KeyMap[i][0]) + { + key = KeyMap[i][1]; + break; + } + } + } + + return (KeyCode)key; +} + + + +LRESULT CALLBACK PlatformCore::systemWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) +{ + PlatformCore* self; + + // WM_NCCREATE should be the first message to come it; use it to set class pointer. + if (msg == WM_NCCREATE) + { + self = static_cast(((LPCREATESTRUCT)lp)->lpCreateParams); + + if (self) + { + SetWindowLongPtr(hwnd, 0, (LONG_PTR)self); + self->hWnd = hwnd; + } + } + else + { + self = (PlatformCore*)(UPInt)GetWindowLongPtr(hwnd, 0); + } + + return self ? self->WindowProc(msg, wp, lp) : + DefWindowProc(hwnd, msg, wp, lp); +} + + +LRESULT PlatformCore::WindowProc(UINT msg, WPARAM wp, LPARAM lp) +{ + KeyCode keyCode; + + switch (msg) + { + case WM_PAINT: + { + PAINTSTRUCT ps; + BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + } + return 0; + + case WM_SETCURSOR: + ::SetCursor(Cursor); + return 0; + + case WM_MOUSEMOVE: + if (MMode == Mouse_Relative) + { + POINT newPos = { LOWORD(lp), HIWORD(lp) }; + ::ClientToScreen(hWnd, &newPos); + if ((newPos.x == WindowCenter.x) && (newPos.y == WindowCenter.y)) + break; + ::SetCursorPos(WindowCenter.x, WindowCenter.y); + + LONG dx = newPos.x - WindowCenter.x; + LONG dy = newPos.y - WindowCenter.y; + + pApp->OnMouseMove(dx, dy, Mod_MouseRelative); + } + else + { + pApp->OnMouseMove(LOWORD(lp), HIWORD(lp), 0); + } + break; + + case WM_MOVE: + { + RECT r; + GetClientRect(hWnd, &r); + WindowCenter.x = r.right/2; + WindowCenter.y = r.bottom/2; + ::ClientToScreen(hWnd, &WindowCenter); + } + break; + + case WM_KEYDOWN: + switch (wp) + { + case VK_CONTROL: Modifiers |= Mod_Control; break; + case VK_MENU: Modifiers |= Mod_Alt; break; + case VK_SHIFT: Modifiers |= Mod_Shift; break; + case VK_LWIN: + case VK_RWIN: Modifiers |= Mod_Meta; break; + } + if ((keyCode = MapVKToKeyCode((unsigned)wp)) != Key_None) + pApp->OnKey(keyCode, 0, true, Modifiers); + + if (keyCode == Key_Escape && MMode == Mouse_Relative) + { + MMode = Mouse_RelativeEscaped; + ShowCursor(TRUE); + } + break; + + case WM_KEYUP: + if ((keyCode = MapVKToKeyCode((unsigned)wp)) != Key_None) + pApp->OnKey(keyCode, 0, false, Modifiers); + switch (wp) + { + case VK_CONTROL: Modifiers &= ~Mod_Control; break; + case VK_MENU: Modifiers &= ~Mod_Alt; break; + case VK_SHIFT: Modifiers &= ~Mod_Shift; break; + case VK_LWIN: + case VK_RWIN: Modifiers &= ~Mod_Meta; break; + } + break; + + case WM_LBUTTONDOWN: + //App->OnMouseButton(0, + + ::SetCapture(hWnd); + + if (MMode == Mouse_RelativeEscaped) + { + ::SetCursorPos(WindowCenter.x, WindowCenter.y); + ::ShowCursor(FALSE); + MMode = Mouse_Relative; + } + break; + + case WM_LBUTTONUP: + ReleaseCapture(); + break; + + case WM_SETFOCUS: + // Do NOT restore the Relative mode here, since calling SetCursorPos + // would screw up titlebar window dragging. + // Let users click in the center instead to resume. + break; + + case WM_KILLFOCUS: + if (MMode == Mouse_Relative) + { + MMode = Mouse_RelativeEscaped; + ShowCursor(TRUE); + } + break; + + case WM_SIZE: + // Change window size as long as we're not being minimized. + if (wp != SIZE_MINIMIZED) + { + Width = LOWORD(lp); + Height = HIWORD(lp); + if (pRender) + pRender->SetWindowSize(Width, Height); + pApp->OnResize(Width,Height); + } + break; + + case WM_STYLECHANGING: + // Resize the window. This is needed because the size includes any present system controls, and + // windows does not adjust it when changing to fullscreen. + { + STYLESTRUCT* pss = (STYLESTRUCT*)lp; + RECT winSize; + winSize.left = winSize.top = 0; + winSize.right = Width; + winSize.bottom = Height; + int w = winSize.right-winSize.left; + int h = winSize.bottom-winSize.top; + AdjustWindowRect(&winSize, pss->styleNew, false); + ::SetWindowPos(hWnd, NULL, 0, 0, w, h, SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOZORDER); + } + break; + + case WM_QUIT: + case WM_CLOSE: + pApp->OnQuitRequest(); + return false; + } + + return DefWindowProc(hWnd, msg, wp, lp); +} + +int PlatformCore::Run() +{ + while (!Quit) + { + MSG msg; + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + else + { + pApp->OnIdle(); + + // Keep sleeping when we're minimized. + if (IsIconic(hWnd)) + { + Sleep(10); + } + } + } + + return ExitCode; +} + + +RenderDevice* PlatformCore::SetupGraphics(const SetupGraphicsDeviceSet& setupGraphicsDesc, + const char* type, const Render::RendererParams& rp) +{ + const SetupGraphicsDeviceSet* setupDesc = setupGraphicsDesc.PickSetupDevice(type); + OVR_ASSERT(setupDesc); + + pRender = *setupDesc->pCreateDevice(rp, (void*)hWnd); + if (pRender) + pRender->SetWindowSize(Width, Height); + + ::ShowWindow(hWnd, SW_RESTORE); + return pRender.GetPtr(); +} + + +void PlatformCore::PlayMusicFile(const char *fileName) +{ + PlaySoundA(fileName, NULL, SND_FILENAME | SND_LOOP | SND_ASYNC); +} + + +//----------------------------------------------------------------------------- + +// Used to capture all the active monitor handles +struct MonitorSet +{ + enum { MaxMonitors = 8 }; + HMONITOR Monitors[MaxMonitors]; + int MonitorCount; + int PrimaryCount; +}; + + +BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData) +{ + MonitorSet* monitorSet = (MonitorSet*)dwData; + if (monitorSet->MonitorCount > MonitorSet::MaxMonitors) + return FALSE; + + monitorSet->Monitors[monitorSet->MonitorCount] = hMonitor; + monitorSet->MonitorCount++; + return TRUE; +}; + + +// Returns the number of active screens for extended displays and 1 for mirrored display +int PlatformCore::GetDisplayCount() +{ + // Get all the monitor handles + MonitorSet monitors; + monitors.MonitorCount = 0; + EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&monitors); + + // Count the primary monitors + int primary = 0; + MONITORINFOEX info; + for (int m=0; m < monitors.MonitorCount; m++) + { + info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitors.Monitors[m], &info); + + if (info.dwFlags & MONITORINFOF_PRIMARY) + primary++; + } + + if (primary > 1) + return 1; // Regard mirrored displays as a single screen + else + return monitors.MonitorCount; // Return all extended displays +} + +//----------------------------------------------------------------------------- +// Returns the device name for the given screen index or empty string for invalid index +// The zero index will always return the primary screen name +Render::DisplayId PlatformCore::GetDisplay(int screen) +{ + // Get all the monitor handles + MonitorSet monitors; + monitors.MonitorCount = 0; + EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, (LPARAM)&monitors); + + String screen_name; + + // Get the name of the suppled screen index with the requirement + // that screen 0 is the primary monitor + int non_primary_count = 0; + MONITORINFOEX info; + for (int m=0; m < monitors.MonitorCount; m++) + { + info.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(monitors.Monitors[m], &info); + + if (info.dwFlags & MONITORINFOF_PRIMARY) + { + if (screen == 0) + { + screen_name = info.szDevice; + break; + } + } + else + { + non_primary_count++; + if (screen == non_primary_count) + { + screen_name = info.szDevice; + break; + } + } + } + + return screen_name; +} + + +}}} + + +int WINAPI WinMain(HINSTANCE hinst, HINSTANCE prevInst, LPSTR inArgs, int show) +{ + using namespace OVR; + using namespace OVR::Platform; + + OVR_UNUSED2(prevInst, show); + + // CreateApplication must be the first call since it does OVR::System::Initialize. + Application* app = Application::CreateApplication(); + Win32::PlatformCore* platform = new Win32::PlatformCore(app, hinst); + // The platform attached to an app will be deleted by DestroyApplication. + app->SetPlatformCore(platform); + + int exitCode = 0; + + // Nested scope for container destructors to shutdown before DestroyApplication. + { + Array args; + Array argv; + argv.PushBack("app"); + + const char* p = inArgs; + const char* pstart = inArgs; + while (*p) + { + if (*p == ' ') + { + args.PushBack(String(pstart, p - pstart)); + while (*p == ' ') + p++; + pstart = p; + } + else + { + p++; + } + } + if (p != pstart) + args.PushBack(String(pstart, p - pstart)); + for (UPInt i = 0; i < args.GetSize(); i++) + argv.PushBack(args[i].ToCStr()); + + exitCode = app->OnStartup((int)argv.GetSize(), &argv[0]); + if (!exitCode) + exitCode = platform->Run(); + } + + // No OVR functions involving memory are allowed after this. + Application::DestroyApplication(app); + app = 0; + + OVR_DEBUG_STATEMENT(_CrtDumpMemoryLeaks()); + return exitCode; +} diff --git a/Samples/CommonSrc/Platform/Win32_Platform.h b/Samples/CommonSrc/Platform/Win32_Platform.h new file mode 100644 index 0000000..5d40861 --- /dev/null +++ b/Samples/CommonSrc/Platform/Win32_Platform.h @@ -0,0 +1,101 @@ +/************************************************************************************ + +Filename : Win32_Platform.h +Content : Win32 implementation of Platform app infrastructure +Created : September 6, 2012 +Authors : Andrew Reisse + +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +#ifndef OVR_Win32_Platform_h +#define OVR_Win32_Platform_h + +#include "Platform.h" +#include + + +namespace OVR { namespace Render { + class RenderDevice; + struct DisplayId; +}} + +namespace OVR { namespace Platform { namespace Win32 { + +class PlatformCore : public Platform::PlatformCore +{ + HWND hWnd; + HINSTANCE hInstance; + bool Quit; + int ExitCode; + int Width, Height; + + MouseMode MMode; + POINT WindowCenter; // In desktop coordinates + HCURSOR Cursor; + int Modifiers; + String WindowTitle; + + // Win32 static function that delegates to WindowProc member function. + static LRESULT CALLBACK systemWindowProc(HWND window, UINT msg, WPARAM wp, LPARAM lp); + + LRESULT WindowProc(UINT msg, WPARAM wp, LPARAM lp); + +public: + PlatformCore(Application* app, HINSTANCE hinst); + ~PlatformCore(); + + bool SetupWindow(int w, int h); + void DestroyWindow(); + void ShowWindow(bool visible); + void Exit(int exitcode) { Quit = 1; ExitCode = exitcode; } + + RenderDevice* SetupGraphics(const SetupGraphicsDeviceSet& setupGraphicsDesc, + const char* type, + const Render::RendererParams& rp); + + void SetMouseMode(MouseMode mm); + void GetWindowSize(int* w, int* h) const; + + void SetWindowTitle(const char*title); + void PlayMusicFile(const char *fileName); + int GetDisplayCount(); + Render::DisplayId GetDisplay(int screen); + + int Run(); +}; + + +// Win32 key conversion helper. +KeyCode MapVKToKeyCode(unsigned vk); + +}}} + + +// OVR_PLATFORM_APP_ARGS specifies the Application class to use for startup, +// providing it with startup arguments. +#define OVR_PLATFORM_APP_ARGS(AppClass, args) \ + OVR::Platform::Application* OVR::Platform::Application::CreateApplication() \ + { OVR::System::Init(OVR::Log::ConfigureDefaultLog(OVR::LogMask_All)); \ + return new AppClass args; } \ + void OVR::Platform::Application::DestroyApplication(OVR::Platform::Application* app) \ + { OVR::Platform::PlatformCore* platform = app->pPlatform; \ + delete app; delete platform; OVR::System::Destroy(); }; + +// OVR_PLATFORM_APP_ARGS specifies the Application startup class with no args. +#define OVR_PLATFORM_APP(AppClass) OVR_PLATFORM_APP_ARGS(AppClass, ()) + +#endif // OVR_Win32_Platform_h -- cgit v1.2.3