summaryrefslogtreecommitdiff
path: root/src/port/ui/ImguiUI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/port/ui/ImguiUI.cpp')
-rw-r--r--src/port/ui/ImguiUI.cpp134
1 files changed, 131 insertions, 3 deletions
diff --git a/src/port/ui/ImguiUI.cpp b/src/port/ui/ImguiUI.cpp
index 615a07d0..be909fc6 100644
--- a/src/port/ui/ImguiUI.cpp
+++ b/src/port/ui/ImguiUI.cpp
@@ -116,6 +116,117 @@ static const char* voiceLangs[] = {
"Original", /*"Japanese",*/ "Lylat"
};
+void DrawSpeakerPositionEditor() {
+ static ImVec2 lastCanvasPos;
+ ImGui::Text("Speaker Position Editor");
+ ImVec2 canvasSize = ImVec2(200, 200); // Static canvas size
+ ImVec2 canvasPos = ImGui::GetCursorScreenPos();
+ ImVec2 center = ImVec2(canvasPos.x + canvasSize.x / 2, canvasPos.y + canvasSize.y / 2);
+
+ // Speaker positions
+ static ImVec2 speakerPositions[4];
+ static bool initialized = false;
+ static float radius = 80.0f;
+
+ // Reset positions if canvas position changed (window resized/moved)
+ if (!initialized || (lastCanvasPos.x != canvasPos.x || lastCanvasPos.y != canvasPos.y)) {
+ const char* cvarNames[4] = { "gPositionFrontLeft", "gPositionFrontRight", "gPositionRearLeft", "gPositionRearRight" };
+ float angles[4] = { 240.f, 300.f, 160.f, 20.f }; // Default angles
+
+ for (int i = 0; i < 4; i++) {
+ int savedAngle = CVarGetInteger(cvarNames[i], -1);
+ if (savedAngle != -1) {
+ angles[i] = static_cast<float>(savedAngle);
+ }
+
+ float rad = angles[i] * (M_PI / 180.0f);
+ speakerPositions[i] = ImVec2(center.x + radius * cosf(rad), center.y + radius * sinf(rad));
+ }
+ initialized = true;
+ lastCanvasPos = canvasPos;
+ }
+
+ // Draw canvas
+ ImDrawList* drawList = ImGui::GetWindowDrawList();
+ drawList->AddRectFilled(canvasPos, ImVec2(canvasPos.x + canvasSize.x, canvasPos.y + canvasSize.y), IM_COL32(26, 26, 26, 255));
+ drawList->AddCircleFilled(center, 5.0f, IM_COL32(255, 255, 255, 255)); // Central person
+
+ // Draw circle line for speaker positions
+ drawList->AddCircle(center, radius, IM_COL32(163, 163, 163, 255), 100);
+
+ // Add markers at 0, 22.5, 45, etc.
+ for (float angle = 0; angle < 360; angle += 22.5f) {
+ float rad = angle * (M_PI / 180.0f);
+ ImVec2 markerStart = ImVec2(center.x + (radius - 5) * cosf(rad), center.y + (radius - 5) * sinf(rad));
+ ImVec2 markerEnd = ImVec2(center.x + radius * cosf(rad), center.y + radius * sinf(rad));
+ drawList->AddLine(markerStart, markerEnd, IM_COL32(163, 163, 163, 255));
+ }
+
+ const char* speakerLabels[4] = { "L", "R", "RL", "RR" };
+ const char* cvarNames[4] = { "gPositionFrontLeft", "gPositionFrontRight", "gPositionRearLeft", "gPositionRearRight" };
+
+ const float snapThreshold = 2.5f; // Degrees within which snapping occurs
+
+ for (int i = 0; i < 4; i++) {
+ // Draw speaker as a darker blue circle
+ drawList->AddCircleFilled(speakerPositions[i], 10.0f, IM_COL32(34, 52, 78, 255)); // Dark blue color
+ drawList->AddText(ImVec2(speakerPositions[i].x - 6, speakerPositions[i].y - 6), IM_COL32(255, 255, 255, 255), speakerLabels[i]);
+
+ // Handle dragging
+ ImGui::SetCursorScreenPos(ImVec2(speakerPositions[i].x - 10, speakerPositions[i].y - 10));
+ ImGui::InvisibleButton(speakerLabels[i], ImVec2(20, 20));
+ if (ImGui::IsItemActive() && ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
+ ImVec2 mouseDelta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Left);
+ ImVec2 newPos = ImVec2(speakerPositions[i].x + mouseDelta.x, speakerPositions[i].y + mouseDelta.y);
+
+ // Constrain position to the circle
+ ImVec2 direction = ImVec2(newPos.x - center.x, newPos.y - center.y);
+ float length = sqrtf(direction.x * direction.x + direction.y * direction.y);
+ ImVec2 constrainedPos = ImVec2(center.x + (direction.x / length) * radius, center.y + (direction.y / length) * radius);
+
+ // Calculate angle of the constrained position
+ float angle = atan2f(constrainedPos.y - center.y, constrainedPos.x - center.x) * (180.0f / M_PI);
+ if (angle < 0) angle += 360.0f;
+
+ // Snap to the nearest 22.5-degree marker if within the snap threshold
+ float snappedAngle = roundf(angle / 22.5f) * 22.5f;
+ if (fabsf(snappedAngle - angle) <= snapThreshold) {
+ float rad = snappedAngle * (M_PI / 180.0f);
+ constrainedPos = ImVec2(center.x + radius * cosf(rad), center.y + radius * sinf(rad));
+ }
+
+ speakerPositions[i] = constrainedPos;
+ ImGui::ResetMouseDragDelta();
+
+ // Save the updated angle to CVar after dragging
+ float updatedAngle = atan2f(speakerPositions[i].y - center.y, speakerPositions[i].x - center.x) * (180.0f / M_PI);
+ if (updatedAngle < 0) updatedAngle += 360.0f;
+ CVarSetInteger(cvarNames[i], static_cast<int>(updatedAngle));
+ Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame(); // Mark for saving
+ }
+
+ // Calculate angle and save to CVar
+ float angle = atan2f(speakerPositions[i].y - center.y, speakerPositions[i].x - center.x) * (180.0f / M_PI);
+ if (angle < 0) angle += 360.0f;
+ CVarSetInteger(cvarNames[i], static_cast<int>(angle));
+ }
+
+ // Reset cursor position for button placement
+ ImGui::SetCursorScreenPos(ImVec2(canvasPos.x, canvasPos.y + canvasSize.y + 10));
+ if (ImGui::Button("Reset Positions")) {
+ float defaultAngles[4] = { 240.f, 300.f, 160.f, 20.f };
+ for (int i = 0; i < 4; i++) {
+ float rad = defaultAngles[i] * (M_PI / 180.0f);
+ speakerPositions[i] = ImVec2(center.x + radius * cosf(rad), center.y + radius * sinf(rad));
+ CVarSetInteger(cvarNames[i], static_cast<int>(defaultAngles[i]));
+ }
+ Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
+ }
+
+ // Reset cursor position to ensure canvas size remains static
+ ImGui::SetCursorScreenPos(ImVec2(canvasPos.x, canvasPos.y + canvasSize.y + 10));
+}
+
void DrawSettingsMenu(){
if(UIWidgets::BeginMenu("Settings")){
if (UIWidgets::BeginMenu("Audio")) {
@@ -173,6 +284,23 @@ void DrawSettingsMenu(){
}
UIWidgets::PaddedEnhancementCheckbox("Surround 5.1 (Needs reload)", "gAudioChannelsSetting", 1, 0);
+
+ if (CVarGetInteger("gAudioChannelsSetting", 0) == 1) {
+ // Subwoofer threshold
+ UIWidgets::CVarSliderInt("Subwoofer threshold (Hz)", "gSubwooferThreshold", 10u, 1000u, 80u, {
+ .tooltip = "The threshold for the subwoofer to be activated. Any sound under this frequency will be played on the subwoofer.",
+ .format = "%d",
+ });
+
+ // Rear music volume slider
+ UIWidgets::CVarSliderFloat("Rear music volume", "gVolumeRearMusic", 0.0f, 1.0f, 1.0f, {
+ .format = "%.0f%%",
+ .isPercentage = true,
+ });
+
+ // Configurable positioning of speakers
+ DrawSpeakerPositionEditor();
+ }
ImGui::EndMenu();
}
@@ -192,10 +320,10 @@ void DrawSettingsMenu(){
};
} else {
if (UIWidgets::Button("Install JP/EU Audio")) {
- if (GameEngine::GenAssetFile()){
+ if (GameEngine::GenAssetFile(false)){
GameEngine::ShowMessage("Success", "Audio assets installed. Changes will be applied on the next startup.", SDL_MESSAGEBOX_INFORMATION);
- Ship::Context::GetInstance()->GetWindow()->Close();
}
+ Ship::Context::GetInstance()->GetWindow()->Close();
}
}
ImGui::EndMenu();
@@ -321,7 +449,7 @@ void DrawSettingsMenu(){
UIWidgets::Tooltip("Matches interpolation value to the refresh rate of your display.");
if (Ship::Context::GetInstance()->GetWindow()->GetWindowBackend() == Ship::WindowBackend::FAST3D_DXGI_DX11) {
- UIWidgets::PaddedEnhancementCheckbox("Render parallelization","gRenderParallelization", true, false);
+ UIWidgets::PaddedEnhancementCheckbox("Render parallelization","gRenderParallelization", true, false, {}, {}, {}, true);
UIWidgets::Tooltip(
"This setting allows the CPU to work on one frame while GPU works on the previous frame.\n"
"Recommended if you can't reach the FPS you set, despite it being set below your refresh rate "