fix: square, grid-aligned D-pad and face buttons
Give both clusters a shared 100x100 footprint so they align on the same grid: D-pad cells are now square (30x30 with 5pt gaps) and the ABXY diamond is positioned on its diagonals instead of stacked rows. Drops the height-matching frame hack from the card layout. Co-Authored-By: qwen3.8-27b@q3_k_xl: squared and aligned the clusters
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@ if(NOT CMAKE_GENERATOR MATCHES "^(Ninja|Xcode)$")
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.21)
|
cmake_minimum_required(VERSION 3.21)
|
||||||
project(xone_macos VERSION 0.1.23 LANGUAGES CXX Swift)
|
project(xone_macos VERSION 0.1.24 LANGUAGES CXX Swift)
|
||||||
|
|
||||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ struct ControllerCardView: View {
|
|||||||
StickPadView(label: "L", x: controller.stickLeftX, y: controller.stickLeftY,
|
StickPadView(label: "L", x: controller.stickLeftX, y: controller.stickLeftY,
|
||||||
pressed: controller.isPressed(.leftStick))
|
pressed: controller.isPressed(.leftStick))
|
||||||
DPadView(controller: controller)
|
DPadView(controller: controller)
|
||||||
.frame(height: 104)
|
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
|
|
||||||
@@ -79,7 +78,6 @@ struct ControllerCardView: View {
|
|||||||
StickPadView(label: "R", x: controller.stickRightX, y: controller.stickRightY,
|
StickPadView(label: "R", x: controller.stickRightX, y: controller.stickRightY,
|
||||||
pressed: controller.isPressed(.rightStick))
|
pressed: controller.isPressed(.rightStick))
|
||||||
FaceButtonsView(controller: controller)
|
FaceButtonsView(controller: controller)
|
||||||
.frame(height: 104)
|
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-19
@@ -4,28 +4,34 @@ import SwiftUI
|
|||||||
// buttons on top, stick pads and triggers below, mirroring the physical
|
// buttons on top, stick pads and triggers below, mirroring the physical
|
||||||
// layout of an Xbox controller.
|
// layout of an Xbox controller.
|
||||||
|
|
||||||
|
// Both clusters (D-pad and face buttons) share a 100x100 footprint so they
|
||||||
|
// align on the same grid in the card layout.
|
||||||
|
|
||||||
struct DPadView: View {
|
struct DPadView: View {
|
||||||
let controller: ControllerInput
|
let controller: ControllerInput
|
||||||
|
|
||||||
|
private let cell: CGFloat = 30
|
||||||
|
private let gap: CGFloat = 5
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 3) {
|
VStack(spacing: gap) {
|
||||||
cell(.dPadUp)
|
cellView(.dPadUp)
|
||||||
HStack(spacing: 3) {
|
HStack(spacing: gap) {
|
||||||
cell(.dPadLeft)
|
cellView(.dPadLeft)
|
||||||
RoundedRectangle(cornerRadius: 5)
|
RoundedRectangle(cornerRadius: 6)
|
||||||
.fill(Color.secondary.opacity(0.28))
|
.fill(Color.secondary.opacity(0.28))
|
||||||
.frame(width: 30, height: 26)
|
.frame(width: cell, height: cell)
|
||||||
cell(.dPadRight)
|
cellView(.dPadRight)
|
||||||
}
|
}
|
||||||
cell(.dPadDown)
|
cellView(.dPadDown)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func cell(_ button: XboxButton) -> some View {
|
private func cellView(_ button: XboxButton) -> some View {
|
||||||
let pressed = controller.isPressed(button)
|
let pressed = controller.isPressed(button)
|
||||||
return RoundedRectangle(cornerRadius: 5)
|
return RoundedRectangle(cornerRadius: 6)
|
||||||
.fill(pressed ? Color.green : Color.secondary.opacity(0.18))
|
.fill(pressed ? Color.green : Color.secondary.opacity(0.18))
|
||||||
.frame(width: 30, height: 26)
|
.frame(width: cell, height: cell)
|
||||||
.overlay(
|
.overlay(
|
||||||
Image(systemName: button.dPadSymbol ?? "")
|
Image(systemName: button.dPadSymbol ?? "")
|
||||||
.font(.system(size: 9))
|
.font(.system(size: 9))
|
||||||
@@ -38,21 +44,20 @@ struct FaceButtonsView: View {
|
|||||||
let controller: ControllerInput
|
let controller: ControllerInput
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 4) {
|
ZStack {
|
||||||
faceButton(.y)
|
faceButton(.y).offset(y: -35)
|
||||||
HStack(spacing: 10) {
|
faceButton(.x).offset(x: -35)
|
||||||
faceButton(.x)
|
faceButton(.b).offset(x: 35)
|
||||||
faceButton(.b)
|
faceButton(.a).offset(y: 35)
|
||||||
}
|
|
||||||
faceButton(.a)
|
|
||||||
}
|
}
|
||||||
|
.frame(width: 100, height: 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func faceButton(_ button: XboxButton) -> some View {
|
private func faceButton(_ button: XboxButton) -> some View {
|
||||||
let pressed = controller.isPressed(button)
|
let pressed = controller.isPressed(button)
|
||||||
return Text(button.label)
|
return Text(button.label)
|
||||||
.font(.callout.weight(.semibold))
|
.font(.callout.weight(.semibold))
|
||||||
.frame(width: 32, height: 32)
|
.frame(width: 30, height: 30)
|
||||||
.background(Circle().fill(pressed ? Color.green : Color.secondary.opacity(0.18)))
|
.background(Circle().fill(pressed ? Color.green : Color.secondary.opacity(0.18)))
|
||||||
.foregroundStyle(pressed ? .white : .primary)
|
.foregroundStyle(pressed ? .white : .primary)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user