diff --git a/src/api/headset.c b/src/api/headset.c index d39d70b5..240f09a3 100644 --- a/src/api/headset.c +++ b/src/api/headset.c @@ -25,34 +25,6 @@ const char* HeadsetOrigins[] = { NULL }; -const char* Subpaths[] = { - [P_NONE] = "", - [P_HEAD] = "head", - [P_HAND] = "hand", - [P_EYE] = "eye", - [P_TRACKER] = "tracker", - [P_LEFT] = "left", - [P_RIGHT] = "right", - [P_PROXIMITY] = "proximity", - [P_TRIGGER] = "trigger", - [P_TRACKPAD] = "trackpad", - [P_JOYSTICK] = "joystick", - [P_MENU] = "menu", - [P_GRIP] = "grip", - [P_A] = "a", - [P_B] = "b", - [P_X] = "x", - [P_Y] = "y", - [P_1] = "1", - [P_2] = "2", - [P_3] = "3", - [P_4] = "4", - [P_5] = "5", - [P_6] = "6", - [P_7] = "7", - [P_8] = "8" -}; - typedef struct { lua_State* L; int ref; @@ -60,42 +32,9 @@ typedef struct { static HeadsetRenderData headsetRenderData; -Path luax_optpath(lua_State* L, int index, const char* fallback) { - char* str = (char*) luaL_optstring(L, index, fallback); - Path path = { { P_NONE } }; - int count = 0; - - if (str[0] == '/') { - str++; - } - - while (1) { - char* slash = strchr(str, '/'); - - if (slash) { - *slash = '\0'; - } - - Subpath subpath = P_NONE; - for (size_t i = 0; i < sizeof(Subpaths) / sizeof(Subpaths[0]); i++) { - if (!strcmp(str, Subpaths[i])) { - subpath = i; - break; - } - } - - lovrAssert(subpath != P_NONE, "Unknown path component '%s'", str); - path.p[count++] = subpath; - - if (slash) { - *slash = '/'; - str = slash + 1; - } else { - break; - } - } - - return path; +static const char* luax_optpath(lua_State* L, int index) { + const char* str = luaL_optstring(L, index, "head"); + return str[0] == '/' ? ++str : str; } static void renderHelper(void* userdata) { @@ -221,7 +160,7 @@ static int l_lovrHeadsetGetBoundsGeometry(lua_State* L) { } int l_lovrHeadsetGetPose(lua_State* L) { - Path path = luax_optpath(L, 1, "head"); + const char* path = luax_optpath(L, 1); float x, y, z, angle, ax, ay, az; FOREACH_TRACKING_DRIVER(driver) { if (driver->getPose(path, &x, &y, &z, &angle, &ax, &ay, &az)) { @@ -239,7 +178,7 @@ int l_lovrHeadsetGetPose(lua_State* L) { } int l_lovrHeadsetGetPosition(lua_State* L) { - Path path = luax_optpath(L, 1, "head"); + const char* path = luax_optpath(L, 1); float x, y, z; FOREACH_TRACKING_DRIVER(driver) { if (driver->getPose(path, &x, &y, &z, NULL, NULL, NULL, NULL)) { @@ -253,7 +192,7 @@ int l_lovrHeadsetGetPosition(lua_State* L) { } int l_lovrHeadsetGetOrientation(lua_State* L) { - Path path = luax_optpath(L, 1, "head"); + const char* path = luax_optpath(L, 1); float angle, ax, ay, az; FOREACH_TRACKING_DRIVER(driver) { if (driver->getPose(path, NULL, NULL, NULL, &angle, &ax, &ay, &az)) { @@ -268,7 +207,7 @@ int l_lovrHeadsetGetOrientation(lua_State* L) { } int l_lovrHeadsetGetDirection(lua_State* L) { - Path path = luax_optpath(L, 1, "head"); + const char* path = luax_optpath(L, 1); float angle, ax, ay, az; FOREACH_TRACKING_DRIVER(driver) { if (driver->getPose(path, NULL, NULL, NULL, &angle, &ax, &ay, &az)) { @@ -286,7 +225,7 @@ int l_lovrHeadsetGetDirection(lua_State* L) { } int l_lovrHeadsetGetVelocity(lua_State* L) { - Path path = luax_optpath(L, 1, "head"); + const char* path = luax_optpath(L, 1); float vx, vy, vz; FOREACH_TRACKING_DRIVER(driver) { if (driver->getVelocity(path, &vx, &vy, &vz, NULL, NULL, NULL)) { @@ -300,7 +239,7 @@ int l_lovrHeadsetGetVelocity(lua_State* L) { } int l_lovrHeadsetGetAngularVelocity(lua_State* L) { - Path path = luax_optpath(L, 1, "head"); + const char* path = luax_optpath(L, 1); float vax, vay, vaz; FOREACH_TRACKING_DRIVER(driver) { if (driver->getVelocity(path, NULL, NULL, NULL, &vax, &vay, &vaz)) { @@ -314,7 +253,7 @@ int l_lovrHeadsetGetAngularVelocity(lua_State* L) { } int l_lovrHeadsetIsTracked(lua_State* L) { - Path path = luax_optpath(L, 1, "head"); + const char* path = luax_optpath(L, 1); FOREACH_TRACKING_DRIVER(driver) { if (driver->getPose(path, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { return true; @@ -324,7 +263,7 @@ int l_lovrHeadsetIsTracked(lua_State* L) { } int l_lovrHeadsetIsDown(lua_State* L) { - Path path = luax_optpath(L, 1, "head"); + const char* path = luax_optpath(L, 1); bool down; FOREACH_TRACKING_DRIVER(driver) { if (driver->isDown(path, &down)) { @@ -336,7 +275,7 @@ int l_lovrHeadsetIsDown(lua_State* L) { } int l_lovrHeadsetIsTouched(lua_State* L) { - Path path = luax_optpath(L, 1, "head"); + const char* path = luax_optpath(L, 1); bool touched; FOREACH_TRACKING_DRIVER(driver) { if (driver->isDown(path, &touched)) { @@ -348,7 +287,7 @@ int l_lovrHeadsetIsTouched(lua_State* L) { } int l_lovrHeadsetGetAxis(lua_State* L) { - Path path = luax_optpath(L, 1, "head"); + const char* path = luax_optpath(L, 1); float x, y, z; int count; FOREACH_TRACKING_DRIVER(driver) { @@ -364,7 +303,7 @@ int l_lovrHeadsetGetAxis(lua_State* L) { } int l_lovrHeadsetVibrate(lua_State* L) { - Path path = luax_optpath(L, 1, "head"); + const char* path = luax_optpath(L, 1); float strength = luax_optfloat(L, 2, 1.f); float duration = luax_optfloat(L, 3, .5f); float frequency = luax_optfloat(L, 4, 0.f); @@ -379,7 +318,7 @@ int l_lovrHeadsetVibrate(lua_State* L) { } int l_lovrHeadsetNewModel(lua_State* L) { - Path path = luax_optpath(L, 1, "head"); + const char* path = luax_optpath(L, 1); ModelData* modelData = NULL; FOREACH_TRACKING_DRIVER(driver) { diff --git a/src/headset/desktop.c b/src/headset/desktop.c index a6b11b01..ea1df6c6 100644 --- a/src/headset/desktop.c +++ b/src/headset/desktop.c @@ -74,9 +74,9 @@ static const float* getBoundsGeometry(int* count) { return NULL; } -static bool getPose(Path path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) { - bool head = PATH_EQ(path, P_HEAD); - bool hand = PATH_EQ(path, P_HAND, P_LEFT) || PATH_EQ(path, P_HAND, P_RIGHT); +static bool getPose(const char* path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) { + bool head = !strcmp(path, "head"); + bool hand = !strcmp(path, "hand/left") || !strcmp(path, "hand/right"); if (!head && !hand) { return false; @@ -97,8 +97,8 @@ static bool getPose(Path path, float* x, float* y, float* z, float* angle, float return true; } -static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) { - if (!PATH_EQ(path, P_HEAD)) { +static bool getVelocity(const char* path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) { + if (strcmp(path, "head")) { return false; } @@ -117,8 +117,8 @@ static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax, return true; } -static bool isDown(Path path, bool* down) { - if (PATH_EQ(path, P_HAND, P_LEFT) || PATH_EQ(path, P_HAND, P_RIGHT)) { +static bool isDown(const char* path, bool* down) { + if (!strcmp(path, "hand/left") || !strcmp(path, "hand/right")) { *down = lovrPlatformIsMouseDown(MOUSE_RIGHT); return true; } @@ -126,19 +126,19 @@ static bool isDown(Path path, bool* down) { return false; } -static bool isTouched(Path path, bool* touched) { +static bool isTouched(const char* path, bool* touched) { return false; } -static int getAxis(Path path, float* x, float* y, float* z) { +static int getAxis(const char* path, float* x, float* y, float* z) { return 0; } -static bool vibrate(Path path, float strength, float duration, float frequency) { +static bool vibrate(const char* path, float strength, float duration, float frequency) { return false; } -static ModelData* newModelData(Path path) { +static ModelData* newModelData(const char* path) { return NULL; } diff --git a/src/headset/headset.h b/src/headset/headset.h index effa21a0..f1d19b50 100644 --- a/src/headset/headset.h +++ b/src/headset/headset.h @@ -21,43 +21,6 @@ typedef enum { DRIVER_WEBVR } HeadsetDriver; -typedef enum { - P_NONE, - P_HEAD, - P_HAND, - P_EYE, - P_TRACKER, - P_LEFT, - P_RIGHT, - P_PROXIMITY, - P_TRIGGER, - P_TRACKPAD, - P_JOYSTICK, - P_MENU, - P_GRIP, - P_A, - P_B, - P_X, - P_Y, - P_1, - P_2, - P_3, - P_4, - P_5, - P_6, - P_7, - P_8 -} Subpath; - -typedef union { - uint8_t p[8]; - uint64_t u64; -} Path; - -#define MAKE_PATH(...) ((Path) { { __VA_ARGS__ } }) -#define PATH_EQ(p, ...) ((p).u64 == MAKE_PATH(__VA_ARGS__).u64) -#define PATH_STARTS_WITH(p, ...) ((MAKE_PATH(__VA_ARGS__).u64 ^ p.u64 & MAKE_PATH(__VA_ARGS__).u64) == 0) - typedef struct HeadsetInterface { struct HeadsetInterface* next; HeadsetDriver driverType; @@ -70,13 +33,13 @@ typedef struct HeadsetInterface { void (*setClipDistance)(float clipNear, float clipFar); void (*getBoundsDimensions)(float* width, float* depth); const float* (*getBoundsGeometry)(int* count); - bool (*getPose)(Path path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az); - bool (*getVelocity)(Path path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz); - bool (*isDown)(Path path, bool* down); - bool (*isTouched)(Path path, bool* touched); - int (*getAxis)(Path path, float* x, float* y, float* z); - bool (*vibrate)(Path path, float strength, float duration, float frequency); - struct ModelData* (*newModelData)(Path path); + bool (*getPose)(const char* path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az); + bool (*getVelocity)(const char* path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz); + bool (*isDown)(const char* path, bool* down); + bool (*isTouched)(const char* path, bool* touched); + int (*getAxis)(const char* path, float* x, float* y, float* z); + bool (*vibrate)(const char* path, float strength, float duration, float frequency); + struct ModelData* (*newModelData)(const char* path); void (*renderTo)(void (*callback)(void*), void* userdata); struct Texture* (*getMirrorTexture)(void); void (*update)(float dt); diff --git a/src/headset/oculus.c b/src/headset/oculus.c index fdcfd4bc..d2bd428d 100644 --- a/src/headset/oculus.c +++ b/src/headset/oculus.c @@ -159,14 +159,16 @@ static const float* getBoundsGeometry(int* count) { return NULL; } -static bool getPose(Path path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) { +static bool getPose(const char* path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) { ovrTrackingState *ts = refreshTracking(); ovrPosef* pose; - if (PATH_EQ(path, P_HEAD)) { + if (!strcmp(path, "head")) { pose = &ts->HeadPose.ThePose; - } else if (PATH_STARTS_WITH(path, P_HAND) && (path.p[1] == P_LEFT || path.p[1] == P_RIGHT)) { - pose = &ts->HandPoses[path.p[1] - P_LEFT].ThePose; + } else if (!strcmp(path, "hand/left")) { + pose = &ts->HandPoses[0].ThePose; + } else if (!strcmp(path, "hand/right")) { + pose = &ts->HandPoses[1].ThePose; } else { return false; } @@ -185,14 +187,16 @@ static bool getPose(Path path, float* x, float* y, float* z, float* angle, float return true; } -static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) { +static bool getVelocity(const char* path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) { ovrTrackingState *ts = refreshTracking(); - ovrPosef* pose; + ovrPoseStatef* pose; - if (PATH_EQ(path, P_HEAD)) { - velocity = &ts->HeadPose; - } else if (PATH_STARTS_WITH(path, P_HAND) && (path.p[1] == P_LEFT || path.p[1] == P_RIGHT)) { - velocity = &ts->HandPoses[path.p[1] - P_LEFT]; + if (!strcmp(path, "head")) { + pose = &ts->HeadPose; + } else if (!strcmp(path, "hand/left")) { + pose = &ts->HandPoses[ovrHand_Left]; + } else if (!strcmp(path, "hand/right")) { + pose = &ts->HandPoses[ovrHand_Right]; } else { return false; } @@ -212,87 +216,86 @@ static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax, return true; } -static bool isDown(Path path, bool* down) { - if (PATH_EQ(path, P_HEAD, P_PROXIMITY)) { +static bool getHandInfo(const char* path, ovrHandType* hand, uint32_t* mask, const char** next) { + if (!strncmp("hand/left", path, strlen("hand/left"))) { + *hand = ovrHand_Left; + *mask = ovrButton_LMask; + *next = path + strlen("hand/left/"); + return true; + } else if (!strncmp("hand/right", path, strlen("hand/right"))) { + *hand = ovrHand_Right; + *mask = ovrButton_RMask; + *next = path + strlen("hand/right/"); + return true; + } else { + return false; + } +} + +static bool isDown(const char* path, bool* down) { + if (!strcmp(path, "head/proximity")) { ovrSessionStatus status; ovr_GetSessionStatus(state.session, &status); *down = status.HmdMounted; return true; } - // Make sure the path starts with /hand/left or /hand/right and only has 3 pieces - if (path.p[0] != P_HAND || (path.p[1] != P_LEFT && path.p[1] != P_RIGHT) || path.p[3] != P_NONE) { - return false; - } + ovrHandType hand; + uint32_t mask; + const char* button; - ovrHandType hand = path.p[1] - P_LEFT; - ovrInputState* is = refreshButtons(); - uint32_t mask = is->Buttons & (hand == ovrHand_Left ? ovrButton_LMask : ovrButton_RMask); - - switch (path.p[2]) { - case P_A: *down = (mask & ovrButton_A); return true; - case P_B: *down = (mask & ovrButton_B); return true; - case P_X: *down = (mask & ovrButton_X); return true; - case P_Y: *down = (mask & ovrButton_Y); return true; - case P_MENU: *down = (mask & ovrButton_Enter); return true; - case P_TRIGGER: *down = (is->IndexTriggerNoDeadzone[hand] > 0.5f); return true; - case P_JOYSTICK: *down = (mask & (ovrButton_LThumb | ovrButton_RThumb)); return true; - case P_GRIP: *down = (is->HandTrigger[hand] > 0.9f); return true; + if (getHandInfo(path, &hand, &mask, &button)) { + ovrInputState* is = refreshButtons(); + if (!strcmp(path, "a")) { return *down = (mask & ovrButton_A), true; } + else if (!strcmp(path, "b")) { return *down = (mask & ovrButton_B), true; } + else if (!strcmp(path, "x")) { return *down = (mask & ovrButton_X), true; } + else if (!strcmp(path, "y")) { return *down = (mask & ovrButton_Y), true; } + else if (!strcmp(path, "menu")) { return *down = (mask & ovrButton_Enter), true; } + else if (!strcmp(path, "trigger")) { return *down = (is->IndexTriggerNoDeadzone[hand] > .5f), true; } + else if (!strcmp(path, "joystick")) { return *down = (mask & (ovrButton_LThumb | ovrButton_RThumb)), true; } + else if (!strcmp(path, "grip")) { return *down = (is->HandTrigger[hand] > .9f), true; } } return false; } -static bool isTouched(Path path, bool* touched) { +static bool isTouched(const char* path, bool* touched) { + ovrHandType hand; + uint32_t mask; + const char* button; - // Make sure the path starts with /hand/left or /hand/right and only has 3 pieces - if (path.p[0] != P_HAND || (path.p[1] != P_LEFT && path.p[1] != P_RIGHT) || path.p[3] != P_NONE) { - return false; - } - - ovrHandType hand = path.p[1] - P_LEFT; - ovrInputState* is = refreshButtons(); - uint32_t mask = is->Buttons & (hand == ovrHand_Left ? ovrButton_LMask : ovrButton_RMask); - - switch (path.p[2]) { - case P_A: *touched = (mask & ovrTouch_A); return true; - case P_B: *touched = (mask & ovrTouch_B); return true; - case P_X: *touched = (mask & ovrTouch_X); return true; - case P_Y: *touched = (mask & ovrTouch_Y); return true; - case P_TRIGGER: *touched = (mask & (ovrTouch_LIndexTrigger | ovrTouch_RIndexTrigger)); return true; - case P_JOYSTICK: *touched = (mask & (ovrTouch_LThumb | ovrTouch_RThumb)); return true; + if (getHandInfo(path, &hand, &mask, &button)) { + if (!strcmp(path, "a")) { return *touched = (mask & ovrTouch_A), true; } + else if (!strcmp(path, "b")) { return *touched = (mask & ovrTouch_B), true; } + else if (!strcmp(path, "x")) { return *touched = (mask & ovrTouch_X), true; } + else if (!strcmp(path, "y")) { return *touched = (mask & ovrTouch_Y), true; } + else if (!strcmp(path, "trigger")) { return *touched = (mask & (ovrTouch_LIndexTrigger | ovrTouch_RIndexTrigger)), true; } + else if (!strcmp(path, "joystick")) { return *touched = (mask & (ovrTouch_LThumb | ovrTouch_RThumb)), true; } } return false; } -static int getAxis(Path path, float* x, float* y, float* z) { +static int getAxis(const char* path, float* x, float* y, float* z) { + ovrHandType hand; + uint32_t mask; + const char* button; - // Make sure the path starts with /hand/left or /hand/right and only has 3 pieces - if (path.p[0] != P_HAND || (path.p[1] != P_LEFT && path.p[1] != P_RIGHT) || path.p[3] != P_NONE) { - return false; - } - - ovrInputState *is = refreshButtons(); - ovrHandType hand = path.p[1] - P_LEFT; - - switch (path.p[2]) { - case P_GRIP: *x = is->HandTriggerNoDeadzone[hand]; return 1; - case P_TRIGGER: *x = is->IndexTriggerNoDeadzone[hand]; return 1; - case P_JOYSTICK: - *x = is->ThumbstickNoDeadzone[hand].x; - *y = is->ThumbstickNoDeadzone[hand].y; - return 2; + if (getHandInfo(path, &hand, &mask, &button)) { + ovrInputState* is = refreshButtons(); + if (!strcmp(path, "grip")) { return *x = is->HandTriggerNoDeadzone[hand], 1; } + if (!strcmp(path, "trigger")) { return *x = is->IndexTriggerNoDeadzone[hand], 1; } + if (!strcmp(path, "joystick")) { return *x = is->ThumbstickNoDeadzone[hand].x, *y = is->ThumbstickNoDeadzone[hand].y, 2; } } return 0; } -static bool vibrate(Path path, float strength, float duration, float frequency) { +static bool vibrate(const char* path, float strength, float duration, float frequency) { return false; // TODO } -static ModelData* newModelData(Path path) { +static ModelData* newModelData(const char* path) { return NULL; // TODO } diff --git a/src/headset/oculus_mobile.c b/src/headset/oculus_mobile.c index c1be7a41..ccdcf83e 100644 --- a/src/headset/oculus_mobile.c +++ b/src/headset/oculus_mobile.c @@ -74,12 +74,12 @@ static const float* getBoundsGeometry(int* count) { return NULL; } -static bool getPose(Path path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) { +static bool getPose(const char* path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) { BridgeLovrPose* pose; - if (PATH_EQ(path, P_HEAD)) { + if (!strcmp(path, "head")) { pose = &bridgeLovrMobileData.updateData.lastHeadPose; - } else if (PATH_EQ(path, P_HAND)) { + } else if (!strcmp(path, "hand")) { pose = &bridgeLovrMobileData.updateData.goPose; } else { return false; @@ -98,12 +98,12 @@ static bool getPose(Path path, float* x, float* y, float* z, float* angle, float return true; } -static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) { +static bool getVelocity(const char* path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) { BridgeLovrVel* velocity; - if (PATH_EQ(path, P_HEAD)) { + if (!strcmp(path, "head")) { velocity = &bridgeLovrMobileData.updateData.lastHeadVelocity; - } else if (PATH_EQ(path, P_HAND)) { + } else if (!strcmp(path, "hand")) { velocity = &bridgeLovrMobileData.updateData.goVelocity; } else { return false; @@ -124,50 +124,46 @@ static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax, return true; } -static bool buttonCheck(BridgeLovrButton field, Path path, bool* result) { - if (!PATH_EQ(path, P_HAND) || path.p[2] != P_NONE) { - return false; // Path needs to start with /hand and have exactly one more piece +static bool buttonCheck(BridgeLovrButton field, const char* path, bool* result) { + if (!strcmp("hand", path, strlen("hand"))) { + path += strlen("hand/"); + if (!strcmp(path, "menu")) { return *result = (field & BRIDGE_LOVR_BUTTON_MENU), true; } + else if (!strcmp(path, "trigger")) { return *result = (field & BRIDGE_LOVR_BUTTON_SHOULDER), true; } + else if (!strcmp(path, "trackpad")) { return *result = (field & BRIDGE_LOVR_BUTTON_TOUCHPAD), true; } } - switch (path.p[1]) { - case P_MENU: *result = (field & BRIDGE_LOVR_BUTTON_MENU); return true; - case P_TRIGGER: *result = (field & BRIDGE_LOVR_BUTTON_SHOULDER); return true; - case P_TRACKPAD: *result = (field & BRIDGE_LOVR_BUTTON_TOUCHPAD); return true; - default: return false; - } -} - -static bool isDown(Path path, bool* down) { - return buttonCheck(bridgeLovrMobileData.updateData.goButtonDown, path, down); -} - -static bool isTouched(Path path, bool* touched) { - return buttonCheck(bridgeLovrMobileData.updateData.goButtonTouch, path, touched); -} - -static int getAxis(Path path, float* x, float* y, float* z) { - if (!PATH_EQ(path, P_HAND) || path.p[2] != P_NONE) { - return 0; // Path needs to start with /hand and have exactly one more piece - } - - switch (path.p[1]) { - case P_TRACKPAD: - *x = (bridgeLovrMobileData.updateData.goTrackpad.x - 160.f) / 160.f; - *y = (bridgeLovrMobileData.updateData.goTrackpad.y - 160.f) / 160.f; - return 2; - case P_TRIGGER: - *x = bridgeLovrMobileData.updateData.goButtonDown ? 1.f : 0.f; - return 1; - default: - return 0; - } -} - -static bool vibrate(Path path, float strength, float duration, float frequency) { return false; } -static ModelData* newModelData(Path path) { +static bool isDown(const char* path, bool* down) { + return buttonCheck(bridgeLovrMobileData.updateData.goButtonDown, path, down); +} + +static bool isTouched(const char* path, bool* touched) { + return buttonCheck(bridgeLovrMobileData.updateData.goButtonTouch, path, touched); +} + +static int getAxis(const char* path, float* x, float* y, float* z) { + if (!strcmp("hand", path, strlen("hand"))) { + path += strlen("hand/"); + if (!strcmp(path, "trackpad")) { + *x = (bridgeLovrMobileData.updateData.goTrackpad.x - 160.f) / 160.f; + *y = (bridgeLovrMobileData.updateData.goTrackpad.y - 160.f) / 160.f; + return 2; + } else if (!strcmp(path, "trigger")) { + *x = bridgeLovrMobileData.updateData.goButtonDown ? 1.f : 0.f; + return 1; + } + } + + return 0; +} + +static bool vibrate(const char* path, float strength, float duration, float frequency) { + return false; +} + +static ModelData* newModelData(const char* path) { return NULL; } diff --git a/src/headset/openvr.c b/src/headset/openvr.c index dd08f62a..7ce59a4d 100644 --- a/src/headset/openvr.c +++ b/src/headset/openvr.c @@ -23,8 +23,8 @@ extern void VR_ShutdownInternal(); extern bool VR_IsHmdPresent(); extern intptr_t VR_GetGenericInterface(const char* pchInterfaceVersion, EVRInitError* peError); extern bool VR_IsRuntimeInstalled(); -#define HEADSET_INDEX k_unTrackedDeviceIndex_Hmd -#define INVALID_INDEX k_unTrackedDeviceIndexInvalid +#define HEADSET k_unTrackedDeviceIndex_Hmd +#define INVALID_DEVICE k_unTrackedDeviceIndexInvalid static struct { struct VR_IVRSystem_FnTable* system; @@ -43,111 +43,24 @@ static struct { int msaa; } state; -static bool getTransform(unsigned int device, mat4 transform) { - TrackedDevicePose_t pose = state.poses[device]; - if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) { - return false; - } else { - mat4_fromMat34(transform, pose.mDeviceToAbsoluteTracking.m); - transform[13] += state.offset; - return true; - } -} - -static TrackedDeviceIndex_t getDeviceIndexForPath(Path path) { - if (PATH_EQ(path, P_HEAD)) { - return HEADSET_INDEX; - } else if (PATH_EQ(path, P_HAND, P_LEFT)) { +static TrackedDeviceIndex_t pathToDevice(const char* path, const char** next) { + if (!strcmp(path, "head")) { + if (next) *next = path + strlen("head/"); + return HEADSET; + } else if (!strcmp(path, "hand/left")) { + if (next) *next = path + strlen("hand/left/"); return state.system->GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole_TrackedControllerRole_LeftHand); - } else if (PATH_EQ(path, P_HAND, P_RIGHT)) { + } else if (!strcmp(path, "hand/right")) { + if (next) *next = path + strlen("hand/right/"); return state.system->GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole_TrackedControllerRole_RightHand); - } else if (path.p[0] == P_TRACKER && path.p[1] >= P_1 && path.p[1] <= P_8 && path.p[2] == P_NONE) { + } else if (!strncmp("tracker/", path, strlen("tracker/"))) { + path += strlen("tracker/"); + uint32_t index = (path[0] - '0') - 1; TrackedDeviceIndex_t indices[8]; uint32_t trackerCount = state.system->GetSortedTrackedDeviceIndicesOfClass(ETrackedDeviceClass_TrackedDeviceClass_GenericTracker, indices, 8, 0); - uint32_t index = path.p[1] - P_1; - return index < trackerCount ? indices[index] : k_unTrackedDeviceIndexInvalid; + return (index >= 0 && index < trackerCount) ? indices[index] : INVALID_DEVICE; } else { - return k_unTrackedDeviceIndexInvalid; - } -} - -static bool getButtonState(Path path, bool touch, bool* value) { - VRControllerState_t input; - - if (PATH_EQ(path, P_HEAD, P_PROXIMITY) && !touch) { - if (!state.system->GetControllerState(HEADSET_INDEX, &input, sizeof(input))) { - return false; - } - - *value = (input.ulButtonPressed >> EVRButtonId_k_EButton_ProximitySensor) & 1; - return true; - } else if (!PATH_STARTS_WITH(path, P_HAND, P_LEFT) && !PATH_STARTS_WITH(path, P_HAND, P_RIGHT)) { - return false; - } - - TrackedDeviceIndex_t deviceIndex = getDeviceIndexForPath(path); - if (deviceIndex == INVALID_INDEX) { - return false; - } - - if (!state.system->GetControllerState(deviceIndex, &input, sizeof(input))) { - return false; - } - - uint64_t mask = touch ? input.ulButtonTouched : input.ulButtonPressed; - - if (state.rift) { - switch (path.p[2]) { - case P_TRIGGER: - *value = (mask >> EVRButtonId_k_EButton_Axis1) & 1; - return true; - - case P_GRIP: - *value = (mask >> EVRButtonId_k_EButton_Axis2) & 1; - return true; - - case P_TRACKPAD: - *value = (mask >> EVRButtonId_k_EButton_Axis0) & 1; - return true; - - case P_A: - *value = path.p[1] == P_RIGHT && (mask >> EVRButtonId_k_EButton_A) & 1; - return true; - - case P_B: - *value = path.p[1] == P_RIGHT && (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1; - return true; - - case P_X: - *value = path.p[1] == P_LEFT && (mask >> EVRButtonId_k_EButton_A) & 1; - return true; - - case P_Y: - *value = path.p[1] == P_LEFT && (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1; - return true; - - default: return false; - } - } else { - switch (path.p[2]) { - case P_TRIGGER: - *value = (mask >> EVRButtonId_k_EButton_SteamVR_Trigger) & 1; - return true; - - case P_TRACKPAD: - *value = (mask >> EVRButtonId_k_EButton_SteamVR_Touchpad) & 1; - return true; - - case P_MENU: - *value = (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1; - return true; - - case P_GRIP: - *value = (mask >> EVRButtonId_k_EButton_Grip) & 1; - return true; - - default: return false; - } + return INVALID_DEVICE; } } @@ -204,7 +117,7 @@ static void destroy(void) { static bool getName(char* name, size_t length) { ETrackedPropertyError error; - state.system->GetStringTrackedDeviceProperty(HEADSET_INDEX, ETrackedDeviceProperty_Prop_ManufacturerName_String, name, length, &error); + state.system->GetStringTrackedDeviceProperty(HEADSET, ETrackedDeviceProperty_Prop_ManufacturerName_String, name, length, &error); return error == ETrackedPropertyError_TrackedProp_Success; } @@ -252,135 +165,137 @@ static const float* getBoundsGeometry(int* count) { return NULL; } -static bool getPose(Path path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) { - TrackedDeviceIndex_t deviceIndex = getDeviceIndexForPath(path); - float transform[16]; - if (deviceIndex != INVALID_INDEX && getTransform(deviceIndex, transform)) { - mat4_getTransform(transform, x, y, z, NULL, NULL, NULL, angle, ax, ay, az); +static bool getTransform(unsigned int device, mat4 transform) { + TrackedDevicePose_t pose = state.poses[device]; + if (!pose.bPoseIsValid || !pose.bDeviceIsConnected) { + return false; + } else { + mat4_fromMat34(transform, pose.mDeviceToAbsoluteTracking.m); + transform[13] += state.offset; return true; } +} + +static bool getPose(const char* path, float* x, float* y, float* z, float* angle, float* ax, float* ay, float* az) { + float transform[16]; + TrackedDeviceIndex_t device = pathToDevice(path, NULL); + if (device == INVALID_DEVICE && !getTransform(device, transform)) { + return false; + } + + mat4_getTransform(transform, x, y, z, NULL, NULL, NULL, angle, ax, ay, az); + return true; +} + +static bool getVelocity(const char* path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) { + TrackedDeviceIndex_t device = pathToDevice(path, NULL); + TrackedDevicePose_t* pose = &state.poses[device]; + if (device == INVALID_DEVICE || !pose->bPoseIsValid || !pose->bDeviceIsConnected) { + return false; + } + + if (vx) { + *vx = pose->vVelocity.v[0]; + *vy = pose->vVelocity.v[1]; + *vz = pose->vVelocity.v[2]; + } + + if (vax) { + *vax = pose->vAngularVelocity.v[0]; + *vay = pose->vAngularVelocity.v[1]; + *vaz = pose->vAngularVelocity.v[2]; + } + + return true; +} + +static bool getButtonState(const char* path, bool touch, bool* value) { + VRControllerState_t input; + + if (!strcmp(path, "head/proximity") && !touch) { + if (!state.system->GetControllerState(HEADSET, &input, sizeof(input))) { + return false; + } + + return *value = (input.ulButtonPressed >> EVRButtonId_k_EButton_ProximitySensor) & 1, true; + } + + const char* button; + TrackedDeviceIndex_t device = pathToDevice(path, &button); + if (device != INVALID_DEVICE || state.system->GetControllerState(device, &input, sizeof(input))) { + uint64_t mask = touch ? input.ulButtonTouched : input.ulButtonPressed; + + if (state.rift) { + if (!strcmp(button, "trigger")) { return *value = (mask >> EVRButtonId_k_EButton_Axis1) & 1, true; } + else if (!strcmp(button, "grip")) { return *value = (mask >> EVRButtonId_k_EButton_Axis2) & 1, true; } + else if (!strcmp(button, "trackpad")) { return *value = (mask >> EVRButtonId_k_EButton_Axis0) & 1, true; } + else if (!strcmp(path, "hand/right/a") || !strcmp(path, "hand/left/x")) { return *value = (mask >> EVRButtonId_k_EButton_A) & 1, true; } + else if (!strcmp(path, "hand/right/b") || !strcmp(path, "hand/left/y")) { return *value = (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1, true; } + } else { + if (!strcmp(button, "trigger")) { return *value = (mask >> EVRButtonId_k_EButton_SteamVR_Trigger) & 1, true; } + else if (!strcmp(button, "trackpad")) { return *value = (mask >> EVRButtonId_k_EButton_SteamVR_Touchpad) & 1, true; } + else if (!strcmp(button, "menu")) { return *value = (mask >> EVRButtonId_k_EButton_ApplicationMenu) & 1, true; } + else if (!strcmp(button, "grip")) { return *value = (mask >> EVRButtonId_k_EButton_Grip) & 1, true; } + } + } + return false; } -static bool getVelocity(Path path, float* vx, float* vy, float* vz, float* vax, float* vay, float* vaz) { - TrackedDeviceIndex_t deviceIndex = getDeviceIndexForPath(path); - if (deviceIndex == INVALID_INDEX) { - return false; - } - - TrackedDevicePose_t* pose = &state.poses[deviceIndex]; - if (!pose->bPoseIsValid || !pose->bDeviceIsConnected) { - return false; - } else { - if (vx) { - *vx = pose->vVelocity.v[0]; - *vy = pose->vVelocity.v[1]; - *vz = pose->vVelocity.v[2]; - } - - if (vax) { - *vax = pose->vAngularVelocity.v[0]; - *vay = pose->vAngularVelocity.v[1]; - *vaz = pose->vAngularVelocity.v[2]; - } - return true; - } -} - -static bool isDown(Path path, bool* down) { +static bool isDown(const char* path, bool* down) { return getButtonState(path, false, down); } -static bool isTouched(Path path, bool* touched) { +static bool isTouched(const char* path, bool* touched) { return getButtonState(path, true, touched); } -static int getAxis(Path path, float* x, float* y, float* z) { - if (path.p[3] != P_NONE) { - return 0; - } - - TrackedDeviceIndex_t deviceIndex = getDeviceIndexForPath(path); - if (deviceIndex == INVALID_INDEX) { - return 0; - } +static int getAxis(const char* path, float* x, float* y, float* z) { + const char* axis; + TrackedDeviceIndex_t device = pathToDevice(path, &axis); VRControllerState_t input; - if (!state.system->GetControllerState(deviceIndex, &input, sizeof(input))) { - return 0; - } - - if (state.rift) { - switch (path.p[2]) { - case P_TRIGGER: - *x = input.rAxis[1].x; - return 1; - - case P_GRIP: - *x = input.rAxis[2].x; - return 1; - - case P_TRACKPAD: - *x = input.rAxis[0].x; - *y = input.rAxis[0].y; - return 2; - - default: return 0; - } - } else { - switch (path.p[2]) { - case P_TRIGGER: - *x = input.rAxis[1].x; - return 1; - - case P_TRACKPAD: - *x = input.rAxis[0].x; - *y = input.rAxis[0].y; - return 2; - - default: return 0; - } + if (device != INVALID_DEVICE || state.system->GetControllerState(device, &input, sizeof(input))) { + if (!strcmp(axis, "trigger")) { return *x = input.rAxis[1].x, 1; } + else if (state.rift && !strcmp(axis, "grip")) { return *x = input.rAxis[2].x, 1; } + else if (!strcmp(axis, "trackpad")) { return *x = input.rAxis[0].x, *y = input.rAxis[0].y, 2; } } return 0; } -static bool vibrate(Path path, float strength, float duration, float frequency) { +static bool vibrate(const char* path, float strength, float duration, float frequency) { if (duration <= 0) return false; - if (!PATH_STARTS_WITH(path, P_HAND)) return false; - TrackedDeviceIndex_t deviceIndex = getDeviceIndexForPath(path); - if (deviceIndex == INVALID_INDEX) return false; + TrackedDeviceIndex_t device = pathToDevice(path, NULL); + if (device == INVALID_DEVICE) return false; - unsigned short uSeconds = (unsigned short) (duration * 1e6f); - state.system->TriggerHapticPulse(deviceIndex, 0, uSeconds); + unsigned short uSeconds = (unsigned short) (duration * 1e6f + .5f); + state.system->TriggerHapticPulse(device, 0, uSeconds); return true; } -static ModelData* newModelData(Path path) { - TrackedDeviceIndex_t deviceIndex = getDeviceIndexForPath(path); - if (deviceIndex == INVALID_INDEX) return false; +static ModelData* newModelData(const char* path) { + TrackedDeviceIndex_t device = pathToDevice(path, NULL); + if (device == INVALID_DEVICE) return false; - // Get model name char renderModelName[1024]; ETrackedDeviceProperty renderModelNameProperty = ETrackedDeviceProperty_Prop_RenderModelName_String; - state.system->GetStringTrackedDeviceProperty(deviceIndex, renderModelNameProperty, renderModelName, 1024, NULL); + state.system->GetStringTrackedDeviceProperty(device, renderModelNameProperty, renderModelName, 1024, NULL); - // Load model - if (!state.deviceModels[deviceIndex]) { - while (state.renderModels->LoadRenderModel_Async(renderModelName, &state.deviceModels[deviceIndex]) == EVRRenderModelError_VRRenderModelError_Loading) { + if (!state.deviceModels[device]) { + while (state.renderModels->LoadRenderModel_Async(renderModelName, &state.deviceModels[device]) == EVRRenderModelError_VRRenderModelError_Loading) { lovrSleep(.001); } } - // Load texture - if (!state.deviceTextures[deviceIndex]) { - while (state.renderModels->LoadTexture_Async(state.deviceModels[deviceIndex]->diffuseTextureId, &state.deviceTextures[deviceIndex]) == EVRRenderModelError_VRRenderModelError_Loading) { + if (!state.deviceTextures[device]) { + while (state.renderModels->LoadTexture_Async(state.deviceModels[device]->diffuseTextureId, &state.deviceTextures[device]) == EVRRenderModelError_VRRenderModelError_Loading) { lovrSleep(.001); } } - RenderModel_t* vrModel = state.deviceModels[deviceIndex]; + RenderModel_t* vrModel = state.deviceModels[device]; ModelData* model = lovrAlloc(ModelData); size_t vertexSize = sizeof(RenderModel_Vertex_t); @@ -436,7 +351,7 @@ static ModelData* newModelData(Path path) { .components = 1 }; - RenderModel_TextureMap_t* vrTexture = state.deviceTextures[deviceIndex]; + RenderModel_TextureMap_t* vrTexture = state.deviceTextures[device]; model->textures[0] = lovrTextureDataCreate(vrTexture->unWidth, vrTexture->unHeight, 0, FORMAT_RGBA); memcpy(model->textures[0]->blob.data, vrTexture->rubTextureMapData, vrTexture->unWidth * vrTexture->unHeight * 4); @@ -482,7 +397,7 @@ static void renderTo(void (*callback)(void*), void* userdata) { Camera camera = { .canvas = state.canvas, .viewMatrix = { MAT4_IDENTITY, MAT4_IDENTITY } }; float head[16], eye[16]; - getTransform(HEADSET_INDEX, head); + getTransform(HEADSET, head); for (int i = 0; i < 2; i++) { EVREye vrEye = (i == 0) ? EVREye_Eye_Left : EVREye_Eye_Right;