Commit MetaInfo

Revisão17d64556e9e40089c989763f935b9c2dc4425cec (tree)
Hora2020-03-03 13:48:00
AutorDavid Ludwig <dludwig@pobo...>
CommiterDavid Ludwig

Mensagem de Log

improved game-controller support; code cleanups; UI tweaks

Mudança Sumário

Diff

diff -r 8350a4792a3a -r 17d64556e9e4 main.cpp
--- a/main.cpp Mon Mar 02 16:27:39 2020 -0500
+++ b/main.cpp Mon Mar 02 23:48:00 2020 -0500
@@ -57,6 +57,11 @@
5757 #endif
5858
5959 // TODO: persist these on-disk
60+#if DEV_DAVIDL
61+static bool autoCreateVirtualJoystick = true;
62+#else
63+static bool autoCreateVirtualJoystick = false;
64+#endif
6065 static bool autoOpenJoysticks = false;
6166 static bool autoOpenGameControllers = true;
6267 static bool showGameControllerMappingUnformatted = false;
@@ -68,17 +73,40 @@
6873 struct NamedColumn {
6974 float width;
7075 const char *name;
76+ bool show = true;
7177 };
7278
7379 template <typename Collection>
7480 constexpr float TotalWidth(const Collection & aCollection) {
7581 float total = 0.f;
7682 for (const auto & it : aCollection) {
77- total += it.width;
83+ if (it.show) {
84+ total += it.width;
85+ }
7886 }
7987 return total;
8088 }
8189
90+template <typename Collection>
91+constexpr void ImGuiExt_SetColumns(const Collection & src) {
92+ int numVisibleColumns = 0;
93+ for (const auto & it : src) {
94+ if (it.show) {
95+ numVisibleColumns++;
96+ }
97+ }
98+ ImGui::Columns(numVisibleColumns);
99+ int srcIndex = 0;
100+ int destIndex = 0;
101+ for (const auto & it : src) {
102+ if (it.show) {
103+ ImGui::SetColumnWidth(destIndex, src[srcIndex].width);
104+ destIndex++;
105+ }
106+ srcIndex++;
107+ }
108+}
109+
82110 const NamedColumn joystickWindowColumns[] = {
83111 { 35.f, "" },
84112 { 60.f, "Actions" },
@@ -108,7 +136,7 @@
108136 { 250.f, "Name" },
109137 { 60.f, "Player\nIndex" },
110138 { 150.f, "Type" },
111- { 95.f, "Has Mapping?" },
139+ { 70.f, "Mapping" },
112140 { 55.f, "Vendor" },
113141 { 60.f, "Product" },
114142 { 65.f, "Product\nVersion" },
@@ -127,7 +155,7 @@
127155
128156 extern bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event *event);
129157
130-void ImGui_TextGUID(SDL_JoystickGUID guid)
158+void ImGuiExt_TextGUID(SDL_JoystickGUID guid)
131159 {
132160 ImGui::Text("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
133161 guid.data[0], guid.data[1], guid.data[2], guid.data[3],
@@ -203,7 +231,7 @@
203231 { SDL_CONTROLLER_TYPE_PS4, "PS4" },
204232 { SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO, "Nintendo Switch Pro" },
205233 #if SDL_JOYSTICK_VIRTUAL
206- // { SDL_CONTROLLER_TYPE_VIRTUAL, "Virtual" },
234+ { SDL_CONTROLLER_TYPE_VIRTUAL, "Virtual" },
207235 #endif
208236 };
209237
@@ -238,6 +266,43 @@
238266 // { SDL_CONTROLLER_AXIS_MAX, "MAX" }, // don't convert this to a value
239267 };
240268
269+static bool ImGuiExt_ToggleButton(bool isHighlighted)
270+{
271+ ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
272+ ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.f);
273+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 4));
274+ ImGui::PushStyleColor(ImGuiCol_Border, (ImVec4)ImColor(255, 255, 255));
275+ const float hue = 0.0f;
276+ const float lightness_base = (isHighlighted == 0 ? 0.0f : 0.7f);
277+ ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, std::clamp(lightness_base, 0.f, 1.f)));
278+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, std::clamp(lightness_base + 0.1f, 0.f, 1.f)));
279+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, std::clamp(lightness_base + 0.2f, 0.f, 1.f)));
280+ const bool wasClicked = ImGui::Button("Toggle");
281+ ImGui::PopStyleColor(4);
282+ ImGui::PopStyleVar(3);
283+ return wasClicked;
284+}
285+
286+static bool ImGuiExt_StateButton(bool isHighlighted, ImVec2 size)
287+{
288+ ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
289+ ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.f);
290+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 4));
291+ const ImVec4 buttonBgColor = (ImVec4)(
292+ isHighlighted ?
293+ ImColor(255, 255, 0) :
294+ ImColor(0, 0, 0)
295+ );
296+ ImGui::PushStyleColor(ImGuiCol_Button, buttonBgColor);
297+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonBgColor);
298+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, buttonBgColor);
299+ ImGui::PushStyleColor(ImGuiCol_Border, (ImVec4)ImColor(255, 255, 255));
300+ const bool wasClicked = ImGui::Button("", size);
301+ ImGui::PopStyleColor(4);
302+ ImGui::PopStyleVar(3);
303+ return wasClicked;
304+}
305+
241306
242307 void ShowJoystickChildWindow(int device_index);
243308 void ShowJoysticksWindow()
@@ -249,9 +314,9 @@
249314 #if SDL_JOYSTICK_VIRTUAL
250315 static struct VJoyParams {
251316 int type_index = 1; // index into 'EnumTypeInfo<SDL_JoystickType>::infos'
252- int naxes = 2;
317+ int naxes = SDL_CONTROLLER_AXIS_MAX;
253318 int nballs = 0;
254- int nbuttons = 4;
319+ int nbuttons = SDL_CONTROLLER_BUTTON_MAX;
255320 int nhats = 0;
256321 } vjoy_params;
257322 static struct VJoyParams vjoy_default_params = VJoyParams();
@@ -317,10 +382,7 @@
317382 ImGui::Separator();
318383 ImGui::Separator();
319384
320- ImGui::Columns(SDL_arraysize(joystickWindowColumns), "JoystickList", true);
321- for (int i = 0; i < SDL_arraysize(joystickWindowColumns); ++i) {
322- ImGui::SetColumnWidth(i, joystickWindowColumns[i].width);
323- }
385+ ImGuiExt_SetColumns(joystickWindowColumns);
324386 for (int i = 0; i < SDL_arraysize(joystickWindowColumns); ++i) {
325387 ImGui::Text("%s", joystickWindowColumns[i].name);
326388 ImGui::NextColumn();
@@ -374,7 +436,7 @@
374436
375437 ImGui::Text("%d", SDL_JoystickGetDevicePlayerIndex(device_index));
376438 ImGui::NextColumn();
377- ImGui_TextGUID(SDL_JoystickGetDeviceGUID(device_index));
439+ ImGuiExt_TextGUID(SDL_JoystickGetDeviceGUID(device_index));
378440 ImGui::NextColumn();
379441
380442 ImGui::Text("%s", NameOf(SDL_JoystickGetDeviceType(device_index)));
@@ -384,11 +446,11 @@
384446 ImGui::NextColumn();
385447
386448 #if SDL_JOYSTICK_VIRTUAL
387- const SDL_bool is_joystick_virtual = SDL_JoystickIsVirtual(device_index);
449+ const SDL_bool isVirtual = SDL_JoystickIsVirtual(device_index);
388450 #else
389- const SDL_bool is_joystick_virtual = SDL_FALSE;
451+ const SDL_bool isVirtual = SDL_FALSE;
390452 #endif
391- ImGui::Text("%s", (is_joystick_virtual == SDL_TRUE ? "YES" : "NO"));
453+ ImGui::Text("%s", (isVirtual == SDL_TRUE ? "YES" : "NO"));
392454 ImGui::NextColumn();
393455
394456 const SDL_bool is_game_controller = SDL_IsGameController(device_index);
@@ -432,9 +494,9 @@
432494 return;
433495 }
434496 #if SDL_JOYSTICK_VIRTUAL
435- const SDL_bool is_joystick_virtual = SDL_JoystickIsVirtual(device_index);
497+ const SDL_bool isVirtual = SDL_JoystickIsVirtual(device_index);
436498 #else
437- const SDL_bool is_joystick_virtual = SDL_FALSE;
499+ const SDL_bool isVirtual = SDL_FALSE;
438500 #endif
439501
440502 char window_name[64];
@@ -442,7 +504,7 @@
442504 // ImGui::BeginChild(window_name, ImVec2(0,300), true, 0);
443505 ImGui::BeginChild(window_name, ImVec2(0,550), true, 0);
444506
445- ImGui::Text("Is Virtual?: %s", (is_joystick_virtual == SDL_TRUE ? "YES" : "NO"));
507+ ImGui::Text("Is Virtual?: %s", (isVirtual == SDL_TRUE ? "YES" : "NO"));
446508
447509 ImGui::Separator();
448510
@@ -460,7 +522,7 @@
460522 { "Index:", true },
461523 { "State:", true },
462524 { "Raw State:", true },
463- { "Edit:", is_joystick_virtual == SDL_TRUE },
525+ { "Edit:", isVirtual == SDL_TRUE },
464526 };
465527
466528 ImGui::SetColumnWidth(0, 85);
@@ -493,19 +555,7 @@
493555 }
494556
495557 case 1: {
496- // display button-state as rectangle that lights up if pressed
497- ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
498- ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.f);
499- ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 4));
500- const ImVec4 buttonBgColor = (ImVec4)(
501- (buttonState == 0) ?
502- ImColor(0, 0, 0) :
503- ImColor(255, 255, 0));
504- ImGui::PushStyleColor(ImGuiCol_Button, buttonBgColor);
505- ImGui::PushStyleColor(ImGuiCol_Border, (ImVec4)ImColor(255, 255, 255));
506- ImGui::Button("", ImVec2(24, 24));
507- ImGui::PopStyleColor(2);
508- ImGui::PopStyleVar(3);
558+ ImGuiExt_StateButton(buttonState != 0, ImVec2(24,24));
509559 break;
510560 };
511561
@@ -518,24 +568,12 @@
518568 }
519569
520570 case 3: {
521- if (is_joystick_virtual) {
522- ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
523- ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.f);
524- ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 4));
525- ImGui::PushStyleColor(ImGuiCol_Border, (ImVec4)ImColor(255, 255, 255));
526- const float hue = 0.0f;
527- const Uint8 current = SDL_JoystickGetButton(joystick, col);
528- const float lightness_base = (current == 0 ? 0.0f : 0.7f);
529- ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, std::clamp(lightness_base, 0.f, 1.f)));
530- ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, std::clamp(lightness_base + 0.1f, 0.f, 1.f)));
531- ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, std::clamp(lightness_base + 0.2f, 0.f, 1.f)));
532- if (ImGui::Button("Toggle")) {
571+ if (isVirtual) {
572+ if (ImGuiExt_ToggleButton(buttonState != 0)) {
533573 #if SDL_JOYSTICK_VIRTUAL
534- SDL_JoystickSetVirtualButton(joystick, col, !current);
574+ SDL_JoystickSetVirtualButton(joystick, col, !buttonState);
535575 #endif
536576 }
537- ImGui::PopStyleColor(4);
538- ImGui::PopStyleVar(3);
539577 } else {
540578 ImGui::InvisibleButton("", ImVec2(4,4));
541579 }
@@ -601,12 +639,12 @@
601639 const Sint16 s16_max = std::numeric_limits<Sint16>::max();
602640 if (ImGui::SliderScalar("", ImGuiDataType_S16, &axis, &s16_min, &s16_max, "")) {
603641 #if SDL_JOYSTICK_VIRTUAL
604- if (is_joystick_virtual) {
642+ if (isVirtual) {
605643 SDL_JoystickSetVirtualAxis(joystick, i, axis);
606644 }
607645 #endif
608646 }
609- if (is_joystick_virtual) {
647+ if (isVirtual) {
610648 ImGui::SameLine();
611649 if (ImGui::Button("Reset")) {
612650 #if SDL_JOYSTICK_VIRTUAL
@@ -769,10 +807,7 @@
769807 ImGui::Separator();
770808 ImGui::Separator();
771809
772- ImGui::Columns(SDL_arraysize(gameControllersWindowColumns), "ControllerList", true);
773- for (int i = 0; i < SDL_arraysize(gameControllersWindowColumns); ++i) {
774- ImGui::SetColumnWidth(i, gameControllersWindowColumns[i].width);
775- }
810+ ImGuiExt_SetColumns(gameControllersWindowColumns);
776811 for (int i = 0; i < SDL_arraysize(gameControllersWindowColumns); ++i) {
777812 ImGui::Text("%s", gameControllersWindowColumns[i].name);
778813 ImGui::NextColumn();
@@ -827,9 +862,9 @@
827862
828863 // Mapping
829864 const char * mapping = SDL_GameControllerMappingForDeviceIndex(device_index);
830- ImGui::Text("%s", (mapping ? "YES" : "NO"));
831- if (mapping) {
832- ImGui::SameLine();
865+ if (!mapping) {
866+ ImGui::Text("(null)");
867+ } else {
833868 if (ImGui::Button("Show...")) {
834869 didCopyMapping = false;
835870 ImGui::OpenPopup("Show Mapping");
@@ -947,7 +982,8 @@
947982 {
948983 SDL_JoystickID device_instance_id = SDL_JoystickGetDeviceInstanceID(device_index);
949984 SDL_GameController * controller = SDL_GameControllerFromInstanceID(device_instance_id);
950- if (!controller) {
985+ SDL_Joystick * joystick = SDL_GameControllerGetJoystick(controller);
986+ if (!controller || !joystick) {
951987 return;
952988 }
953989
@@ -956,14 +992,20 @@
956992 ImGui::BeginChild(window_name, ImVec2(0,0), true, 0);
957993
958994 // Basics
995+ const SDL_GameControllerType controllerType = SDL_GameControllerGetType(controller);
996+ const bool isVirtual = (controllerType == SDL_CONTROLLER_TYPE_VIRTUAL);
959997 {
998+ const NamedColumn basicsColumns[] = {
999+ { 170.f, "Name" },
1000+ { 230.f, "Value" },
1001+ };
1002+ const float basicsColumnsWidth = TotalWidth(basicsColumns);
1003+
9601004 ImGui::SetCursorPos(ImVec2(8,8));
961- ImGui::BeginChild("Basics", ImVec2(400,160), true);
1005+ ImGui::BeginChild("Basics", ImVec2(basicsColumnsWidth,160), true);
9621006 ImGui::Text("Basics:");
9631007 ImGui::Separator();
964- ImGui::Columns(2);
965- ImGui::SetColumnWidth(0, 170.f);
966- ImGui::SetColumnWidth(1, 200.f);
1008+ ImGuiExt_SetColumns(basicsColumns);
9671009
9681010 ImGui::Text("Name");
9691011 ImGui::NextColumn();
@@ -972,7 +1014,7 @@
9721014
9731015 ImGui::Text("Type");
9741016 ImGui::NextColumn();
975- ImGui::Text("%s", NameOf(SDL_GameControllerGetType(controller)));
1017+ ImGui::Text("%s", NameOf(controllerType));
9761018 ImGui::NextColumn();
9771019
9781020 ImGui::Text("Player Index");
@@ -1005,34 +1047,35 @@
10051047
10061048 // Buttons
10071049 {
1050+ const NamedColumn buttonsColumns[] = {
1051+ { 170.f, "Name" },
1052+ { 35.f, "Raw\nState" },
1053+ { 92.f, "State" },
1054+ };
1055+ const float buttonsColumnsWidth = TotalWidth(buttonsColumns);
1056+
10081057 ImGui::SetCursorPos(ImVec2(416,8));
1009- ImGui::BeginChild("Buttons", ImVec2(250,400), true);
1058+ ImGui::BeginChild("Buttons", ImVec2(buttonsColumnsWidth,410), true);
10101059 ImGui::Text("Buttons:");
10111060 ImGui::Separator();
1012- ImGui::Columns(3);
1013- ImGui::SetColumnWidth(0, 170.f);
1014- ImGui::SetColumnWidth(1, 32.f);
1015- ImGui::SetColumnWidth(2, 64.f);
1061+ ImGuiExt_SetColumns(buttonsColumns);
10161062 for (int i = 0; i < (int)SDL_CONTROLLER_BUTTON_MAX; ++i) {
10171063 ImGui::PushID(i);
10181064 const SDL_GameControllerButton button = (SDL_GameControllerButton)i;
1019- const Uint8 buttonState = SDL_GameControllerGetButton(controller, button);
1020- ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
1021- if (buttonState != 0) {
1022- ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(255,255,0));
1023- ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(255,0,0));
1024- } else {
1025- ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(255,255,255));
1026- ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor(0,0,0));
1027- }
1028- ImGui::PushStyleColor(ImGuiCol_Border, (ImVec4)ImColor(255,255,255));
1065+ Uint8 buttonState = SDL_GameControllerGetButton(controller, button);
10291066 ImGui::Text("Button, %s", NameOf(button));
10301067 ImGui::NextColumn();
10311068 ImGui::Text("%d", (int)buttonState);
10321069 ImGui::NextColumn();
1033- ImGui::Button("", ImVec2(20,20));
1034- ImGui::PopStyleColor(3);
1035- ImGui::PopStyleVar(1);
1070+ ImGuiExt_StateButton(buttonState != 0, ImVec2(20,20));
1071+ if (isVirtual) {
1072+ ImGui::SameLine();
1073+ if (ImGuiExt_ToggleButton(buttonState != 0)) {
1074+#if SDL_JOYSTICK_VIRTUAL
1075+ SDL_JoystickSetVirtualButton(joystick, i, !buttonState);
1076+#endif
1077+ }
1078+ }
10361079 ImGui::NextColumn();
10371080 ImGui::PopID();
10381081 }
@@ -1041,25 +1084,44 @@
10411084
10421085 // Axes
10431086 {
1087+ const NamedColumn axesColumns[] = {
1088+ { 150.f, "Name" },
1089+ { 60.f, "Raw\nState" },
1090+ { 190.f, "State" },
1091+ };
1092+ const float axesColumnsWidth = TotalWidth(axesColumns);
10441093 ImGui::SetCursorPos(ImVec2(8,180));
1045- ImGui::BeginChild("Axes", ImVec2(400,200), true);
1094+ ImGui::BeginChild("Axes", ImVec2(axesColumnsWidth,180), true);
10461095 ImGui::Text("Axes:");
10471096 ImGui::Separator();
1048- ImGui::Columns(3);
1049- ImGui::SetColumnWidth(0, 150.f);
1050- ImGui::SetColumnWidth(1, 60.f);
1051- ImGui::SetColumnWidth(2, 250.f);
1097+ ImGuiExt_SetColumns(axesColumns);
10521098 for (int i = 0; i < (int)SDL_CONTROLLER_AXIS_MAX; ++i) {
10531099 ImGui::PushID(i);
10541100 const SDL_GameControllerAxis key = (SDL_GameControllerAxis)i;
1055- Sint16 value = SDL_GameControllerGetAxis(controller, key);
1101+ Sint16 axis = SDL_GameControllerGetAxis(controller, key);
1102+ Sint16 axis_initial_state = 0;
1103+ const SDL_bool axis_has_initial_state = SDL_JoystickGetAxisInitialState(joystick, i, &axis_initial_state);
10561104 ImGui::Text("Axis, %s", NameOf(key));
10571105 ImGui::NextColumn();
1058- ImGui::Text("%d", (int)value);
1106+ ImGui::Text("%d", (int)axis);
10591107 ImGui::NextColumn();
10601108 const Sint16 s16_min = std::numeric_limits<Sint16>::min();
10611109 const Sint16 s16_max = std::numeric_limits<Sint16>::max();
1062- ImGui::SliderScalar("", ImGuiDataType_S16, &value, &s16_min, &s16_max, "");
1110+ if (ImGui::SliderScalar("", ImGuiDataType_S16, &axis, &s16_min, &s16_max, "")) {
1111+#if SDL_JOYSTICK_VIRTUAL
1112+ if (isVirtual) {
1113+ SDL_JoystickSetVirtualAxis(joystick, i, axis);
1114+ }
1115+#endif
1116+ }
1117+ if (isVirtual) {
1118+ ImGui::SameLine();
1119+ if (ImGui::Button("Reset")) {
1120+#if SDL_JOYSTICK_VIRTUAL
1121+ SDL_JoystickSetVirtualAxis(joystick, i, (axis_has_initial_state ? axis_initial_state : 0));
1122+#endif
1123+ }
1124+ }
10631125 ImGui::NextColumn();
10641126 ImGui::PopID();
10651127 }
@@ -1184,10 +1246,16 @@
11841246 SDL_RenderClear(renderer);
11851247 SDL_SetRenderTarget(renderer, nullptr);
11861248
1187-#if DEV_DAVIDL && SDL_JOYSTICK_VIRTUAL
1249+#if SDL_JOYSTICK_VIRTUAL
11881250 // DEBUG: add a virtual joystick
1189- if (0) {
1190- const int vjoy_device_index = SDL_JoystickAttachVirtual(SDL_JOYSTICK_TYPE_GAMECONTROLLER, 2, 0, 4, 0);
1251+ if (autoCreateVirtualJoystick) {
1252+ const int vjoy_device_index = SDL_JoystickAttachVirtual(
1253+ SDL_JOYSTICK_TYPE_GAMECONTROLLER,
1254+ SDL_CONTROLLER_AXIS_MAX, // naxes
1255+ 0, // nballs
1256+ SDL_CONTROLLER_BUTTON_MAX, // nbuttons
1257+ 0 // nhats
1258+ );
11911259 if (vjoy_device_index >= 0) {
11921260 SDL_JoystickOpen(vjoy_device_index);
11931261 }
Show on old repository browser