ASAPCabinetFE
 
Loading...
Searching...
No Matches
isection_renderer.h
Go to the documentation of this file.
1
10#ifndef ISECTION_RENDERER_H
11#define ISECTION_RENDERER_H
12
13#include <nlohmann/json.hpp>
14#include <string>
15#include <vector>
16#include <unordered_map>
17#include <imgui.h>
18#include <filesystem>
19#include "ImGuiFileDialog.h"
20#include "log/logging.h"
21
23public:
24 virtual ~ISectionRenderer() = default;
25
26 virtual void render(const std::string& sectionName, nlohmann::json& sectionData, bool& isCapturing,
27 std::string& capturingKeyName, ImGuiFileDialog* fileDialog, bool defaultOpen = false,
28 bool& isDialogOpen = *(new bool(false)), std::string& dialogKey = *(new std::string())) = 0;
29};
30
32protected:
33 void renderBool(const std::string& key, nlohmann::json& value, const std::string& sectionName) {
34 bool val = value.get<bool>();
35 if (ImGui::Checkbox(key.c_str(), &val)) {
36 value = val;
37 LOG_DEBUG("Updated " + sectionName + "." + key + " to " + std::to_string(val));
38 }
39 }
40
41 void renderFloat(const std::string& key, nlohmann::json& value, const std::string& sectionName,
42 float minVal = 0.0f, float maxVal = 1.0f, const char* format = "%.2f") {
43 float val = value.get<float>();
44 if (key == "titleWeight") {
45 minVal = 0.2f; maxVal = 0.8f;
46 } else if (key == "yearWeight") {
47 minVal = 0.0f; maxVal = 0.4f;
48 } else if (key == "manufacturerWeight") {
49 minVal = 0.0f; maxVal = 0.3f;
50 } else if (key == "romWeight") {
51 minVal = 0.0f; maxVal = 0.5f;
52 } else if (key == "titleThreshold") {
53 minVal = 0.3f; maxVal = 0.8f;
54 } else if (key == "confidenceThreshold") {
55 minVal = 0.4f; maxVal = 0.9f;
56 } else if (key == "DPI Scale") {
57 minVal = 0.5f; maxVal = 3.0f;
58 } else if (key.find("Alpha") != std::string::npos || key == "scrollbarLength" ||
59 key == "metadataPanelWidth" || key == "metadataPanelHeight") {
60 minVal = 0.0f; maxVal = 1.0f;
61 } else if (key == "arrowHintWidth" || key == "arrowHintHeight") {
62 minVal = 0.0f; maxVal = 200.0f;
63 } else if (key == "arrowThickness" || key == "arrowGlow") {
64 minVal = 0.0f; maxVal = 10.0f;
65 } else if (key == "scrollbarWidth" || key == "thumbWidth") {
66 minVal = 0.0f; maxVal = 50.0f;
67 } else if (key == "masterVol" || key == "mediaAudioVol" || key == "tableMusicVol" ||
68 key == "interfaceAudioVol" || key == "interfaceAmbienceVol") {
69 minVal = 0.0f; maxVal = 100.0f;
70 } else if (key == "configUIWidth" || key == "configUIHeight") {
71 minVal = 0.1f; maxVal = 1.0f;
72 }
73 if (ImGui::SliderFloat(key.c_str(), &val, minVal, maxVal, format)) {
74 value = val;
75 LOG_DEBUG("Updated " + sectionName + "." + key + " to " + std::to_string(val));
76 }
77 }
78
79 void renderInt(const std::string& key, nlohmann::json& value, const std::string& sectionName,
80 int minVal = 0, int maxVal = 10000) {
81 int val = value.get<int>();
82 if (key.find("WindowWidth") != std::string::npos || key.find("WindowHeight") != std::string::npos ||
83 key.find("MediaWidth") != std::string::npos || key.find("MediaHeight") != std::string::npos) {
84 minVal = 0; maxVal = 3840;
85 } else if (key == "fontSize") {
86 minVal = 10; maxVal = 60;
87 } else if (key == "screenshotWait") {
88 minVal = 0; maxVal = 60;
89 }
90 if (ImGui::InputInt(key.c_str(), &val)) {
91 val = std::clamp(val, minVal, maxVal);
92 value = val;
93 LOG_DEBUG("Updated " + sectionName + "." + key + " to " + std::to_string(val));
94 }
95 }
96
97 void renderString(const std::string& key, nlohmann::json& value, const std::string& sectionName) {
98 std::string val = value.get<std::string>();
99 char buffer[256];
100 strncpy(buffer, val.c_str(), sizeof(buffer) - 1);
101 buffer[sizeof(buffer) - 1] = '\0';
102 if (ImGui::InputText(key.c_str(), buffer, sizeof(buffer))) {
103 value = std::string(buffer);
104 LOG_DEBUG("Updated " + sectionName + "." + key + " to " + buffer);
105 }
106 }
107
108 void renderColor(const std::string& key, nlohmann::json& value, const std::string& sectionName) {
109 float color[4] = {
110 value[0].get<float>() / 255.0f,
111 value[1].get<float>() / 255.0f,
112 value[2].get<float>() / 255.0f,
113 value[3].get<float>() / 255.0f
114 };
115 if (ImGui::ColorEdit4(key.c_str(), color)) {
116 value = nlohmann::json{
117 static_cast<int>(color[0] * 255.0f),
118 static_cast<int>(color[1] * 255.0f),
119 static_cast<int>(color[2] * 255.0f),
120 static_cast<int>(color[3] * 255.0f)
121 };
122 LOG_DEBUG("Updated " + sectionName + "." + key + " to [" +
123 std::to_string(value[0].get<int>()) + "," +
124 std::to_string(value[1].get<int>()) + "," +
125 std::to_string(value[2].get<int>()) + "," +
126 std::to_string(value[3].get<int>()) + "]");
127 }
128 }
129
130 void renderRotation(const std::string& key, nlohmann::json& value, const std::string& sectionName) {
131 int val = value.get<int>();
132 static std::unordered_map<std::string, int> lastLoggedValues;
133 int currentValue = snapToStep(val);
134 if (ImGui::SliderInt(key.c_str(), &currentValue, 0, 360, "%d°")) {
135 int snappedValue = snapToStep(currentValue);
136 if (snappedValue != lastLoggedValues[key]) {
137 value = snappedValue;
138 lastLoggedValues[key] = snappedValue;
139 LOG_DEBUG("Updated " + sectionName + "." + key + " to " + std::to_string(snappedValue) + "°");
140 }
141 }
142 }
143
144 void renderKeybind(const std::string& key, nlohmann::json& value, const std::string& sectionName,
145 bool& isCapturing, std::string& capturingKeyName) {
146 if (!value.is_string()) {
147 LOG_DEBUG("Invalid type for keybind " + key + ", expected string, got " + value.type_name());
148 return;
149 }
150 std::string currentBind = value.get<std::string>();
151 std::string buttonLabel = "[" + key + ": " + (currentBind.empty() ? "Unbound" : currentBind) + "]";
152 if (ImGui::Button(buttonLabel.c_str(), ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
153 if (!isCapturing) {
154 isCapturing = true;
155 capturingKeyName = key;
156 LOG_DEBUG("Started capturing key for " + sectionName + "." + key);
157 }
158 }
159 if (isCapturing && capturingKeyName == key) {
160 ImGui::Text("Press a key or joystick input to bind... (Esc to cancel)");
161 }
162 }
163
164 void renderPathOrExecutable(const std::string& key, nlohmann::json& value, const std::string& sectionName,
165 ImGuiFileDialog* fileDialog, bool& isDialogOpen, std::string& dialogKey) {
166 std::string val = value.get<std::string>();
167 char buffer[1024];
168 strncpy(buffer, val.c_str(), sizeof(buffer) - 1);
169 buffer[sizeof(buffer) - 1] = '\0';
170 ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - 60);
171 if (ImGui::InputText("##value", buffer, sizeof(buffer))) {
172 value = std::string(buffer);
173 LOG_DEBUG("Updated " + sectionName + "." + key + " to " + buffer);
174 }
175 ImGui::PopItemWidth();
176 ImGui::SameLine();
177 if (ImGui::Button("Browse", ImVec2(50, 0))) {
178 LOG_DEBUG("Browse button clicked for " + key);
179 IGFD::FileDialogConfig config;
180 config.path = (!val.empty() && std::filesystem::exists(val)) ? std::filesystem::path(val).parent_path().string() : std::string(getenv("HOME"));
181 config.flags = ImGuiFileDialogFlags_Modal;
182 fileDialog->SetFileStyle(IGFD_FileStyleByTypeDir, nullptr, ImVec4(0.5f, 1.0f, 0.9f, 0.9f));
183
184 if (key == "VPXTablesPath") {
185 fileDialog->OpenDialog("FolderDlg_VPXTablesPath", "Select VPX Tables Folder", nullptr, config);
186 } else if (key == "VPinballXPath") {
187 fileDialog->SetFileStyle(IGFD_FileStyleByFullName, "VPinballX*", ImVec4(0.0f, 1.0f, 0.0f, 0.9f));
188 fileDialog->OpenDialog("FileDlg_VPinballXPath", "Select VPinballX Executable", "VPinballX*", config);
189 } else if (key == "vpxIniPath") {
190 fileDialog->SetFileStyle(IGFD_FileStyleByExtention, ".ini", ImVec4(1.0f, 1.0f, 0.0f, 0.9f));
191 fileDialog->OpenDialog("FileDlg_vpxIniPath", "Select VPinballX Config File", ".ini", config);
192 }
193 isDialogOpen = true;
194 dialogKey = key;
195 LOG_DEBUG("Dialog opened with key: " + dialogKey + ", isDialogOpen: " + std::to_string(isDialogOpen));
196 }
197 }
198
199 int snapToStep(int value) {
200 const int steps[] = {0, 90, 180, 270, 360};
201 int nearestStep = 0;
202 int minDiff = abs(value - steps[0]);
203 for (int i = 1; i < 5; ++i) {
204 int diff = abs(value - steps[i]);
205 if (diff < minDiff) {
206 minDiff = diff;
207 nearestStep = steps[i];
208 }
209 }
210 return nearestStep;
211 }
212};
213
214#endif // ISECTION_RENDERER_H
Definition isection_renderer.h:31
Definition isection_renderer.h:22