1
+ use std:: cell:: RefCell ;
1
2
use std:: io:: { self , Read , Write } ;
3
+ use std:: rc:: Rc ;
2
4
3
5
use serde:: { Deserialize , Serialize } ;
4
6
5
7
use coupler:: format:: clap:: * ;
6
8
use coupler:: format:: vst3:: * ;
9
+ use coupler:: params:: { ParamId , ParamValue } ;
10
+ use coupler:: view:: { ParentWindow , RawParent , Size , View } ;
7
11
use coupler:: { buffers:: * , bus:: * , engine:: * , events:: * , host:: * , params:: * , plugin:: * , view:: * } ;
8
12
9
- use coupler_reflector:: PluginWindow ;
13
+ use reflector:: graphics:: Renderer ;
14
+ use reflector:: platform:: {
15
+ App , AppMode , AppOptions , Bitmap , Cursor , MouseButton , Point , RawWindow , Response , Result ,
16
+ Window , WindowContext , WindowOptions ,
17
+ } ;
10
18
11
19
#[ derive( Params , Serialize , Deserialize , Clone ) ]
12
20
struct GainParams {
@@ -26,7 +34,7 @@ pub struct Gain {
26
34
27
35
impl Plugin for Gain {
28
36
type Engine = GainEngine ;
29
- type View = PluginWindow ;
37
+ type View = GainView ;
30
38
31
39
fn info ( ) -> PluginInfo {
32
40
PluginInfo {
@@ -84,13 +92,8 @@ impl Plugin for Gain {
84
92
}
85
93
}
86
94
87
- fn view ( & mut self , _host : ViewHost , parent : & ParentWindow ) -> Self :: View {
88
- let size = Size {
89
- width : 512.0 ,
90
- height : 512.0 ,
91
- } ;
92
-
93
- PluginWindow :: open ( parent, size) . unwrap ( )
95
+ fn view ( & mut self , host : ViewHost , parent : & ParentWindow ) -> Self :: View {
96
+ GainView :: open ( host, parent, & self . params ) . unwrap ( )
94
97
}
95
98
}
96
99
@@ -146,3 +149,179 @@ impl Engine for GainEngine {
146
149
}
147
150
}
148
151
}
152
+
153
+ struct Gesture {
154
+ start_mouse_pos : Point ,
155
+ start_value : f32 ,
156
+ }
157
+
158
+ struct ViewState {
159
+ host : ViewHost ,
160
+ params : Rc < RefCell < GainParams > > ,
161
+ renderer : Renderer ,
162
+ framebuffer : Vec < u32 > ,
163
+ mouse_pos : Point ,
164
+ gesture : Option < Gesture > ,
165
+ }
166
+
167
+ impl ViewState {
168
+ fn new ( host : ViewHost , params : Rc < RefCell < GainParams > > ) -> ViewState {
169
+ ViewState {
170
+ host,
171
+ params,
172
+ renderer : Renderer :: new ( ) ,
173
+ framebuffer : Vec :: new ( ) ,
174
+ mouse_pos : Point { x : -1.0 , y : -1.0 } ,
175
+ gesture : None ,
176
+ }
177
+ }
178
+
179
+ fn update_cursor ( & self , window : & Window ) {
180
+ let pos = self . mouse_pos ;
181
+ if pos. x >= 96.0 && pos. x < 160.0 && pos. y >= 96.0 && pos. y < 160.0 {
182
+ window. set_cursor ( Cursor :: SizeNs ) ;
183
+ } else {
184
+ window. set_cursor ( Cursor :: Arrow ) ;
185
+ }
186
+ }
187
+
188
+ fn handle_event ( & mut self , cx : & WindowContext , event : reflector:: platform:: Event ) -> Response {
189
+ use reflector:: graphics:: { Affine , Color , Path , Point } ;
190
+ use reflector:: platform:: Event ;
191
+
192
+ match event {
193
+ Event :: Frame => {
194
+ let scale = cx. window ( ) . scale ( ) ;
195
+ let size = cx. window ( ) . size ( ) ;
196
+ let width = ( size. width * scale) as usize ;
197
+ let height = ( size. height * scale) as usize ;
198
+ self . framebuffer . resize ( width * height, 0xFF000000 ) ;
199
+
200
+ let mut canvas = self . renderer . canvas ( & mut self . framebuffer , width, height) ;
201
+
202
+ canvas. clear ( Color :: rgba ( 21 , 26 , 31 , 255 ) ) ;
203
+
204
+ let transform = Affine :: scale ( scale as f32 ) ;
205
+
206
+ let value = self . params . borrow ( ) . gain ;
207
+
208
+ let center = Point :: new ( 128.0 , 128.0 ) ;
209
+ let radius = 32.0 ;
210
+ let angle1 = 0.75 * std:: f32:: consts:: PI ;
211
+ let angle2 = angle1 + value * 1.5 * std:: f32:: consts:: PI ;
212
+ let mut path = Path :: new ( ) ;
213
+ path. move_to ( center + radius * Point :: new ( angle1. cos ( ) , angle1. sin ( ) ) ) ;
214
+ path. arc ( radius, angle1, angle2) ;
215
+ path. line_to ( center + ( radius - 4.0 ) * Point :: new ( angle2. cos ( ) , angle2. sin ( ) ) ) ;
216
+ path. arc ( radius - 4.0 , angle2, angle1) ;
217
+ path. close ( ) ;
218
+ canvas. fill_path ( & path, transform, Color :: rgba ( 240 , 240 , 245 , 255 ) ) ;
219
+
220
+ let center = Point :: new ( 128.0 , 128.0 ) ;
221
+ let radius = 32.0 ;
222
+ let angle = 0.75 * std:: f32:: consts:: PI ;
223
+ let span = 1.5 * std:: f32:: consts:: PI ;
224
+ let mut path = Path :: new ( ) ;
225
+ path. move_to ( center + radius * Point :: new ( angle. cos ( ) , angle. sin ( ) ) ) ;
226
+ path. arc ( radius, angle, angle + span) ;
227
+ path. line_to ( center + ( radius - 4.0 ) * Point :: new ( -angle. cos ( ) , angle. sin ( ) ) ) ;
228
+ path. arc ( radius - 4.0 , angle + span, angle) ;
229
+ path. close ( ) ;
230
+ canvas. stroke_path ( & path, 1.0 , transform, Color :: rgba ( 240 , 240 , 245 , 255 ) ) ;
231
+
232
+ cx. window ( ) . present ( Bitmap :: new ( & self . framebuffer , width, height) ) ;
233
+ }
234
+ Event :: MouseMove ( pos) => {
235
+ self . mouse_pos = pos;
236
+ if let Some ( gesture) = & self . gesture {
237
+ let delta = -0.005 * ( pos. y - gesture. start_mouse_pos . y ) as f32 ;
238
+ let new_value = ( gesture. start_value + delta) . clamp ( 0.0 , 1.0 ) ;
239
+ self . host . set_param ( 0 , new_value as f64 ) ;
240
+ self . params . borrow_mut ( ) . gain = new_value;
241
+ } else {
242
+ self . update_cursor ( cx. window ( ) ) ;
243
+ }
244
+ }
245
+ Event :: MouseDown ( button) => {
246
+ if button == MouseButton :: Left {
247
+ let pos = self . mouse_pos ;
248
+ if pos. x >= 96.0 && pos. x < 160.0 && pos. y >= 96.0 && pos. y < 160.0 {
249
+ cx. window ( ) . set_cursor ( Cursor :: SizeNs ) ;
250
+ self . host . begin_gesture ( 0 ) ;
251
+ let value = self . params . borrow ( ) . gain ;
252
+ self . host . set_param ( 0 , value as f64 ) ;
253
+ self . params . borrow_mut ( ) . gain = value;
254
+ self . gesture = Some ( Gesture {
255
+ start_mouse_pos : pos,
256
+ start_value : value,
257
+ } ) ;
258
+ return Response :: Capture ;
259
+ }
260
+ }
261
+ }
262
+ Event :: MouseUp ( button) => {
263
+ if button == MouseButton :: Left {
264
+ if self . gesture . is_some ( ) {
265
+ self . host . end_gesture ( 0 ) ;
266
+ self . gesture = None ;
267
+ self . update_cursor ( cx. window ( ) ) ;
268
+ return Response :: Capture ;
269
+ }
270
+ }
271
+ }
272
+ _ => { }
273
+ }
274
+
275
+ Response :: Ignore
276
+ }
277
+ }
278
+
279
+ pub struct GainView {
280
+ #[ allow( unused) ]
281
+ app : App ,
282
+ window : Window ,
283
+ params : Rc < RefCell < GainParams > > ,
284
+ }
285
+
286
+ impl GainView {
287
+ fn open ( host : ViewHost , parent : & ParentWindow , params : & GainParams ) -> Result < GainView > {
288
+ let app = AppOptions :: new ( ) . mode ( AppMode :: Guest ) . build ( ) ?;
289
+
290
+ let mut options = WindowOptions :: new ( ) ;
291
+ options. size ( reflector:: platform:: Size :: new ( 256.0 , 256.0 ) ) ;
292
+
293
+ let raw_parent = match parent. as_raw ( ) {
294
+ RawParent :: Win32 ( window) => RawWindow :: Win32 ( window) ,
295
+ RawParent :: Cocoa ( view) => RawWindow :: Cocoa ( view) ,
296
+ RawParent :: X11 ( window) => RawWindow :: X11 ( window) ,
297
+ } ;
298
+ unsafe { options. raw_parent ( raw_parent) } ;
299
+
300
+ let params = Rc :: new ( RefCell :: new ( params. clone ( ) ) ) ;
301
+ let mut state = ViewState :: new ( host, Rc :: clone ( & params) ) ;
302
+ let window = options. open ( app. handle ( ) , move |cx, event| state. handle_event ( cx, event) ) ?;
303
+
304
+ window. show ( ) ;
305
+
306
+ Ok ( GainView {
307
+ app,
308
+ window,
309
+ params,
310
+ } )
311
+ }
312
+ }
313
+
314
+ impl View for GainView {
315
+ fn size ( & self ) -> Size {
316
+ let size = self . window . size ( ) ;
317
+
318
+ Size {
319
+ width : size. width ,
320
+ height : size. height ,
321
+ }
322
+ }
323
+
324
+ fn param_changed ( & mut self , id : ParamId , value : ParamValue ) {
325
+ self . params . borrow_mut ( ) . set_param ( id, value) ;
326
+ }
327
+ }
0 commit comments