Commit MetaInfo

Revisãofa3f1986526162c9867a8cbbbc9c0288a20d62ac (tree)
Hora2020-02-26 04:48:34
AutorDavid Ludwig <dludwig@pobo...>
CommiterDavid Ludwig

Mensagem de Log

Initial, work-in-progress version

The current code is largely geared towards testing a proposed,
LibSDL feature, Virtual Joysticks, and contains API calls to such.

Building may be broken. In general, layout directories in the following
manner:

some-directory/

SDL-test-panel/ -- SDL Test Panel code
SDL/ -- LibSDL source code, such as from https://hg.libsdl.org/SDL
imgui/ -- ImGui source code, such as from https://github.com/ocornut/imgui
imgui_sdl/ -- ImGuiSDL source code, such as from https://github.com/Tyyppi77/imgui_sdl

Mudança Sumário

Diff

diff -r 000000000000 -r fa3f19865261 CMakeLists.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CMakeLists.txt Tue Feb 25 14:48:34 2020 -0500
@@ -0,0 +1,26 @@
1+cmake_minimum_required(VERSION 3.15)
2+project(SDL-test-panel)
3+list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
4+add_executable(SDL-test-panel
5+ main.cpp
6+ ../imgui/imgui.cpp
7+ ../imgui/imgui_demo.cpp
8+ ../imgui/imgui_draw.cpp
9+ ../imgui/imgui_widgets.cpp
10+ ../imgui/examples/imgui_impl_sdl.cpp
11+ ../imgui_sdl/imgui_sdl.cpp
12+)
13+# find_package(SDL2 REQUIRED)
14+# message("SDL2_INCLUDE_DIRS: (${SDL2_INCLUDE_DIRS})")
15+# message("SDL2_LIBRARIES: (${SDL2_LIBRARIES})")
16+# target_include_directories(SDL-test-panel PRIVATE ${SDL2_INCLUDE_DIRS})
17+# target_link_libraries(SDL-test-panel ${SDL2_LIBRARIES})
18+set_property(TARGET SDL-test-panel PROPERTY CXX_STANDARD 20)
19+target_include_directories(SDL-test-panel PRIVATE
20+ "${CMAKE_CURRENT_LIST_DIR}/../include/SDL2"
21+ "${CMAKE_CURRENT_LIST_DIR}/../imgui"
22+ "${CMAKE_CURRENT_LIST_DIR}/../imgui/examples"
23+ "${CMAKE_CURRENT_LIST_DIR}/../imgui_sdl"
24+)
25+target_link_directories(SDL-test-panel PRIVATE "${CMAKE_CURRENT_LIST_DIR}/../lib")
26+target_link_libraries(SDL-test-panel "$<IF:$<CONFIG:Debug>,SDL2d,SDL2>")
diff -r 000000000000 -r fa3f19865261 LICENSE-imgui_sdl.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE-imgui_sdl.txt Tue Feb 25 14:48:34 2020 -0500
@@ -0,0 +1,21 @@
1+MIT License
2+
3+Copyright (c) 2018
4+
5+Permission is hereby granted, free of charge, to any person obtaining a copy
6+of this software and associated documentation files (the "Software"), to deal
7+in the Software without restriction, including without limitation the rights
8+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+copies of the Software, and to permit persons to whom the Software is
10+furnished to do so, subject to the following conditions:
11+
12+The above copyright notice and this permission notice shall be included in all
13+copies or substantial portions of the Software.
14+
15+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+SOFTWARE.
diff -r 000000000000 -r fa3f19865261 LICENSE.txt
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/LICENSE.txt Tue Feb 25 14:48:34 2020 -0500
@@ -0,0 +1,20 @@
1+
2+SDL Test Panel
3+Copyright (C) 2020 David Lee Ludwig <dludwig@pobox.com>
4+
5+This software is provided 'as-is', without any express or implied
6+warranty. In no event will the authors be held liable for any damages
7+arising from the use of this software.
8+
9+Permission is granted to anyone to use this software for any purpose,
10+including commercial applications, and to alter it and redistribute it
11+freely, subject to the following restrictions:
12+
13+1. The origin of this software must not be misrepresented; you must not
14+ claim that you wrote the original software. If you use this software
15+ in a product, an acknowledgment in the product documentation would be
16+ appreciated but is not required.
17+2. Altered source versions must be plainly marked as such, and must not be
18+ misrepresented as being the original software.
19+3. This notice may not be removed or altered from any source distribution.
20+
diff -r 000000000000 -r fa3f19865261 cmake/FindSDL2.cmake
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake/FindSDL2.cmake Tue Feb 25 14:48:34 2020 -0500
@@ -0,0 +1,92 @@
1+# - Find SDL2 library and headers
2+#
3+# Find module for SDL 2.0 (http://www.libsdl.org/).
4+# It defines the following variables:
5+# SDL2_INCLUDE_DIRS - The location of the headers, e.g., SDL.h.
6+# SDL2_LIBRARIES - The libraries to link against to use SDL2.
7+# SDL2_FOUND - If false, do not try to use SDL2.
8+# SDL2_VERSION_STRING - Human-readable string containing the version of SDL2.
9+#
10+# This module responds to the the flag:
11+# SDL2_BUILDING_LIBRARY
12+# If this is defined, then no SDL2_main will be linked in because
13+# only applications need main().
14+# Otherwise, it is assumed you are building an application and this
15+# module will attempt to locate and set the the proper link flags
16+# as part of the returned SDL2_LIBRARIES variable.
17+#
18+# Also defined, but not for general use are:
19+# SDL2_INCLUDE_DIR - The directory that contains SDL.h.
20+# SDL2_LIBRARY - The location of the SDL2 library.
21+# SDL2MAIN_LIBRARY - The location of the SDL2main library.
22+#
23+
24+#=============================================================================
25+# Copyright 2013 Benjamin Eikel
26+#
27+# Distributed under the OSI-approved BSD License (the "License");
28+# see accompanying file Copyright.txt for details.
29+#
30+# This software is distributed WITHOUT ANY WARRANTY; without even the
31+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
32+# See the License for more information.
33+#=============================================================================
34+# (To distribute this file outside of CMake, substitute the full
35+# License text for the above reference.)
36+
37+find_package(PkgConfig QUIET)
38+pkg_check_modules(PC_SDL2 QUIET sdl2)
39+
40+# Look for SDL_render.h, which is in SDL2, but not in SDL1.
41+find_path(SDL2_INCLUDE_DIR
42+ NAMES SDL_render.h
43+ HINTS
44+ ${PC_SDL2_INCLUDEDIR}
45+ ${PC_SDL2_INCLUDE_DIRS}
46+ PATH_SUFFIXES SDL2
47+)
48+
49+find_library(SDL2_LIBRARY
50+ NAMES SDL2
51+ HINTS
52+ ${PC_SDL2_LIBDIR}
53+ ${PC_SDL2_LIBRARY_DIRS}
54+ PATH_SUFFIXES x64 x86
55+)
56+
57+if(NOT SDL2_BUILDING_LIBRARY)
58+ find_library(SDL2MAIN_LIBRARY
59+ NAMES SDL2main
60+ HINTS
61+ ${PC_SDL2_LIBDIR}
62+ ${PC_SDL2_LIBRARY_DIRS}
63+ PATH_SUFFIXES x64 x86
64+ )
65+endif()
66+
67+if(SDL2_INCLUDE_DIR AND EXISTS "${SDL2_INCLUDE_DIR}/SDL_version.h")
68+ file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+[0-9]+$")
69+ file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_MINOR_LINE REGEX "^#define[ \t]+SDL_MINOR_VERSION[ \t]+[0-9]+$")
70+ file(STRINGS "${SDL2_INCLUDE_DIR}/SDL_version.h" SDL2_VERSION_PATCH_LINE REGEX "^#define[ \t]+SDL_PATCHLEVEL[ \t]+[0-9]+$")
71+ string(REGEX REPLACE "^#define[ \t]+SDL_MAJOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MAJOR "${SDL2_VERSION_MAJOR_LINE}")
72+ string(REGEX REPLACE "^#define[ \t]+SDL_MINOR_VERSION[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_MINOR "${SDL2_VERSION_MINOR_LINE}")
73+ string(REGEX REPLACE "^#define[ \t]+SDL_PATCHLEVEL[ \t]+([0-9]+)$" "\\1" SDL2_VERSION_PATCH "${SDL2_VERSION_PATCH_LINE}")
74+ set(SDL2_VERSION_STRING ${SDL2_VERSION_MAJOR}.${SDL2_VERSION_MINOR}.${SDL2_VERSION_PATCH})
75+ unset(SDL2_VERSION_MAJOR_LINE)
76+ unset(SDL2_VERSION_MINOR_LINE)
77+ unset(SDL2_VERSION_PATCH_LINE)
78+ unset(SDL2_VERSION_MAJOR)
79+ unset(SDL2_VERSION_MINOR)
80+ unset(SDL2_VERSION_PATCH)
81+endif()
82+
83+set(SDL2_INCLUDE_DIRS ${SDL2_INCLUDE_DIR})
84+set(SDL2_LIBRARIES ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY})
85+
86+include(FindPackageHandleStandardArgs)
87+
88+find_package_handle_standard_args(SDL2
89+ REQUIRED_VARS SDL2_INCLUDE_DIR SDL2_LIBRARY
90+ VERSION_VAR SDL2_VERSION_STRING)
91+
92+mark_as_advanced(SDL2_INCLUDE_DIR SDL2_LIBRARY)
diff -r 000000000000 -r fa3f19865261 main.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Tue Feb 25 14:48:34 2020 -0500
@@ -0,0 +1,607 @@
1+/*
2+ SDL Test Panel
3+ Copyright (C) 2020 David Lee Ludwig <dludwig@pobox.com>
4+
5+ This software is provided 'as-is', without any express or implied
6+ warranty. In no event will the authors be held liable for any damages
7+ arising from the use of this software.
8+
9+ Permission is granted to anyone to use this software for any purpose,
10+ including commercial applications, and to alter it and redistribute it
11+ freely, subject to the following restrictions:
12+
13+ 1. The origin of this software must not be misrepresented; you must not
14+ claim that you wrote the original software. If you use this software
15+ in a product, an acknowledgment in the product documentation would be
16+ appreciated but is not required.
17+ 2. Altered source versions must be plainly marked as such, and must not be
18+ misrepresented as being the original software.
19+ 3. This notice may not be removed or altered from any source distribution.
20+*/
21+
22+#include <limits>
23+#include <mutex>
24+#include <numeric>
25+#include <string>
26+#include <type_traits>
27+
28+#include "SDL.h"
29+#include "imgui.h"
30+#include "imgui_sdl.h"
31+#include "imgui_internal.h"
32+
33+extern bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event);
34+
35+void ImGui_TextGUID(SDL_JoystickGUID guid)
36+{
37+ ImGui::Text("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
38+ guid.data[0], guid.data[1], guid.data[2], guid.data[3],
39+ guid.data[4], guid.data[5], guid.data[6], guid.data[7],
40+ guid.data[8], guid.data[9], guid.data[10], guid.data[11],
41+ guid.data[12], guid.data[13], guid.data[14], guid.data[15]
42+ );
43+}
44+
45+struct JoystickTypeInfo {
46+ SDL_JoystickType type;
47+ const char * name;
48+};
49+static const JoystickTypeInfo joystick_type_infos[] = {
50+ { SDL_JOYSTICK_TYPE_UNKNOWN, "Unknown" },
51+ { SDL_JOYSTICK_TYPE_GAMECONTROLLER, "Game controller" },
52+ { SDL_JOYSTICK_TYPE_WHEEL, "Wheel" },
53+ { SDL_JOYSTICK_TYPE_ARCADE_STICK, "Arcade stick" },
54+ { SDL_JOYSTICK_TYPE_FLIGHT_STICK, "Flight stick" },
55+ { SDL_JOYSTICK_TYPE_DANCE_PAD, "Dance pad" },
56+ { SDL_JOYSTICK_TYPE_GUITAR, "Guitar" },
57+ { SDL_JOYSTICK_TYPE_DRUM_KIT, "Drum kit" },
58+ { SDL_JOYSTICK_TYPE_ARCADE_PAD, "Arcade pad" },
59+ { SDL_JOYSTICK_TYPE_THROTTLE, "Throttle" }
60+};
61+
62+static bool GetJoystickTypeInfosForImGuiCombo(void *, int idx, const char ** out_text)
63+{
64+ if (idx < 0 || idx >= SDL_arraysize(joystick_type_infos)) {
65+ return false;
66+ }
67+ *out_text = joystick_type_infos[idx].name;
68+ return true;
69+}
70+
71+constexpr const char * JoystickTypeName(SDL_JoystickType type)
72+{
73+ for (int i = 0; i < SDL_arraysize(joystick_type_infos); ++i) {
74+ if (type == joystick_type_infos[i].type) {
75+ return joystick_type_infos[i].name;
76+ }
77+ }
78+ return JoystickTypeName(SDL_JOYSTICK_TYPE_UNKNOWN);
79+}
80+
81+void ShowJoystickSubWindow(int device_index);
82+
83+void ShowJoystickMainWindow()
84+{
85+ struct {
86+ float width;
87+ const char *name;
88+ } main_columns[] = {
89+ { 35.f, "" },
90+ { 60.f, "Actions" },
91+ { 95.f, "Device Index" },
92+ { 260.f, "Name" },
93+ { 95.f, "Player Index" },
94+ { 265.f, "Device GUID" },
95+ { 118.f, "Type" },
96+ { 90.f, "Instance ID" },
97+ { 70.f, "Virtual?" },
98+ };
99+ // const float total_width = std::accumulate(main_columns, main_columns + SDL_arraysize(main_columns), 0);
100+ float total_width = 0.f;
101+ for (const auto & col : main_columns) {
102+ total_width += col.width;
103+ }
104+ const float window_margins = 1;
105+ const float main_window_height = 480.f;
106+
107+ ImGui::SetNextWindowPos(ImVec2(window_margins, 20.f + window_margins), ImGuiCond_Once);
108+ ImGui::SetNextWindowSize(ImVec2(total_width, main_window_height), ImGuiCond_Once);
109+ ImGui::Begin("Joysticks", NULL, 0);
110+
111+ static struct VJoyParams {
112+ int type_index = 1; // index into 'joystick_type_infos'
113+ int naxes = 2;
114+ int nballs = 0;
115+ int nbuttons = 4;
116+ int nhats = 0;
117+ } vjoy_params;
118+ static struct VJoyParams vjoy_default_params = VJoyParams();
119+
120+ if (ImGui::Button("Add Virtual Joystick...")) {
121+ vjoy_params = vjoy_default_params;
122+ ImGui::OpenPopup("New Virtual Joystick");
123+ }
124+ if (ImGui::IsPopupOpen("New Virtual Joystick")) {
125+ ImVec2 pos = GImGui->CurrentWindow->DC.LastItemRect.GetBL();
126+ pos.y += 4;
127+ ImGui::SetNextWindowPos(pos);
128+ }
129+ if (ImGui::BeginPopupModal("New Virtual Joystick", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
130+ ImGui::Combo("Type", &vjoy_params.type_index, &GetJoystickTypeInfosForImGuiCombo, NULL, IM_ARRAYSIZE(joystick_type_infos));
131+ ImGui::InputInt("Num Axes", &vjoy_params.naxes, 1, 0);
132+ ImGui::InputInt("Num Balls", &vjoy_params.nballs);
133+ ImGui::InputInt("Num Buttons", &vjoy_params.nbuttons);
134+ ImGui::InputInt("Num Hats", &vjoy_params.nhats);
135+
136+ ImGui::Separator();
137+
138+ if (ImGui::Button("Create", ImVec2(120,0))) {
139+ SDL_JoystickType vjoy_type = SDL_JOYSTICK_TYPE_UNKNOWN;
140+ if (vjoy_params.type_index >= 0 &&
141+ vjoy_params.type_index < SDL_arraysize(joystick_type_infos))
142+ {
143+ vjoy_type = joystick_type_infos[vjoy_params.type_index].type;
144+ printf("vjoy_type: %d\n", (int)vjoy_type);
145+ }
146+ int vjoy_device_index = \
147+ SDL_JoystickAttachVirtual(vjoy_type,
148+ vjoy_params.naxes,
149+ vjoy_params.nballs,
150+ vjoy_params.nbuttons,
151+ vjoy_params.nhats);
152+ if (vjoy_device_index >= 0) {
153+ SDL_Joystick * vjoy = SDL_JoystickOpen(vjoy_device_index);
154+ if (vjoy) {
155+ vjoy_default_params = vjoy_params;
156+ }
157+ }
158+ ImGui::CloseCurrentPopup();
159+ }
160+ ImGui::SameLine();
161+ if (ImGui::Button("Cancel", ImVec2(120,0))) {
162+ ImGui::CloseCurrentPopup();
163+ }
164+ ImGui::EndPopup();
165+ }
166+ ImGui::SameLine();
167+ ImGui::Dummy(ImVec2(32,0));
168+ ImGui::SameLine();
169+ const int num_joysticks = SDL_NumJoysticks();
170+ ImGui::Text("Joysticks, Total-Count: %d", num_joysticks);
171+
172+ ImGui::Separator();
173+ ImGui::Separator();
174+
175+ ImGui::Columns(SDL_arraysize(main_columns), "JoystickList", true);
176+ for (int i = 0; i < SDL_arraysize(main_columns); ++i) {
177+ ImGui::SetColumnWidth(i, main_columns[i].width);
178+ }
179+ for (int i = 0; i < SDL_arraysize(main_columns); ++i) {
180+ ImGui::Text("%s", main_columns[i].name);
181+ ImGui::NextColumn();
182+ }
183+
184+ ImGui::Separator();
185+
186+ for (int device_index = 0; device_index < num_joysticks; ++device_index) {
187+ ImGui::PushID(device_index);
188+ SDL_JoystickID device_instance_id = SDL_JoystickGetDeviceInstanceID(device_index);
189+ SDL_Joystick * joystick = SDL_JoystickFromInstanceID(device_instance_id);
190+
191+ ImGuiTreeNodeFlags tree_node_flags = 0;
192+ if (joystick) {
193+ tree_node_flags |= ImGuiTreeNodeFlags_DefaultOpen;
194+ }
195+ const bool tree_node_is_open = ImGui::TreeNodeEx((void*)(intptr_t)device_index, tree_node_flags, ""); //, "Joystick #%d", device_index);
196+ ImGui::NextColumn();
197+#if 1
198+ if (!joystick) {
199+ if (ImGui::Button("Open")) {
200+ joystick = SDL_JoystickOpen(device_index);
201+ if (joystick != nullptr) {
202+ printf("Joystick opened successfully\n");
203+ } else {
204+ printf("Joystick open failed, SDL_GetError=(%s)\n", SDL_GetError());
205+ }
206+ device_instance_id = SDL_JoystickGetDeviceInstanceID(device_index);
207+ // printf("joystick: %p\n", joystick);
208+ // printf("SDL_JoystickGetDevicePlayerIndex(device_index): %d\n", SDL_JoystickGetDevicePlayerIndex(device_index));
209+ // if (joystick) {
210+ // printf("SDL_JoystickGetPlayerIndex(joystick): %d\n", SDL_JoystickGetPlayerIndex(joystick));
211+ // }
212+ }
213+ } else {
214+ if (ImGui::Button("Close")) {
215+ SDL_JoystickClose(joystick);
216+ joystick = nullptr;
217+ device_instance_id = SDL_JoystickGetDeviceInstanceID(device_index);
218+ }
219+ }
220+#endif
221+ ImGui::NextColumn();
222+
223+ ImGui::Text("%d", device_index);
224+ ImGui::NextColumn();
225+
226+ const char * joystick_name = SDL_JoystickNameForIndex(device_index);
227+ ImGui::Text("%s", (joystick_name ? joystick_name : "(null)"));
228+ ImGui::NextColumn();
229+
230+ ImGui::Text("%d", SDL_JoystickGetDevicePlayerIndex(device_index));
231+ ImGui::NextColumn();
232+ ImGui_TextGUID(SDL_JoystickGetDeviceGUID(device_index));
233+ ImGui::NextColumn();
234+
235+ ImGui::Text("%s", JoystickTypeName(SDL_JoystickGetDeviceType(device_index)));
236+ ImGui::NextColumn();
237+
238+ ImGui::Text("%d", (int)SDL_JoystickGetDeviceInstanceID(device_index));
239+ ImGui::NextColumn();
240+
241+ const SDL_bool is_joystick_virtual = SDL_JoystickIsVirtual(device_index);
242+ ImGui::Text("%s", (is_joystick_virtual == SDL_TRUE ? "YES" : "NO"));
243+
244+ ImGui::NextColumn();
245+
246+ if (tree_node_is_open) {
247+ // setup new state
248+ ImGui::PushID(device_index);
249+ ImGui::Columns(1);
250+
251+ // show sub-content
252+ ShowJoystickSubWindow(device_index);
253+
254+ // restore state
255+ ImGui::TreePop();
256+ ImGui::Columns(SDL_arraysize(main_columns), "JoystickList", true);
257+ for (int i = 0; i < SDL_arraysize(main_columns); ++i) {
258+ ImGui::SetColumnWidth(i, main_columns[i].width);
259+ }
260+ ImGui::PopID();
261+ }
262+
263+ ImGui::PopID();
264+ }
265+ ImGui::End();
266+}
267+
268+void ShowJoystickSubWindow(int device_index)
269+{
270+ SDL_JoystickID device_instance_id = SDL_JoystickGetDeviceInstanceID(device_index);
271+ SDL_Joystick * joystick = SDL_JoystickFromInstanceID(device_instance_id);
272+ if (!joystick) {
273+ return;
274+ }
275+ const SDL_bool is_joystick_virtual = SDL_JoystickIsVirtual(device_index);
276+
277+ char window_name[64];
278+ SDL_snprintf(window_name, SDL_arraysize(window_name), "Joystick #%d", device_index);
279+ ImGui::BeginChild(window_name, ImVec2(0,300), true, 0);
280+
281+ ImGui::Text("Is Virtual?: %s", (is_joystick_virtual == SDL_TRUE ? "YES" : "NO"));
282+
283+ ImGui::Separator();
284+
285+ ImGui::PushID("Buttons");
286+ const int nbuttons = SDL_JoystickNumButtons(joystick);
287+ ImGui::Text("Buttons: (count = %d)", nbuttons);
288+ ImGui::Separator();
289+ if (nbuttons > 0) {
290+ ImGui::Columns(nbuttons + 1);
291+
292+ struct {
293+ const char * name;
294+ bool show;
295+ } rowLabels[] = {
296+ { "Index:", true },
297+ { "State:", true },
298+ { "Raw State:", true },
299+ { "Edit:", is_joystick_virtual == SDL_TRUE },
300+ };
301+
302+ int num_rows = 0;
303+ for (int i = 0; i < SDL_arraysize(rowLabels); ++i) {
304+ if (rowLabels[i].show) {
305+ num_rows++;
306+ }
307+ }
308+
309+ ImGui::SetColumnWidth(0, 85);
310+ for (int i = 1; i < nbuttons + 1; ++i) {
311+ // ImGui::SetColumnWidth(i, ImGui::GetWindowWidth() / (nbuttons + 1));
312+ ImGui::SetColumnWidth(i, 70);
313+ }
314+
315+ for (int row = 0; row < SDL_arraysize(rowLabels); ++row) {
316+ if (!rowLabels[row].show) {
317+ continue;
318+ }
319+ ImGui::PushID(row);
320+ ImGui::Text("%s", rowLabels[row].name);
321+ ImGui::NextColumn();
322+
323+ for (int col = 0; col < nbuttons; ++col) {
324+ ImGui::PushID(col);
325+ const Uint8 buttonState = SDL_JoystickGetButton(joystick, col);
326+
327+ switch (row) {
328+ case 0: {
329+ // display button-index
330+ ImGui::Indent(4);
331+ ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(127, 255, 127));
332+ ImGui::Text("#%d", col);
333+ ImGui::PopStyleColor(1);
334+ ImGui::Unindent(4);
335+ break;
336+ }
337+
338+ case 1: {
339+ // display button-state as rectangle that lights up if pressed
340+ ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
341+ ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.f);
342+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 4));
343+ const ImVec4 buttonBgColor = (ImVec4)(
344+ (buttonState == 0) ?
345+ ImColor(0, 0, 0) :
346+ ImColor(255, 255, 0));
347+ ImGui::PushStyleColor(ImGuiCol_Button, buttonBgColor);
348+ ImGui::PushStyleColor(ImGuiCol_Border, (ImVec4)ImColor(255, 255, 255));
349+ ImGui::Button("", ImVec2(24, 24));
350+ ImGui::PopStyleColor(2);
351+ ImGui::PopStyleVar(3);
352+ break;
353+ };
354+
355+ case 2: {
356+ // display raw button-state
357+ ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(255, 255, 255));
358+ ImGui::Text("%d", buttonState);
359+ ImGui::PopStyleColor(1);
360+ break;
361+ }
362+
363+ case 3: {
364+ if (is_joystick_virtual) {
365+ ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 1.f);
366+ ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.f);
367+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 4));
368+ ImGui::PushStyleColor(ImGuiCol_Border, (ImVec4)ImColor(255, 255, 255));
369+ const float hue = 0.0f;
370+ const Uint8 current = SDL_JoystickGetButton(joystick, col);
371+ const float lightness_base = (current == 0 ? 0.0f : 0.7f);
372+ ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, std::clamp(lightness_base, 0.f, 1.f)));
373+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, std::clamp(lightness_base + 0.1f, 0.f, 1.f)));
374+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, std::clamp(lightness_base + 0.2f, 0.f, 1.f)));
375+ if (ImGui::Button("Toggle")) {
376+ SDL_JoystickSetVirtualButton(joystick, col, !current);
377+ }
378+ ImGui::PopStyleColor(4);
379+ ImGui::PopStyleVar(3);
380+ } else {
381+ ImGui::InvisibleButton("", ImVec2(4,4));
382+ }
383+ break;
384+ }
385+ }
386+
387+ ImGui::NextColumn();
388+ ImGui::PopID(); // col
389+ }
390+ ImGui::PopID(); // row
391+ }
392+ }
393+ ImGui::PopID();
394+
395+ ImGui::Spacing();
396+ ImGui::Columns(1);
397+ ImGui::Separator();
398+
399+ ImGui::PushID("Axes");
400+ const int naxes = SDL_JoystickNumAxes(joystick);
401+ ImGui::Text("Axes: (count = %d)", naxes);
402+ ImGui::Columns(4);
403+ ImGui::SetColumnWidth(0,60);
404+ ImGui::SetColumnWidth(1,110);
405+ ImGui::SetColumnWidth(2,80);
406+ ImGui::SetColumnWidth(3,300);
407+ ImGui::Text("Index"); ImGui::NextColumn();
408+ ImGui::Text("Initial Value"); ImGui::NextColumn();
409+ ImGui::Text("Raw Value"); ImGui::NextColumn();
410+ ImGui::Text("Value"); ImGui::NextColumn();
411+ ImGui::Separator();
412+ for (int i = 0; i < naxes; ++i) {
413+ ImGui::PushID(i);
414+ Sint16 axis = SDL_JoystickGetAxis(joystick, i);
415+ const float axis_normal = (((float)axis) - std::numeric_limits<Sint16>::min()) / (std::numeric_limits<Sint16>::max() - std::numeric_limits<Sint16>::min());
416+
417+ Sint16 axis_initial_state = 0;
418+ const SDL_bool axis_has_initial_state = SDL_JoystickGetAxisInitialState(joystick, i, &axis_initial_state);
419+ char initial_state_text[64];
420+ if (axis_has_initial_state) {
421+ SDL_snprintf(initial_state_text, SDL_arraysize(initial_state_text), "%d", (int)axis_initial_state);
422+ } else {
423+ SDL_strlcpy(initial_state_text, "N/A", SDL_arraysize(initial_state_text));
424+ }
425+
426+ ImGui::PushStyleColor(ImGuiCol_Text, (ImVec4)ImColor(127, 255, 127));
427+ ImGui::Text("#%d", i);
428+ ImGui::PopStyleColor(1);
429+ ImGui::NextColumn();
430+
431+ if (axis_has_initial_state) {
432+ ImGui::Text("%d", (int)axis_initial_state);
433+ } else {
434+ ImGui::Text("N/A");
435+ }
436+ ImGui::NextColumn();
437+
438+ ImGui::Text("%d", (int)axis);
439+ ImGui::NextColumn();
440+
441+ const Sint16 s16_min = std::numeric_limits<Sint16>::min();
442+ const Sint16 s16_max = std::numeric_limits<Sint16>::max();
443+ if (ImGui::SliderScalar("", ImGuiDataType_S16, &axis, &s16_min, &s16_max, "")) {
444+ if (is_joystick_virtual) {
445+ SDL_JoystickSetVirtualAxis(joystick, i, axis);
446+ }
447+ }
448+ if (is_joystick_virtual) {
449+ ImGui::SameLine();
450+ if (ImGui::Button("Reset")) {
451+ SDL_JoystickSetVirtualAxis(joystick, i, (axis_has_initial_state ? axis_initial_state : 0));
452+ }
453+ }
454+ ImGui::NextColumn();
455+ ImGui::PopID();
456+ }
457+ ImGui::PopID();
458+
459+ ImGui::Spacing();
460+ ImGui::Columns(1);
461+ ImGui::Separator();
462+
463+ ImGui::PushID("Balls");
464+ const int nballs = SDL_JoystickNumBalls(joystick);
465+ ImGui::Text("Balls: (count = %d)", nballs);
466+ ImGui::PopID();
467+
468+ ImGui::Spacing();
469+ ImGui::Columns(1);
470+ ImGui::Separator();
471+
472+ ImGui::PushID("Hats");
473+ const int nhats = SDL_JoystickNumHats(joystick);
474+ ImGui::Text("Hats: (count = %d)", nhats);
475+ ImGui::PopID();
476+
477+ ImGui::EndChild();
478+}
479+
480+int main()
481+{
482+ // Initialize SDL and ImGui
483+ const int sysWindowWidth = 1280;
484+ const int sysWindowHeight = 700;
485+ SDL_Init(SDL_INIT_EVERYTHING);
486+ SDL_Window * window = SDL_CreateWindow(
487+ "SDL Test Panel",
488+#if DEV_DAVIDL
489+ 1900, 450,
490+#else
491+ SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
492+#endif
493+ sysWindowWidth, sysWindowHeight,
494+ SDL_WINDOW_RESIZABLE);
495+ SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
496+ ImGui::CreateContext();
497+ ImGuiSDL::Initialize(renderer, sysWindowWidth, sysWindowHeight);
498+ SDL_Texture * texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, 100, 100);
499+ SDL_SetRenderTarget(renderer, texture);
500+ SDL_SetRenderDrawColor(renderer, 255, 0, 255, 255);
501+ SDL_RenderClear(renderer);
502+ SDL_SetRenderTarget(renderer, nullptr);
503+
504+#if DEV_DAVIDL
505+ // DEBUG: add a virtual joystick
506+ if (1) {
507+ const int vjoy_device_index = SDL_JoystickAttachVirtual(SDL_JOYSTICK_TYPE_GAMECONTROLLER, 2, 0, 4, 0);
508+ if (vjoy_device_index >= 0) {
509+ SDL_JoystickOpen(vjoy_device_index);
510+ }
511+ }
512+#endif
513+
514+ // Loop indefinitely while processing events and drawing content
515+ bool isRunning = true;
516+ while (isRunning) {
517+ // Process user-input events
518+ ImGuiIO & io = ImGui::GetIO();
519+ int wheel = 0;
520+ SDL_Event e;
521+ while (SDL_PollEvent(&e)) {
522+ switch (e.type) {
523+ case SDL_QUIT:
524+ isRunning = false;
525+ break;
526+ case SDL_WINDOWEVENT:
527+ if (e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
528+ {
529+ io.DisplaySize.x = static_cast<float>(e.window.data1);
530+ io.DisplaySize.y = static_cast<float>(e.window.data2);
531+ }
532+ break;
533+ case SDL_MOUSEWHEEL:
534+ wheel = e.wheel.y;
535+ break;
536+#if DEV_DAVIDL
537+ case SDL_JOYBUTTONDOWN:
538+ printf("SDL_JOYBUTTONDOWN\n");
539+ break;
540+ case SDL_JOYBUTTONUP:
541+ printf("SDL_JOYBUTTONUP\n");
542+ break;
543+ case SDL_JOYDEVICEADDED:
544+ printf("SDL_JOYDEVICEADDED\n");
545+ break;
546+ case SDL_JOYDEVICEREMOVED:
547+ printf("SDL_JOYDEVICEREMOVED\n");
548+ break;
549+
550+#endif
551+ default:
552+ ImGui_ImplSDL2_ProcessEvent(&e);
553+ break;
554+ }
555+ }
556+
557+ // Record time-advancement
558+ static Uint64 g_Time = 0;
559+ static const Uint64 frequency = SDL_GetPerformanceFrequency();
560+ const Uint64 current_time = SDL_GetPerformanceCounter();
561+ io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f);
562+ g_Time = current_time;
563+
564+ // Update mouse inputs
565+ int mouseX, mouseY;
566+ const int buttons = SDL_GetMouseState(&mouseX, &mouseY);
567+ io.MousePos = ImVec2(static_cast<float>(mouseX), static_cast<float>(mouseY));
568+ io.MouseDown[0] = buttons & SDL_BUTTON(SDL_BUTTON_LEFT);
569+ io.MouseDown[1] = buttons & SDL_BUTTON(SDL_BUTTON_RIGHT);
570+ io.MouseWheel = static_cast<float>(wheel);
571+
572+ // Tell ImGui that we're ready to draw a new frame
573+ ImGui::NewFrame();
574+
575+ // Layout this frame's ImGui
576+ static bool show_window_imgui_demo = false;
577+ static bool show_window_joysticks = true;
578+ if (ImGui::BeginMainMenuBar()) {
579+ if (ImGui::BeginMenu("View")) {
580+ ImGui::MenuItem("ImGui Demo Window...", NULL, &show_window_imgui_demo);
581+ ImGui::MenuItem("Joysticks...", NULL, &show_window_joysticks);
582+ ImGui::EndMenu();
583+ }
584+ ImGui::EndMainMenuBar();
585+ }
586+ if (show_window_imgui_demo) {
587+ ImGui::ShowDemoWindow();
588+ }
589+ if (show_window_joysticks) {
590+ ShowJoystickMainWindow();
591+ }
592+
593+ // Tell ImGui + SDL that we're done drawing, for now
594+ SDL_SetRenderDrawColor(renderer, 114, 144, 154, 255);
595+ SDL_RenderClear(renderer);
596+ ImGui::Render();
597+ ImGuiSDL::Render(ImGui::GetDrawData());
598+ SDL_RenderPresent(renderer);
599+ }
600+
601+ // Cleanup
602+ ImGuiSDL::Deinitialize();
603+ SDL_DestroyRenderer(renderer);
604+ SDL_DestroyWindow(window);
605+ ImGui::DestroyContext();
606+ return 0;
607+}
Show on old repository browser