@@ -6,111 +6,154 @@ struct EmulatorView: View {
6
6
@State private var loadError : Error ?
7
7
private let abButtonSize : CGFloat = 75
8
8
private let impactGenerator = UIImpactFeedbackGenerator ( style: . light)
9
+ @Environment ( \. verticalSizeClass) var verticalSizeClass
9
10
10
11
init ( romFilename: String ) {
11
12
self . romFilename = romFilename
12
13
self . bridge = EmulatorBridge . sharedInstance ( )
13
14
}
14
15
15
16
var body : some View {
17
+ Group {
18
+ if verticalSizeClass == . compact {
19
+ landscapeView
20
+ } else {
21
+ portraitView
22
+ }
23
+ }
24
+ . onAppear {
25
+ bridge. loadROM ( romFilename)
26
+ }
27
+ . onDisappear {
28
+ bridge. endEmulator ( )
29
+ }
30
+ . alert ( " Failed to load ROM " , isPresented: . constant( loadError != nil ) ) {
31
+ Button ( " OK " , role: . cancel) { loadError = nil }
32
+ } message: {
33
+ if let error = loadError {
34
+ Text ( error. localizedDescription)
35
+ }
36
+ }
37
+ . navigationBarHidden ( verticalSizeClass == . compact)
38
+ . navigationBarTitleDisplayMode ( . inline)
39
+ . statusBar ( hidden: verticalSizeClass == . compact)
40
+ }
41
+
42
+ @ViewBuilder
43
+ private var landscapeView : some View {
44
+ HStack {
45
+ DirectionalPadView ( )
46
+ GeometryReader { geometry in
47
+ EmulatorMetalView ( )
48
+ . frame ( width: geometry. size. height * ( 160.0 / 144.0 ) )
49
+ . frame ( height: geometry. size. height)
50
+ }
51
+ VStack {
52
+ abButtons
53
+ . padding ( . top, 50 )
54
+ . padding ( . vertical, 50 )
55
+ selectStartButtons
56
+ }
57
+ }
58
+ }
59
+
60
+ @ViewBuilder
61
+ private var portraitView : some View {
16
62
VStack ( spacing: 0 ) {
17
63
GeometryReader { geometry in
18
64
EmulatorMetalView ( )
19
65
. frame ( width: geometry. size. width)
20
66
. frame ( height: geometry. size. width * ( 144.0 / 160.0 ) )
21
67
}
22
-
23
- HStack ( spacing: 50 ) {
24
- DirectionalPadView ( )
25
-
26
- HStack ( spacing: 30 ) {
27
- Button ( " B " ) { }
28
- . frame ( width: abButtonSize, height: abButtonSize)
29
- . background ( Color . red)
30
- . foregroundColor ( . white)
31
- . clipShape ( Circle ( ) )
32
- . simultaneousGesture (
33
- DragGesture ( minimumDistance: 0 )
34
- . onChanged { _ in
35
- impactGenerator. impactOccurred ( )
36
- bridge. buttonB = true ;
37
- }
38
- . onEnded { _ in
39
- bridge. buttonB = false ;
40
- }
41
- )
42
- Button ( " A " ) { }
43
- . frame ( width: abButtonSize, height: abButtonSize)
44
- . background ( Color . red)
45
- . foregroundColor ( . white)
46
- . clipShape ( Circle ( ) )
47
- . offset ( y: - 30 )
48
- . simultaneousGesture (
49
- DragGesture ( minimumDistance: 0 )
50
- . onChanged { _ in
51
- impactGenerator. impactOccurred ( )
52
- bridge. buttonA = true ;
53
- }
54
- . onEnded { _ in
55
- bridge. buttonA = false ;
56
- }
57
- )
68
+ VStack ( spacing: 50 ) {
69
+ HStack ( spacing: 40 ) {
70
+ DirectionalPadView ( )
71
+ abButtons
72
+ . padding ( . horizontal, 10 )
73
+ . padding ( . vertical, 50 )
58
74
}
75
+ selectStartButtons
76
+ . padding ( . bottom, 30 )
59
77
}
60
- . padding ( . horizontal, 10 )
61
- . padding ( . vertical, 50 )
62
-
63
- HStack ( spacing: 30 ) {
64
- Button ( " Select " ) { }
65
- . frame ( width: 60 , height: 30 )
66
- . background ( Color . gray)
67
- . foregroundColor ( . white)
68
- . cornerRadius ( 15 )
69
- . simultaneousGesture (
70
- DragGesture ( minimumDistance: 0 )
71
- . onChanged { _ in
72
- impactGenerator. impactOccurred ( )
73
- bridge. buttonSelect = true ;
74
- }
75
- . onEnded { _ in
76
- bridge. buttonSelect = false ;
77
- }
78
- )
79
-
80
- Button ( " Start " ) { }
81
- . frame ( width: 60 , height: 30 )
82
- . background ( Color . gray)
83
- . foregroundColor ( . white)
84
- . cornerRadius ( 15 )
85
- . simultaneousGesture (
86
- DragGesture ( minimumDistance: 0 )
87
- . onChanged { _ in
88
- impactGenerator. impactOccurred ( )
89
- bridge. buttonStart = true ;
90
- }
91
- . onEnded { _ in
92
- bridge. buttonStart = false ;
93
- }
94
- )
95
- }
96
- . padding ( . bottom, 30 )
97
- }
98
- . onAppear {
99
- bridge. loadROM ( romFilename)
100
78
}
101
- . onDisappear {
102
- bridge. endEmulator ( )
79
+ }
80
+
81
+ @ViewBuilder
82
+ private var abButtons : some View {
83
+ HStack ( spacing: 30 ) {
84
+ Button ( " B " ) { }
85
+ . frame ( width: abButtonSize, height: abButtonSize)
86
+ . background ( Color . red)
87
+ . foregroundColor ( . white)
88
+ . clipShape ( Circle ( ) )
89
+ . simultaneousGesture (
90
+ DragGesture ( minimumDistance: 0 )
91
+ . onChanged { _ in
92
+ impactGenerator. impactOccurred ( )
93
+ bridge. buttonB = true ;
94
+ }
95
+ . onEnded { _ in
96
+ bridge. buttonB = false ;
97
+ }
98
+ )
99
+ Button ( " A " ) { }
100
+ . frame ( width: abButtonSize, height: abButtonSize)
101
+ . background ( Color . red)
102
+ . foregroundColor ( . white)
103
+ . clipShape ( Circle ( ) )
104
+ . offset ( y: - 30 )
105
+ . simultaneousGesture (
106
+ DragGesture ( minimumDistance: 0 )
107
+ . onChanged { _ in
108
+ impactGenerator. impactOccurred ( )
109
+ bridge. buttonA = true ;
110
+ }
111
+ . onEnded { _ in
112
+ bridge. buttonA = false ;
113
+ }
114
+ )
103
115
}
104
- . alert ( " Failed to load ROM " , isPresented: . constant( loadError != nil ) ) {
105
- Button ( " OK " , role: . cancel) { loadError = nil }
106
- } message: {
107
- if let error = loadError {
108
- Text ( error. localizedDescription)
109
- }
116
+ }
117
+
118
+ @ViewBuilder
119
+ private var selectStartButtons : some View {
120
+ HStack ( spacing: 30 ) {
121
+ Button ( " Select " ) { }
122
+ . frame ( width: 60 , height: 30 )
123
+ . background ( Color . gray)
124
+ . foregroundColor ( . white)
125
+ . cornerRadius ( 15 )
126
+ . simultaneousGesture (
127
+ DragGesture ( minimumDistance: 0 )
128
+ . onChanged { _ in
129
+ impactGenerator. impactOccurred ( )
130
+ bridge. buttonSelect = true ;
131
+ }
132
+ . onEnded { _ in
133
+ bridge. buttonSelect = false ;
134
+ }
135
+ )
136
+
137
+ Button ( " Start " ) { }
138
+ . frame ( width: 60 , height: 30 )
139
+ . background ( Color . gray)
140
+ . foregroundColor ( . white)
141
+ . cornerRadius ( 15 )
142
+ . simultaneousGesture (
143
+ DragGesture ( minimumDistance: 0 )
144
+ . onChanged { _ in
145
+ impactGenerator. impactOccurred ( )
146
+ bridge. buttonStart = true ;
147
+ }
148
+ . onEnded { _ in
149
+ bridge. buttonStart = false ;
150
+ }
151
+ )
110
152
}
111
153
}
112
154
}
113
-
155
+
156
+
114
157
// Preview provider
115
158
struct ContentView_Previews : PreviewProvider {
116
159
static var previews : some View {
0 commit comments