Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | daniel-mar | 1 | unit DXFFBEdit; |
2 | |||
3 | interface |
||
4 | |||
5 | uses |
||
6 | Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, |
||
7 | StdCtrls, Spin, DXInput, TypInfo, ExtCtrls, Menus, ComCtrls; |
||
8 | |||
9 | type |
||
10 | TDelphiXFFEditForm = class(TForm) |
||
11 | ListGroupBox: TGroupBox; |
||
12 | AddButton: TButton; |
||
13 | DelButton: TButton; |
||
14 | EditGroupBox: TGroupBox; |
||
15 | EffectTypeBox: TComboBox; |
||
16 | EffectTypeLabel: TLabel; |
||
17 | ConstantLabel: TLabel; |
||
18 | ConstantYEdit: TSpinEdit; |
||
19 | ConstantXEdit: TSpinEdit; |
||
20 | ConstantXLabel: TLabel; |
||
21 | ConstantYLabel: TLabel; |
||
22 | FadeTimeLabel: TLabel; |
||
23 | FadeTimeEdit: TSpinEdit; |
||
24 | PeriodLabel: TLabel; |
||
25 | PeriodEdit: TSpinEdit; |
||
26 | PeriodLabel2: TLabel; |
||
27 | PowerLabel: TLabel; |
||
28 | TimeLabel: TLabel; |
||
29 | TimeEdit: TSpinEdit; |
||
30 | TimeLabel2: TLabel; |
||
31 | AttackTimeEditLabel: TLabel; |
||
32 | AttackTimeEdit: TSpinEdit; |
||
33 | RunButton: TButton; |
||
34 | RunGroupButton: TButton; |
||
35 | OKButton: TButton; |
||
36 | CancelButton: TButton; |
||
37 | DXInput: TDXInput; |
||
38 | NameEditLabel: TLabel; |
||
39 | NameEdit: TEdit; |
||
40 | Bevel1: TBevel; |
||
41 | StopButton: TButton; |
||
42 | PopupMenu: TPopupMenu; |
||
43 | A1: TMenuItem; |
||
44 | DeleteEffectItem: TMenuItem; |
||
45 | PowerEdit: TSpinEdit; |
||
46 | Timer: TTimer; |
||
47 | Bevel2: TBevel; |
||
48 | N1: TMenuItem; |
||
49 | N2: TMenuItem; |
||
50 | SaveToFileItem: TMenuItem; |
||
51 | AddFromFileButton: TButton; |
||
52 | OpenDialog: TOpenDialog; |
||
53 | SaveDialog: TSaveDialog; |
||
54 | EffectView: TTreeView; |
||
55 | ConditionLabel: TLabel; |
||
56 | ConditionXLabel: TLabel; |
||
57 | ConditionXEdit: TSpinEdit; |
||
58 | ConditionYLabel: TLabel; |
||
59 | ConditionYEdit: TSpinEdit; |
||
60 | Label1: TLabel; |
||
61 | Label2: TLabel; |
||
62 | AttackLevelEdit: TSpinEdit; |
||
63 | FadeLevelEdit: TSpinEdit; |
||
64 | Label3: TLabel; |
||
65 | Label4: TLabel; |
||
66 | Label5: TLabel; |
||
67 | Label6: TLabel; |
||
68 | procedure OKButtonClick(Sender: TObject); |
||
69 | procedure CancelButtonClick(Sender: TObject); |
||
70 | procedure EffectViewChange(Sender: TObject; Node: TTreeNode); |
||
71 | procedure FormShow(Sender: TObject); |
||
72 | procedure FormCreate(Sender: TObject); |
||
73 | procedure AddButtonClick(Sender: TObject); |
||
74 | procedure DelButtonClick(Sender: TObject); |
||
75 | procedure RunButtonClick(Sender: TObject); |
||
76 | procedure RunGroupButtonClick(Sender: TObject); |
||
77 | procedure StopButtonClick(Sender: TObject); |
||
78 | procedure ChangeEvent(Sender: TObject); |
||
79 | procedure TimerTimer(Sender: TObject); |
||
80 | procedure NameEditChange(Sender: TObject); |
||
81 | procedure EffectViewDragDrop(Sender, Source: TObject; X, Y: Integer); |
||
82 | procedure EffectViewDragOver(Sender, Source: TObject; X, Y: Integer; |
||
83 | State: TDragState; var Accept: Boolean); |
||
84 | procedure AddFromFileButtonClick(Sender: TObject); |
||
85 | procedure SaveToFileItemClick(Sender: TObject); |
||
86 | procedure EffectViewEdited(Sender: TObject; Node: TTreeNode; |
||
87 | var S: String); |
||
88 | procedure EffectTypeBoxChange(Sender: TObject); |
||
89 | private |
||
90 | FChanged: Boolean; |
||
91 | FSelectEffect: TForceFeedbackEffect; |
||
92 | FOldStates: TDXInputStates; |
||
93 | FUpdating: Boolean; |
||
94 | function AddTree(Parent: TTreeNode; Effect: TForceFeedbackEffect): TTreeNode; |
||
95 | procedure Save; |
||
96 | public |
||
97 | Effects: TForceFeedbackEffects; |
||
98 | end; |
||
99 | |||
100 | var |
||
101 | DelphiXFFEditForm: TDelphiXFFEditForm; |
||
102 | |||
103 | implementation |
||
104 | |||
105 | uses DXConsts; |
||
106 | |||
107 | {$R *.DFM} |
||
108 | |||
109 | procedure TDelphiXFFEditForm.FormCreate(Sender: TObject); |
||
110 | var |
||
111 | e: TForceFeedbackEffectType; |
||
112 | s: string; |
||
113 | begin |
||
114 | for e:=Low(e) to High(e) do |
||
115 | begin |
||
116 | if e=etNone then |
||
117 | s := SNone |
||
118 | else |
||
119 | s := GetEnumName(TypeInfo(TForceFeedbackEffectType), Integer(e)); |
||
120 | |||
121 | EffectTypeBox.Items.Add(s); |
||
122 | end; |
||
123 | end; |
||
124 | |||
125 | function TDelphiXFFEditForm.AddTree(Parent: TTreeNode; Effect: TForceFeedbackEffect): TTreeNode; |
||
126 | var |
||
127 | i: Integer; |
||
128 | begin |
||
129 | Result := EffectView.Items.AddChildObject(Parent, Effect.Name, Effect); |
||
130 | for i:=0 to Effect.Count-1 do |
||
131 | AddTree(Result, Effect.Effects[i]); |
||
132 | end; |
||
133 | |||
134 | procedure TDelphiXFFEditForm.Save; |
||
135 | begin |
||
136 | if FChanged then EffectViewChange(nil, nil); |
||
137 | end; |
||
138 | |||
139 | procedure TDelphiXFFEditForm.FormShow(Sender: TObject); |
||
140 | begin |
||
141 | Caption := Format(SFFBEffectEditor, [Effects.Input.ClassName]); |
||
142 | |||
143 | Effects.Input.Enabled := True; |
||
144 | |||
145 | EffectView.Selected := AddTree(nil, Effects); |
||
146 | if EffectView.Selected<>nil then |
||
147 | EffectView.Selected.Expanded := True; |
||
148 | end; |
||
149 | |||
150 | procedure TDelphiXFFEditForm.OKButtonClick(Sender: TObject); |
||
151 | begin |
||
152 | Save; |
||
153 | Tag := 1; |
||
154 | Close; |
||
155 | end; |
||
156 | |||
157 | procedure TDelphiXFFEditForm.CancelButtonClick(Sender: TObject); |
||
158 | begin |
||
159 | Close; |
||
160 | end; |
||
161 | |||
162 | procedure SetControlEnabled(Control: TControl; Value: Boolean); |
||
163 | var |
||
164 | NewColor: TColor; |
||
165 | begin |
||
166 | Control.Enabled := Value; |
||
167 | |||
168 | if Value then NewColor := clWindow else NewColor := clBtnFace; |
||
169 | |||
170 | if Control is TComboBox then TComboBox(Control).Color := NewColor; |
||
171 | if Control is TSpinEdit then TSpinEdit(Control).Color := NewColor; |
||
172 | if Control is TEdit then TEdit(Control).Color := NewColor; |
||
173 | end; |
||
174 | |||
175 | procedure TDelphiXFFEditForm.EffectViewChange(Sender: TObject; Node: TTreeNode); |
||
176 | var |
||
177 | i: Integer; |
||
178 | Control: TControl; |
||
179 | begin |
||
180 | StopButtonClick(nil); |
||
181 | |||
182 | FUpdating := True; |
||
183 | try |
||
184 | if FSelectEffect<>nil then |
||
185 | begin |
||
186 | if FChanged then |
||
187 | begin |
||
188 | with FSelectEffect do |
||
189 | begin |
||
190 | Name := NameEdit.Text; |
||
191 | |||
192 | EffectType := etNone; |
||
193 | |||
194 | Power := PowerEdit.Value; |
||
195 | Time := TimeEdit.Value; |
||
196 | AttackTime := AttackTimeEdit.Value; |
||
197 | AttackLevel := AttackLevelEdit.Value; |
||
198 | FadeTime := FadeTimeEdit.Value; |
||
199 | FadeLevel := FadeLevelEdit.Value; |
||
200 | Constant := Point(ConstantXEdit.Value, ConstantYEdit.Value); |
||
201 | Period := PeriodEdit.Value; |
||
202 | Condition := Point(ConditionXEdit.Value, ConditionYEdit.Value); |
||
203 | |||
204 | EffectType := TForceFeedbackEffectType(EffectTypeBox.ItemIndex); |
||
205 | end; |
||
206 | end; |
||
207 | end; |
||
208 | |||
209 | FSelectEffect := nil; |
||
210 | if (EffectView.Selected<>nil) and (EffectView.Selected.Data<>nil) then |
||
211 | FSelectEffect := EffectView.Selected.Data; |
||
212 | |||
213 | DelButton.Enabled := (FSelectEffect<>nil) and (FSelectEffect.Parent<>nil); |
||
214 | DeleteEffectItem.Enabled := DelButton.Enabled; |
||
215 | SaveToFileItem.Enabled := FSelectEffect<>nil; |
||
216 | |||
217 | if FSelectEffect<>nil then |
||
218 | begin |
||
219 | for i:=0 to ComponentCount-1 do |
||
220 | if (Components[i] is TControl) then |
||
221 | begin |
||
222 | Control := TControl(Components[i]); |
||
223 | if Control.Parent=EditGroupBox then |
||
224 | SetControlEnabled(Control, True); |
||
225 | end; |
||
226 | end else |
||
227 | begin |
||
228 | for i:=0 to ComponentCount-1 do |
||
229 | if (Components[i] is TControl) then |
||
230 | begin |
||
231 | Control := TControl(Components[i]); |
||
232 | if Control.Parent=EditGroupBox then |
||
233 | begin |
||
234 | SetControlEnabled(Control, False); |
||
235 | if Control is TEdit then |
||
236 | TEdit(Control).Text := '' |
||
237 | else if Control is TSpinEdit then |
||
238 | TSpinEdit(Control).Value := 0 |
||
239 | else if Control is TComboBox then |
||
240 | TComboBox(Control).ItemIndex := 0 |
||
241 | else if Control is TCheckBox then |
||
242 | TCheckBox(Control).Checked := False; |
||
243 | end; |
||
244 | end; |
||
245 | end; |
||
246 | |||
247 | if FSelectEffect<>nil then |
||
248 | begin |
||
249 | with FSelectEffect do |
||
250 | begin |
||
251 | NameEdit.Text := Name; |
||
252 | |||
253 | EffectTypeBox.ItemIndex := Integer(EffectType); |
||
254 | |||
255 | PowerEdit.Value := Power; |
||
256 | TimeEdit.Value := Time; |
||
257 | |||
258 | AttackTimeEdit.Value := AttackTime; |
||
259 | AttackLevelEdit.Value := AttackLevel; |
||
260 | |||
261 | FadeTimeEdit.Value := FadeTime; |
||
262 | FadeLevelEdit.Value := FadeLevel; |
||
263 | |||
264 | ConstantXEdit.Value := Constant.X; |
||
265 | ConstantYEdit.Value := Constant.Y; |
||
266 | |||
267 | PeriodEdit.Value := Period; |
||
268 | |||
269 | ConditionXEdit.Value := Condition.X; |
||
270 | ConditionYEdit.Value := Condition.Y; |
||
271 | end; |
||
272 | |||
273 | EffectTypeBoxChange(nil); |
||
274 | end; |
||
275 | finally |
||
276 | FUpdating := False; |
||
277 | end; |
||
278 | |||
279 | FChanged := False; |
||
280 | FOldStates := []; |
||
281 | end; |
||
282 | |||
283 | procedure TDelphiXFFEditForm.AddButtonClick(Sender: TObject); |
||
284 | var |
||
285 | Effect: TForceFeedbackEffect; |
||
286 | OwnerEffect: TForceFeedbackEffect; |
||
287 | i, j: Integer; |
||
288 | Flag: Boolean; |
||
289 | begin |
||
290 | if FSelectEffect<>nil then |
||
291 | OwnerEffect := FSelectEffect |
||
292 | else |
||
293 | OwnerEffect := Effects; |
||
294 | |||
295 | { Unique name making } |
||
296 | j := 0; |
||
297 | repeat |
||
298 | Flag := True; |
||
299 | Inc(j); |
||
300 | for i:=0 to OwnerEffect.Count-1 do |
||
301 | if AnsiCompareText(OwnerEffect[i].Name, Format('Effect%d', [j]))=0 then |
||
302 | begin |
||
303 | Flag := False; |
||
304 | Break; |
||
305 | end; |
||
306 | until Flag; |
||
307 | |||
308 | { Effect making } |
||
309 | Effect := TForceFeedbackEffect.Create(OwnerEffect); |
||
310 | Effect.Name := Format('Effect%d', [j]); |
||
311 | |||
312 | EffectView.Selected := AddTree(EffectView.Selected, Effect); |
||
313 | end; |
||
314 | |||
315 | procedure TDelphiXFFEditForm.DelButtonClick(Sender: TObject); |
||
316 | begin |
||
317 | FSelectEffect.Free; |
||
318 | FSelectEffect := nil; |
||
319 | |||
320 | EffectView.Selected.Delete; |
||
321 | end; |
||
322 | |||
323 | procedure TDelphiXFFEditForm.RunButtonClick(Sender: TObject); |
||
324 | begin |
||
325 | if not RunButton.Enabled then Exit; |
||
326 | |||
327 | Save; |
||
328 | |||
329 | if not DXInput.UseDirectInput then |
||
330 | begin |
||
331 | Screen.Cursor := crHourGlass; |
||
332 | try |
||
333 | DXInput.UseDirectInput := True; |
||
334 | finally |
||
335 | Screen.Cursor := crDefault; |
||
336 | end; |
||
337 | end; |
||
338 | |||
339 | FSelectEffect.Start; |
||
340 | end; |
||
341 | |||
342 | procedure TDelphiXFFEditForm.RunGroupButtonClick(Sender: TObject); |
||
343 | var |
||
344 | Effect: TForceFeedbackEffect; |
||
345 | begin |
||
346 | if not RunGroupButton.Enabled then Exit; |
||
347 | |||
348 | Save; |
||
349 | |||
350 | if not DXInput.UseDirectInput then |
||
351 | begin |
||
352 | Screen.Cursor := crHourGlass; |
||
353 | try |
||
354 | DXInput.UseDirectInput := True; |
||
355 | finally |
||
356 | Screen.Cursor := crDefault; |
||
357 | end; |
||
358 | end; |
||
359 | |||
360 | Effect := FSelectEffect; |
||
361 | while (Effect.Parent<>nil) and (Effect.Parent.Parent<>nil) do |
||
362 | Effect := Effect.Parent; |
||
363 | |||
364 | Effect.Start; |
||
365 | end; |
||
366 | |||
367 | procedure TDelphiXFFEditForm.StopButtonClick(Sender: TObject); |
||
368 | begin |
||
369 | Effects.Stop; |
||
370 | Effects.UnLoad(True); |
||
371 | end; |
||
372 | |||
373 | procedure TDelphiXFFEditForm.ChangeEvent(Sender: TObject); |
||
374 | begin |
||
375 | if not FUpdating then FChanged := True; |
||
376 | end; |
||
377 | |||
378 | procedure TDelphiXFFEditForm.TimerTimer(Sender: TObject); |
||
379 | var |
||
380 | s: TDXInputStates; |
||
381 | begin |
||
382 | if not (Effects.Input is TKeyboard) then |
||
383 | begin |
||
384 | Effects.Input.Update; |
||
385 | s := Effects.Input.States; |
||
386 | |||
387 | if (isButton1 in s) and (not (isButton1 in FOldStates)) then |
||
388 | RunGroupButtonClick(nil) |
||
389 | else if (isButton2 in s) and (not (isButton2 in FOldStates)) then |
||
390 | RunButtonClick(nil) |
||
391 | else if (s*[isButton1, isButton2]=[]) and (FOldStates*[isButton1, isButton2]<>[]) then |
||
392 | StopButtonClick(nil); |
||
393 | |||
394 | FOldStates := s; |
||
395 | end; |
||
396 | end; |
||
397 | |||
398 | procedure TDelphiXFFEditForm.NameEditChange(Sender: TObject); |
||
399 | begin |
||
400 | if not FUpdating then |
||
401 | if EffectView.Selected<>nil then |
||
402 | begin |
||
403 | EffectView.Selected.Text := NameEdit.Text; |
||
404 | FSelectEffect.Name := NameEdit.Text; |
||
405 | end; |
||
406 | end; |
||
407 | |||
408 | procedure TDelphiXFFEditForm.EffectViewDragOver(Sender, Source: TObject; X, |
||
409 | Y: Integer; State: TDragState; var Accept: Boolean); |
||
410 | var |
||
411 | Node: TTreeNode; |
||
412 | begin |
||
413 | Accept := False; |
||
414 | |||
415 | Node := EffectView.GetNodeAt(X, Y); |
||
416 | if Node=nil then Exit; |
||
417 | |||
418 | if Node=EffectView.Items.GetFirstNode then Exit; |
||
419 | |||
420 | while Node<>nil do |
||
421 | begin |
||
422 | if Node=EffectView.Selected then |
||
423 | Exit; |
||
424 | Node := Node.Parent; |
||
425 | end; |
||
426 | |||
427 | Accept := True; |
||
428 | end; |
||
429 | |||
430 | procedure TDelphiXFFEditForm.EffectViewDragDrop(Sender, Source: TObject; X, |
||
431 | Y: Integer); |
||
432 | var |
||
433 | Node, Node2: TTreeNode; |
||
434 | Effect: TForceFeedbackEffect; |
||
435 | begin |
||
436 | Save; |
||
437 | |||
438 | Node := EffectView.GetNodeAt(X, Y); |
||
439 | |||
440 | if Node<>nil then |
||
441 | begin |
||
442 | Effect := TObject(EffectView.Selected.Data) as TForceFeedbackEffect; |
||
443 | |||
444 | Node2 := EffectView.Selected; |
||
445 | |||
446 | if X>Node.DisplayRect(True).Right+10 then |
||
447 | begin |
||
448 | { Effect is moved to the child. } |
||
449 | Effect.Parent := TObject(Node.Data) as TForceFeedbackEffect; |
||
450 | EffectView.Selected.MoveTo(Node, naAddChild); |
||
451 | Effect.Index := EffectView.Selected.Index; |
||
452 | end else |
||
453 | begin |
||
454 | { Effect is moved to the brother. } |
||
455 | Effect.Parent := (TObject(Node.Data) as TForceFeedbackEffect).Parent; |
||
456 | EffectView.Selected.MoveTo(Node, naInsert); |
||
457 | Effect.Index := EffectView.Selected.Index; |
||
458 | end; |
||
459 | |||
460 | EffectView.Selected := Node2; |
||
461 | |||
462 | EffectView.Invalidate; |
||
463 | end; |
||
464 | end; |
||
465 | |||
466 | procedure TDelphiXFFEditForm.AddFromFileButtonClick(Sender: TObject); |
||
467 | var |
||
468 | i: Integer; |
||
469 | Effect: TForceFeedbackEffect; |
||
470 | begin |
||
471 | if not OpenDialog.Execute then Exit; |
||
472 | |||
473 | Save; |
||
474 | |||
475 | for i:=0 to OpenDialog.Files.Count-1 do |
||
476 | begin |
||
477 | Effect := TForceFeedbackEffect.Create(Effects); |
||
478 | try |
||
479 | Effect.LoadFromFile(OpenDialog.Files[i]); |
||
480 | except |
||
481 | Effect.Free; |
||
482 | raise; |
||
483 | end; |
||
484 | |||
485 | EffectView.Selected := AddTree(EffectView.Items.GetFirstNode, Effect); |
||
486 | end; |
||
487 | end; |
||
488 | |||
489 | procedure TDelphiXFFEditForm.SaveToFileItemClick(Sender: TObject); |
||
490 | begin |
||
491 | SaveDialog.FileName := FSelectEffect.Name+'.ffe'; |
||
492 | |||
493 | if not SaveDialog.Execute then Exit; |
||
494 | |||
495 | Save; |
||
496 | |||
497 | FSelectEffect.SaveToFile(SaveDialog.FileName); |
||
498 | end; |
||
499 | |||
500 | procedure TDelphiXFFEditForm.EffectViewEdited(Sender: TObject; |
||
501 | Node: TTreeNode; var S: String); |
||
502 | begin |
||
503 | NameEdit.Text := s; |
||
504 | end; |
||
505 | |||
506 | procedure TDelphiXFFEditForm.EffectTypeBoxChange(Sender: TObject); |
||
507 | var |
||
508 | EffectType: TForceFeedbackEffectType; |
||
509 | begin |
||
510 | ChangeEvent(Sender); |
||
511 | |||
512 | EffectType := TForceFeedbackEffectType(EffectTypeBox.ItemIndex); |
||
513 | |||
514 | SetControlEnabled(PowerEdit, EffectType<>etNone); |
||
515 | SetControlEnabled(TimeEdit, EffectType<>etNone); |
||
516 | |||
517 | SetControlEnabled(AttackTimeEdit, EffectType<>etNone); |
||
518 | SetControlEnabled(AttackLevelEdit, EffectType<>etNone); |
||
519 | |||
520 | SetControlEnabled(FadeTimeEdit, EffectType<>etNone); |
||
521 | SetControlEnabled(FadeLevelEdit, EffectType<>etNone); |
||
522 | |||
523 | SetControlEnabled(ConstantXEdit, EffectType in [etConstantForce, etPeriodic, etCondition]); |
||
524 | SetControlEnabled(ConstantYEdit, EffectType in [etConstantForce, etPeriodic, etCondition]); |
||
525 | |||
526 | SetControlEnabled(PeriodEdit, EffectType in [etPeriodic]); |
||
527 | |||
528 | SetControlEnabled(ConditionXEdit, EffectType in [etCondition]); |
||
529 | SetControlEnabled(ConditionYEdit, EffectType in [etCondition]); |
||
530 | end; |
||
531 | |||
532 | end. |