Subversion Repositories plumbers

Rev

Rev 10 | Rev 12 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 daniel-mar 1
unit Unit1;
2
 
8 daniel-mar 3
// TODO: the "folder open" icons look like you can CHOOSE a file, not open it!
4
//       - change the icon to something else
5
//       - add open-dialogs for choosing the bmp and wav files
10 daniel-mar 6
// TODO: Give controls better names
11 daniel-mar 7
// TODO: When loading the file, check if dependencies are broken and output a warning
8
// Idea: About the hotspot / action markings:
9
//       - anti moiree?
10
//       - allow user to draw a rectangle with drag'n'drop instead of left and right mouse button.
11
//         also, automatically determine the left/top and right/bottom border, so the user can draw the rectange in every direction
8 daniel-mar 12
// Idea: unused liste auch bei decision page anzeigen
11 daniel-mar 13
// Idea: Function to re-order stuff?
2 daniel-mar 14
 
15
interface
16
 
17
uses
18
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
10 daniel-mar 19
  Dialogs, StdCtrls, Spin, Grids, GameBinStruct, ComCtrls, ExtCtrls, MPlayer,
20
  Menus;
2 daniel-mar 21
 
22
const
10 daniel-mar 23
  CUR_VER = '2017-10-04';
2 daniel-mar 24
 
25
type
26
  TForm1 = class(TForm)
27
    ListBox1: TListBox;
28
    Button1: TButton;
29
    Button2: TButton;
30
    Button3: TButton;
31
    Button4: TButton;
32
    Button5: TButton;
33
    Button10: TButton;
34
    PageControl2: TPageControl;
35
    TabSheet4: TTabSheet;
36
    Label1: TLabel;
37
    Label2: TLabel;
38
    SpinEdit1: TSpinEdit;
39
    Edit1: TEdit;
40
    Button6: TButton;
41
    Button7: TButton;
42
    Button8: TButton;
43
    Button9: TButton;
44
    ListBox2: TListBox;
45
    TabSheet5: TTabSheet;
46
    Label3: TLabel;
47
    Image1: TImage;
48
    Label10: TLabel;
49
    Label11: TLabel;
50
    Edit2: TEdit;
51
    PageControl1: TPageControl;
52
    TabSheet1: TTabSheet;
53
    Label5: TLabel;
54
    Label4: TLabel;
55
    Label6: TLabel;
56
    SpinEdit6: TSpinEdit;
57
    SpinEdit2: TSpinEdit;
58
    SpinEdit3: TSpinEdit;
59
    SpinEdit4: TSpinEdit;
60
    SpinEdit5: TSpinEdit;
61
    ComboBox1: TComboBox;
62
    TabSheet2: TTabSheet;
63
    Label13: TLabel;
64
    Label14: TLabel;
65
    Label15: TLabel;
66
    ComboBox2: TComboBox;
67
    SpinEdit17: TSpinEdit;
68
    SpinEdit18: TSpinEdit;
69
    SpinEdit19: TSpinEdit;
70
    SpinEdit20: TSpinEdit;
71
    SpinEdit21: TSpinEdit;
72
    TabSheet3: TTabSheet;
73
    Label7: TLabel;
74
    Label8: TLabel;
75
    Label9: TLabel;
76
    ComboBox3: TComboBox;
77
    SpinEdit7: TSpinEdit;
78
    SpinEdit8: TSpinEdit;
79
    SpinEdit9: TSpinEdit;
80
    SpinEdit10: TSpinEdit;
81
    SpinEdit11: TSpinEdit;
82
    SpinEdit12: TSpinEdit;
83
    Image2: TImage;
84
    Edit3: TEdit;
85
    SpinEdit13: TSpinEdit;
86
    Label12: TLabel;
87
    Label16: TLabel;
88
    Button13: TButton;
89
    Button14: TButton;
90
    MediaPlayer1: TMediaPlayer;
91
    Timer1: TTimer;
92
    GroupBox2: TGroupBox;
93
    Button15: TButton;
94
    Button17: TButton;
95
    Button16: TButton;
96
    Label18: TLabel;
97
    Label17: TLabel;
98
    ListBox3: TListBox;
99
    Label19: TLabel;
100
    Label24: TLabel;
101
    Label25: TLabel;
102
    Label26: TLabel;
103
    Label27: TLabel;
104
    Label28: TLabel;
105
    Label29: TLabel;
106
    Button11: TButton;
107
    Button12: TButton;
108
    Button18: TButton;
109
    MainMenu1: TMainMenu;
110
    File1: TMenuItem;
111
    Close1: TMenuItem;
112
    Newfile1: TMenuItem;
113
    Savetogamebin1: TMenuItem;
114
    Saveandtest1: TMenuItem;
115
    N1: TMenuItem;
116
    N2: TMenuItem;
117
    Help1: TMenuItem;
118
    About1: TMenuItem;
119
    PopupMenu1: TPopupMenu;
120
    Addtoscene1: TMenuItem;
6 daniel-mar 121
    Panel1: TPanel;
122
    Panel2: TPanel;
8 daniel-mar 123
    Panel3: TPanel;
124
    Image3: TImage;
10 daniel-mar 125
    Button19: TButton;
126
    PageControl3: TPageControl;
127
    TabSheet6: TTabSheet;
128
    TabSheet7: TTabSheet;
129
    Label20: TLabel;
130
    Label21: TLabel;
131
    Label22: TLabel;
132
    Label23: TLabel;
133
    Label34: TLabel;
134
    Label35: TLabel;
135
    Label32: TLabel;
136
    Label33: TLabel;
137
    Label30: TLabel;
138
    Label31: TLabel;
139
    Label36: TLabel;
140
    Label37: TLabel;
11 daniel-mar 141
    CheckBox1: TCheckBox;
142
    TabSheet8: TTabSheet;
143
    Button20: TButton;
2 daniel-mar 144
    procedure ListBox1Click(Sender: TObject);
145
    procedure Edit1Change(Sender: TObject);
146
    procedure Edit2Change(Sender: TObject);
147
    procedure SpinEdit1Change(Sender: TObject);
148
    procedure Button3Click(Sender: TObject);
149
    procedure FormShow(Sender: TObject);
150
    procedure SpinEdit12Change(Sender: TObject);
151
    procedure ActionTargetChange(Sender: TObject);
152
    procedure ActionSpinEditsChange(Sender: TObject);
153
    procedure Button1Click(Sender: TObject);
154
    procedure Button10Click(Sender: TObject);
155
    procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
156
      Y: Integer);
157
    procedure ListBox2Click(Sender: TObject);
158
    procedure SpinEdit13Change(Sender: TObject);
159
    procedure Edit3Change(Sender: TObject);
160
    procedure FormCreate(Sender: TObject);
161
    procedure Button13Click(Sender: TObject);
162
    procedure Button14Click(Sender: TObject);
163
    procedure Button2Click(Sender: TObject);
164
    procedure Timer1Timer(Sender: TObject);
165
    procedure Button17Click(Sender: TObject);
166
    procedure Button15Click(Sender: TObject);
167
    procedure Button16Click(Sender: TObject);
168
    procedure ListBox1DblClick(Sender: TObject);
169
    procedure ListBox2DblClick(Sender: TObject);
170
    procedure Button4Click(Sender: TObject);
171
    procedure Button5Click(Sender: TObject);
172
    procedure Button6Click(Sender: TObject);
173
    procedure Button7Click(Sender: TObject);
174
    procedure Button8Click(Sender: TObject);
175
    procedure Button9Click(Sender: TObject);
176
    procedure Image1MouseLeave(Sender: TObject);
177
    procedure ListBox3DblClick(Sender: TObject);
178
    procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
179
      Shift: TShiftState; X, Y: Integer);
180
    procedure Button11Click(Sender: TObject);
181
    procedure Button12Click(Sender: TObject);
182
    procedure Button18Click(Sender: TObject);
183
    procedure Image1MouseEnter(Sender: TObject);
184
    procedure About1Click(Sender: TObject);
185
    procedure Close1Click(Sender: TObject);
186
    procedure Addtoscene1Click(Sender: TObject);
187
    procedure ListBox3MouseDown(Sender: TObject; Button: TMouseButton;
188
      Shift: TShiftState; X, Y: Integer);
8 daniel-mar 189
    procedure ListBox3Click(Sender: TObject);
10 daniel-mar 190
    procedure Button19Click(Sender: TObject);
191
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
11 daniel-mar 192
    procedure Button20Click(Sender: TObject);
193
    procedure CheckBox1Click(Sender: TObject);
2 daniel-mar 194
  private
195
    Game: TGameBinFile;
10 daniel-mar 196
    GameBak: TGameBinFile;
2 daniel-mar 197
    PlayStart: Cardinal;
198
    MediaplayerOpened: boolean;
199
    StopPlayRequest: boolean;
200
    FirstTickCount: Cardinal;
8 daniel-mar 201
    procedure ShowSceneBmp;
2 daniel-mar 202
    function CurScene: PSceneDef;
203
    procedure LoadScene;
204
    procedure Load;
205
    procedure Save;
206
    procedure ReloadActionSceneLists;
207
    function FindSceneIndex(sceneID: integer): integer;
208
    function GetGreatestSceneID: integer;
209
    function SearchSceneIDGapFromTop: integer;
210
    procedure RedrawDecisionBitmap;
211
    function CurPicture: PPictureDef;
212
    function CurPictureTimepos: Cardinal;
213
    procedure New;
214
    procedure NewScene;
215
    procedure SetupGUIAfterLoad;
216
    procedure RecalcSlideshowLength;
217
    procedure RecalcSoundtrackLength;
218
    procedure RecalcUnusedFiles;
10 daniel-mar 219
    procedure RecalcStats;
2 daniel-mar 220
    procedure HandlePossibleEmptySceneList;
221
    procedure DisableEnableSceneControls(enable: boolean);
222
    procedure DisableEnablePictureControls(enable: boolean);
223
    procedure DisableEnableFileControls(enable: boolean);
6 daniel-mar 224
    class procedure AspectRatio(image: TImage; panel: TControl);
2 daniel-mar 225
  end;
226
 
227
var
228
  Form1: TForm1;
229
 
230
implementation
231
 
232
{$R *.dfm}
233
 
234
uses
235
  Math, MMSystem, ShellAPI;
236
 
10 daniel-mar 237
const
238
  DEFAULT_DURATION = 0;
239
  DEFAULT_FILENAME = 'DUMMY.BMP';
240
 
2 daniel-mar 241
function GetSceneIDFromName(sceneName: string): Integer;
242
var
243
  sSceneID: string;
244
begin
245
  if Copy(sceneName, 1, 2) <> 'SC' then raise Exception.Create('Scene name invalid');
246
  sSceneID := Copy(sceneName, 3, 2);
247
  if not TryStrToInt(sSceneID, result) then raise Exception.Create('Scene name invalid');
248
end;
249
 
10 daniel-mar 250
procedure SelectFilenameBase(Edit: TEdit);
251
begin
252
  if Edit.CanFocus then
253
  begin
254
    Edit.SetFocus;
255
    Edit.SelStart := 0;
256
    Edit.SelLength := Pos('.', Edit.Text)-1;
257
  end;
258
end;
259
 
2 daniel-mar 260
function _DecisecondToTime(ds: integer): string;
261
begin
262
  result := FormatDatetime('hh:nn:ss', ds / 10 / (24*60*60))+','+IntToStr(ds mod 10);
263
end;
264
 
265
{ TForm1 }
266
 
267
function TForm1.GetGreatestSceneID: integer;
268
var
269
  i: integer;
270
begin
271
  result := -1;
272
  for i := 0 to ListBox1.Items.Count - 1 do
273
  begin
274
    result := Max(result, GetSceneIDFromName(ListBox1.Items.Strings[i]));
275
  end;
276
end;
277
 
278
procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
279
  Shift: TShiftState; X, Y: Integer);
280
var
281
  sE1, sE2, sE3, sE4: TSpinEdit;
282
 
283
  procedure _Go;
284
  begin
285
    if Button = mbLeft then
286
    begin
287
      sE1.Value := Round(Image1.Picture.Width*(X/Image1.Width));
288
      sE2.Value := Round(Image1.Picture.Height*(Y/Image1.Height));
289
    end
290
    else if Button = mbRight then
291
    begin
292
      sE3.Value := Round(Image1.Picture.Width*(X/Image1.Width));
293
      sE4.Value := Round(Image1.Picture.Height*(Y/Image1.Height));
294
    end;
295
  end;
296
 
297
begin
298
  if PageControl1.ActivePage = TabSheet1 then
299
  begin
300
    sE1 := SpinEdit3;
301
    sE2 := SpinEdit2;
302
    sE3 := SpinEdit4;
303
    sE4 := SpinEdit5;
304
    _Go;
305
  end
306
  else if PageControl1.ActivePage = TabSheet2 then
307
  begin
308
    sE1 := SpinEdit17;
309
    sE2 := SpinEdit18;
310
    sE3 := SpinEdit19;
311
    sE4 := SpinEdit20;
312
    _Go;
313
  end
314
  else if PageControl1.ActivePage = TabSheet3 then
315
  begin
316
    sE1 := SpinEdit7;
317
    sE2 := SpinEdit8;
318
    sE3 := SpinEdit10;
319
    sE4 := SpinEdit9;
320
    _Go;
321
  end;
322
end;
323
 
324
procedure TForm1.Image1MouseEnter(Sender: TObject);
325
begin
326
  Label28.Visible := true;
327
  Label29.Visible := true;
328
end;
329
 
330
procedure TForm1.Image1MouseLeave(Sender: TObject);
331
begin
332
  Label10.Caption := '';
333
  Label28.Visible := false;
334
  Label29.Visible := false;
335
end;
336
 
337
procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
338
  Y: Integer);
339
begin
340
  label10.Caption := Format('Coords: [%d, %d]', [Round(Image1.Picture.Width*(X/Image1.Width)),
341
                                                 Round(Image1.Picture.Height*(Y/Image1.Height))]);
342
end;
343
 
344
function TForm1.SearchSceneIDGapFromTop: integer;
345
var
346
  i: integer;
347
begin
348
  result := -1;
349
  for i := 99 downto 0 do
350
  begin
351
    if ListBox1.Items.IndexOf(Format('SC%.2d', [i])) = -1 then
352
    begin
353
      result := i;
354
      exit;
355
    end;
356
  end;
357
end;
358
 
359
procedure TForm1.Button10Click(Sender: TObject);
360
begin
361
  Save;
10 daniel-mar 362
  if not FileExists('ShowTime32.exe') then raise Exception.Create('GAME.BIN saved; ShowTime32.exe not found.');
2 daniel-mar 363
  ShellExecute(Application.Handle, 'open', 'ShowTime32.exe', '', '', SW_NORMAL);
364
end;
365
 
366
procedure TForm1.Button11Click(Sender: TObject);
367
var
368
  fileName: string;
369
begin
370
  fileName := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + CurScene^.szDecisionBmp;
371
  if not FileExists(fileName) then exit;
372
  ShellExecute(Application.Handle, 'open', PChar(fileName), '', '', SW_NORMAL);
373
end;
374
 
375
procedure TForm1.Button12Click(Sender: TObject);
376
var
377
  fileName: string;
378
begin
379
  fileName := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + CurPicture^.szBitmapFile;
380
  if not FileExists(fileName) then exit;
381
  ShellExecute(Application.Handle, 'open', Pchar(fileName), '', '', SW_NORMAL);
382
end;
383
 
384
procedure TForm1.Button13Click(Sender: TObject);
385
var
386
  fileName: string;
387
begin
388
  fileName := CurScene^.szSceneFolder;
389
  if not DirectoryExists(fileName) then MkDir(fileName);
390
  ShellExecute(Application.Handle, 'open', 'explorer.exe', PChar(fileName), '', SW_NORMAL);
391
end;
392
 
393
procedure TForm1.HandlePossibleEmptySceneList;
394
begin
395
  if Game.numScenes = 0 then
396
  begin
397
    PageControl2.ActivePage := nil;
398
    PageControl2.Pages[0].TabVisible := false;
399
    PageControl2.Pages[1].TabVisible := false;
400
  end
401
  else
402
  begin
403
    if PageControl2.ActivePage = nil then PageControl2.ActivePageIndex := 0;
404
    PageControl2.Pages[0].TabVisible := true;
405
    PageControl2.Pages[1].TabVisible := true;
406
  end;
407
end;
408
 
409
procedure TForm1.Button14Click(Sender: TObject);
410
begin
411
  New;
412
end;
413
 
414
procedure TForm1.DisableEnableSceneControls(enable: boolean);
415
begin
416
  ListBox1.Enabled := enable;
417
  Button1.Enabled := enable;
418
  Button2.Enabled := enable;
419
  Button4.Enabled := enable;
420
  Button5.Enabled := enable;
421
end;
422
 
423
procedure TForm1.DisableEnablePictureControls(enable: boolean);
424
begin
425
  Button8.Enabled := enable;
426
  Button9.Enabled := enable;
427
  Button6.Enabled := enable;
428
  Button7.Enabled := enable;
429
end;
430
 
431
procedure TForm1.DisableEnableFileControls(enable: boolean);
432
begin
433
  Button3.Enabled := enable;
434
  Button10.Enabled := enable;
435
  Button14.Enabled := enable;
436
end;
437
 
6 daniel-mar 438
var
439
  AutomaticNextDia: boolean;
440
 
2 daniel-mar 441
procedure TForm1.Button15Click(Sender: TObject);
442
var
443
  decisionBMP: string;
444
  PictureLastFrame: Cardinal;
445
  i: integer;
446
  DecisionPicSet: boolean;
447
begin
448
  if PlayStart <> 0 then
449
  begin
6 daniel-mar 450
    if MediaplayerOpened and not AutomaticNextDia then
2 daniel-mar 451
    begin
452
      if MediaPlayer1.Mode = mpPlaying then MediaPlayer1.Stop;
453
      Mediaplayer1.TimeFormat := tfMilliseconds;
454
      if CurPictureTimepos*100 < Cardinal(MediaPlayer1.Length) then
455
      begin
456
        MediaPlayer1.Position := CurPictureTimepos * 100;
457
        MediaPlayer1.Play;
458
      end;
459
    end;
6 daniel-mar 460
    AutomaticNextDia := false;
2 daniel-mar 461
    FirstTickCount := GetTickCount;
462
    PlayStart := GetTickCount - CurPictureTimepos * 100;
463
  end
464
  else
465
  begin
8 daniel-mar 466
    TabSheet5.TabVisible := false;
2 daniel-mar 467
    DisableEnablePictureControls(false);
468
    DisableEnableSceneControls(false);
469
    DisableEnableFileControls(false);
470
    Edit1.Enabled := false;
471
    Edit3.Enabled := false;
472
    SpinEdit1.Enabled := false;
473
    SpinEdit13.Enabled := false;
474
    Label18.Font.Color := clGreen;
475
    try
476
      Timer1.Enabled := false;
477
 
478
      RecalcSoundtrackLength; // optional
479
 
480
      Mediaplayer1.FileName := Format('%s\%s', [CurScene^.szSceneFolder, CurScene^.szDialogWav]);
481
      if FileExists(Mediaplayer1.FileName) then
482
      begin
483
        Mediaplayer1.TimeFormat := tfMilliseconds;
484
        Mediaplayer1.Open;
485
        MediaplayerOpened := true;
486
        if CurPictureTimepos*100 < Cardinal(MediaPlayer1.Length) then
487
        begin
488
          MediaPlayer1.Position := CurPictureTimepos * 100;
489
          MediaPlayer1.Play;
490
        end;
491
      end
492
      else
493
      begin
494
        MediaplayerOpened := false;
495
        MediaPlayer1.FileName := '';
496
      end;
497
      PlayStart := GetTickCount - CurPictureTimepos * 100;
498
      Timer1.Enabled := true;
499
 
500
      {$REGION 'Calculate PictureLastFrame'}
501
      PictureLastFrame := 0;
502
      for i := 0 to CurScene^.numPics-1 do
503
      begin
504
        Inc(PictureLastFrame, Game.pictures[CurScene^.pictureIndex + i].duration);
505
      end;
506
      PictureLastFrame := PictureLastFrame * 100;
507
      {$ENDREGION}
508
 
509
      DecisionPicSet := false;
510
      while not Application.Terminated and
511
            not StopPlayRequest and
512
            (
513
                  (MediaPlayer1.Mode = mpPlaying) or
514
                  (GetTickCount - PlayStart <= PictureLastFrame)
515
            ) do
516
      begin
517
        if GetTickCount - PlayStart <= PictureLastFrame then
518
        begin
519
          DecisionPicSet := false;
520
          FirstTickCount := GetTickCount;
521
          while not Application.Terminated and ((GetTickCount - FirstTickCount) < CurPicture^.duration * 100) and not StopPlayRequest do
522
          begin
523
            Application.ProcessMessages;
524
            Sleep(0);
525
          end;
526
 
527
          if not Application.Terminated and (ListBox2.ItemIndex < ListBox2.Count-1) and not StopPlayRequest then
528
          begin
529
            ListBox2.ItemIndex := ListBox2.ItemIndex + 1;
6 daniel-mar 530
            AutomaticNextDia := true;
2 daniel-mar 531
            ListBox2Click(ListBox2);
532
          end;
533
        end
534
        else
535
        begin
536
          if not DecisionPicSet then
537
          begin
538
            decisionBMP := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + CurScene^.szDecisionBmp;
539
            if (CurScene^.szDecisionBmp <> '') and FileExists(decisionBMP) then
540
            begin
541
              Image2.Picture.LoadFromFile(decisionBMP);
6 daniel-mar 542
              AspectRatio(Image2, Panel2);
2 daniel-mar 543
            end
544
            else
545
            begin
546
              Image2.Picture := nil;
547
            end;
548
            DecisionPicSet := true;
549
          end;
550
          Application.ProcessMessages;
551
          Sleep(0);
552
        end;
553
      end;
554
    finally
555
      PlayStart := 0;
556
      if MediaPlayer1.Mode = mpPlaying then MediaPlayer1.Stop;
557
      if MediaplayerOpened then MediaPlayer1.Close;
558
      StopPlayRequest := false;
559
      Label18.Font.Color := clWindowText;
560
      Timer1.Enabled := false;
561
      DisableEnableFileControls(true);
562
      DisableEnableSceneControls(true);
563
      DisableEnablePictureControls(true);
8 daniel-mar 564
      TabSheet5.TabVisible := true;
2 daniel-mar 565
      Edit1.Enabled := true;
566
      SpinEdit1.Enabled := true;
567
      Edit3.Enabled := true;
568
      SpinEdit13.Enabled := true;
569
      Label18.Caption := _DecisecondToTime(CurPictureTimepos);
570
      ListBox2Click(ListBox2);
571
    end;
572
  end;
573
end;
574
 
8 daniel-mar 575
procedure TForm1.ShowSceneBmp;
576
var
577
  Filename: string;
578
begin
579
  Filename := string(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + CurPicture^.szBitmapFile);
580
  if FileExists(Filename) then
581
  begin
582
    Image2.Picture.LoadFromFile(Filename);
583
    AspectRatio(Image2, Panel2);
584
  end
585
  else
586
  begin
587
    Image2.Picture := nil;
588
  end;
589
end;
590
 
2 daniel-mar 591
procedure TForm1.Button16Click(Sender: TObject);
592
begin
593
  ListBox2.ItemIndex := 0; // go to the beginning
594
  ListBox2Click(ListBox2); // load picture data
595
  Button15Click(Button15); // play
596
end;
597
 
598
procedure TForm1.Button17Click(Sender: TObject);
599
begin
600
  if PlayStart <> 0 then
601
  begin
602
    Timer1.Enabled := false;
603
    if MediaplayerOpened then MediaPlayer1.Stop;
604
    StopPlayRequest := true;
605
  end;
606
end;
607
 
608
procedure TForm1.Button18Click(Sender: TObject);
609
var
610
  fileName: string;
611
begin
612
  fileName := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + CurScene^.szDialogWav;
613
  if not FileExists(fileName) then exit;
614
  ShellExecute(Application.Handle, 'open', PChar(fileName), '', '', SW_NORMAL);
615
end;
616
 
10 daniel-mar 617
procedure TForm1.Button19Click(Sender: TObject);
618
begin
11 daniel-mar 619
  if MessageDlg('Are you sure you want to discard all changes?', mtConfirmation, mbYesNoCancel, 0) = mrYes then
620
  begin
621
    CopyMemory(@Game, @GameBak, SizeOf(Game));
622
    SetupGUIAfterLoad;
623
  end;
10 daniel-mar 624
end;
625
 
2 daniel-mar 626
procedure TForm1.NewScene;
627
var
628
  sceneID: integer;
629
  newScene: PSceneDef;
630
begin
631
  if ListBox1.Items.Count = 100 then
632
  begin
633
    raise Exception.Create('No more space for another scene');
634
  end;
635
 
636
  sceneID := GetGreatestSceneID+1;
637
  if sceneID >= Length(Game.scenes) then sceneID := SearchSceneIDGapFromTop;
638
 
639
  newScene := Game.AddSceneAtEnd(sceneID);
640
  newScene.actions[0].nextSceneID := SCENEID_ENDGAME;
10 daniel-mar 641
  newScene.pictureIndex := Game.numPics;
2 daniel-mar 642
  ListBox1.Items.Add(newScene.szSceneFolder);
643
  ReloadActionSceneLists;
644
  HandlePossibleEmptySceneList;
645
  ListBox1.ItemIndex := ListBox1.Items.Count - 1;
646
  ListBox1Click(ListBox1);
647
end;
648
 
649
procedure TForm1.Button1Click(Sender: TObject);
650
begin
651
  NewScene;
652
end;
653
 
11 daniel-mar 654
procedure TForm1.Button20Click(Sender: TObject);
655
begin
656
  Game.Defrag;
657
  RecalcStats;
658
end;
659
 
2 daniel-mar 660
procedure TForm1.Button2Click(Sender: TObject);
661
var
662
  iScene, iAction, sceneID: integer;
663
  conflicts: TStringList;
664
  sWarning: string;
665
  bakItemindex: integer;
666
begin
667
  if ListBox1.Count = 0 then exit;
668
 
669
  (*
670
  if ListBox1.Count = 1 then
671
  begin
672
    raise Exception.Create('Can''t delete the scene if there is only one.');
673
  end;
674
  *)
675
 
676
  conflicts := TStringList.Create;
677
  try
678
    sceneID := GetSceneIDFromName(CurScene^.szSceneFolder);
679
    for iScene := 0 to Game.numScenes-1 do
680
    begin
681
      for iAction := 0 to Game.scenes[iScene].numActions-1 do
682
      begin
683
        if Game.scenes[iScene].actions[iAction].nextSceneID = sceneID then
684
        begin
685
          conflicts.Add(Format('Scene %s, action #%d', [Game.scenes[iScene].szSceneFolder, iAction+1]));
686
        end;
687
      end;
688
    end;
689
    if conflicts.Count > 0 then
690
    begin
691
      raise Exception.Create('Can''t delete this scene. There are following dependencies:'+#13#10#13#10+conflicts.Text);
692
    end;
693
  finally
694
    FreeAndNil(conflicts);
695
  end;
696
 
697
  sWarning := Format('Do you really want to delete scene %s?', [CurScene^.szSceneFolder]);
698
  if (ListBox1.ItemIndex = 0) and (ListBox1.Count >= 2) then
699
    sWarning := Format('Attention: This will make %s to your new intro sequence. Is that OK?', [ListBox1.Items[ListBox1.ItemIndex+1]]);
700
  if (MessageDlg(sWarning, mtConfirmation, mbYesNoCancel, 0) <> mrYes) then
701
  begin
702
    Exit;
703
  end;
704
 
705
  Game.DeleteScene(ListBox1.ItemIndex);
706
 
707
  bakItemindex := ListBox1.ItemIndex;
708
  ListBox1.Items.Delete(bakItemindex);
709
  ReloadActionSceneLists;
710
  HandlePossibleEmptySceneList;
711
  if ListBox1.Count > 0 then
712
  begin
713
    if bakItemindex = ListBox1.Count then Dec(bakItemindex);
714
    Listbox1.ItemIndex := bakItemindex;
715
    ListBox1Click(ListBox1);
716
  end;
717
end;
718
 
719
procedure TForm1.Button3Click(Sender: TObject);
720
begin
721
  Save;
722
end;
723
 
724
procedure TForm1.Button4Click(Sender: TObject);
725
begin
726
  if ListBox1.ItemIndex <= 0 then exit;
727
  Game.SwapScene(ListBox1.ItemIndex, ListBox1.ItemIndex-1);
728
  ListBox1.Items.Exchange(ListBox1.ItemIndex, ListBox1.ItemIndex-1);
729
  ReloadActionSceneLists;
730
end;
731
 
732
procedure TForm1.Button5Click(Sender: TObject);
733
begin
734
  if ListBox1.ItemIndex = ListBox1.Count-1 then exit;
735
  Game.SwapScene(ListBox1.ItemIndex, ListBox1.ItemIndex+1);
736
  ListBox1.Items.Exchange(ListBox1.ItemIndex, ListBox1.ItemIndex+1);
737
  ReloadActionSceneLists;
738
end;
739
 
740
procedure TForm1.Button6Click(Sender: TObject);
741
var
742
  pic: PPictureDef;
743
begin
10 daniel-mar 744
  if ListBox2.Items.Count > 0 then
745
    pic := Game.AddPictureBetween(CurScene^.pictureIndex + Max(ListBox2.ItemIndex+1,0), false)
746
  else
747
    pic := Game.AddPictureBetween(CurScene^.pictureIndex + Max(ListBox2.ItemIndex,0), true);
748
  pic.duration     := DEFAULT_DURATION;
749
  pic.szBitmapFile := DEFAULT_FILENAME;
2 daniel-mar 750
  if ListBox2.ItemIndex = -1 then
751
  begin
10 daniel-mar 752
    ListBox2.Items.Insert(ListBox2.Count, Format('(%d) %s', [DEFAULT_DURATION, DEFAULT_FILENAME]));
2 daniel-mar 753
    ListBox2.ItemIndex := ListBox2.Count - 1;
754
  end
755
  else
756
  begin
10 daniel-mar 757
    ListBox2.Items.Insert(ListBox2.ItemIndex+1, Format('(%d) %s', [DEFAULT_DURATION, DEFAULT_FILENAME]));
758
    ListBox2.ItemIndex := ListBox2.ItemIndex + 1;
2 daniel-mar 759
  end;
760
  ListBox2Click(Listbox2);
10 daniel-mar 761
  SelectFilenameBase(Edit3);
762
  RecalcStats;
2 daniel-mar 763
end;
764
 
765
procedure TForm1.Button7Click(Sender: TObject);
766
var
767
  bakIdx: integer;
768
begin
769
  if Listbox2.Count > 0 then
770
  begin
771
    bakIdx := ListBox2.ItemIndex;
10 daniel-mar 772
    Game.DeletePicture(CurScene^.pictureIndex + bakIdx);
2 daniel-mar 773
    ListBox2.Items.Delete(bakIdx);
774
    if ListBox2.Count > 0 then
775
    begin
776
      if bakIdx = ListBox2.Count then Dec(bakIdx);
777
      ListBox2.ItemIndex := bakIdx;
778
      ListBox2Click(Listbox2);
779
    end;
8 daniel-mar 780
    RecalcUnusedFiles;
2 daniel-mar 781
  end;
10 daniel-mar 782
  RecalcStats;
2 daniel-mar 783
end;
784
 
785
procedure TForm1.Button8Click(Sender: TObject);
786
begin
787
  if ListBox2.ItemIndex <= 0 then exit;
788
  Game.SwapPicture(CurScene^.pictureIndex+ListBox2.ItemIndex, CurScene^.pictureIndex+ListBox2.ItemIndex-1);
789
  ListBox2.Items.Exchange(ListBox2.ItemIndex, ListBox2.ItemIndex-1);
790
end;
791
 
792
procedure TForm1.Button9Click(Sender: TObject);
793
begin
794
  if ListBox2.ItemIndex = ListBox2.Count-1 then exit;
795
  Game.SwapPicture(CurScene^.pictureIndex+ListBox2.ItemIndex, CurScene^.pictureIndex+ListBox2.ItemIndex+1);
796
  ListBox2.Items.Exchange(ListBox2.ItemIndex, ListBox2.ItemIndex+1);
797
end;
798
 
799
procedure TForm1.Save;
800
var
801
  fs: TFileStream;
802
begin
10 daniel-mar 803
  CopyMemory(@GameBak, @Game, SizeOf(Game));
804
 
2 daniel-mar 805
  fs := TFileStream.Create('GAME.BIN', fmOpenWrite or fmCreate);
806
  try
807
    fs.WriteBuffer(Game, SizeOf(Game));
808
  finally
809
    FreeAndNil(fs);
810
  end;
811
end;
812
 
813
procedure TForm1.ActionTargetChange(Sender: TObject);
814
var
815
  actionIdx: integer;
816
  itemIdx: Integer;
817
begin
818
       if Sender = ComboBox1 then actionIdx := 0
819
  else if Sender = ComboBox2 then actionIdx := 1
820
  else if Sender = ComboBox3 then actionIdx := 2
821
  else raise Exception.Create('Unexpected sender for ActionTargetChange()');
822
 
823
  itemIdx := TComboBox(Sender).ItemIndex;
824
  if itemIdx = 0 then
825
    CurScene^.actions[actionIdx].nextSceneID := SCENEID_ENDGAME
826
  else if itemIdx = 1 then
827
    CurScene^.actions[actionIdx].nextSceneID := SCENEID_PREVDECISION
828
  else
829
    CurScene^.actions[actionIdx].nextSceneID := GetSceneIDFromName(ListBox1.Items[itemIdx - 2]);
830
end;
831
 
832
procedure TForm1.Addtoscene1Click(Sender: TObject);
833
var
834
  fil: string;
835
begin
836
  if ListBox3.ItemIndex = -1 then exit;
837
  fil := ListBox3.Items[ListBox3.ItemIndex];
838
  Button6.Click;
839
  Edit3.Text := fil;
840
end;
841
 
842
procedure TForm1.Edit1Change(Sender: TObject);
843
begin
844
  _WriteStringToFilename(@CurScene^.szDialogWav, Edit1.Text);
845
  RecalcSoundtrackLength;
846
  RecalcUnusedFiles;
847
 
848
  Label24.Visible := not FileExists(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + Edit1.Text);
849
  Label25.Visible := not FileExists(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + 'E' + Edit1.Text);
850
 
851
  Button18.Visible := CurScene^.szDialogWav <> '';
852
end;
853
 
854
procedure TForm1.Edit2Change(Sender: TObject);
855
begin
856
  _WriteStringToFilename(@CurScene^.szDecisionBmp, Edit2.Text);
857
  RecalcUnusedFiles;
8 daniel-mar 858
  RedrawDecisionBitmap;
2 daniel-mar 859
  Label27.Visible := not FileExists(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + Edit2.Text) and not (Edit2.Text = '');
860
  Button11.Visible := CurScene^.szDecisionBmp <> '';
861
end;
862
 
863
procedure TForm1.Edit3Change(Sender: TObject);
864
begin
865
  _WriteStringToFilename(@CurPicture^.szBitmapFile, Edit3.Text);
866
  ListBox2.Items[ListBox2.ItemIndex] := Format('(%d) %s', [CurPicture^.duration, CurPicture^.szBitmapFile]);
867
  RecalcUnusedFiles;
8 daniel-mar 868
  ShowSceneBmp;
2 daniel-mar 869
  Label26.Visible := not FileExists(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + Edit3.Text);
870
  Button12.Visible := CurPicture^.szBitmapFile <> '';
871
end;
872
 
10 daniel-mar 873
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
874
begin
875
  if not CompareMem(@Game, @GameBak, SizeOf(Game)) then
876
  begin
877
    case MessageDlg('Do you want to save the changes?', mtConfirmation, mbYesNoCancel, 0) of
11 daniel-mar 878
      mrYes:
10 daniel-mar 879
      begin
880
        Save;
881
        CanClose := true;
882
      end;
11 daniel-mar 883
      mrNo:
10 daniel-mar 884
      begin
885
        CanClose := true;
886
      end;
11 daniel-mar 887
      mrCancel:
10 daniel-mar 888
      begin
889
        CanClose := false;
890
      end;
891
    end;
892
  end;
893
end;
894
 
2 daniel-mar 895
procedure TForm1.FormCreate(Sender: TObject);
896
begin
897
  PageControl1.ActivePageIndex := 0;
898
  PageControl2.ActivePageIndex := 0;
10 daniel-mar 899
  PageControl3.ActivePageIndex := 0;
2 daniel-mar 900
  Label10.Caption := '';
901
  Label21.Caption := '';
902
  Label23.Caption := '';
903
end;
904
 
905
procedure TForm1.FormShow(Sender: TObject);
906
begin
907
  if FileExists('GAME.BIN') then
908
    Load
909
  else
910
    New;
911
end;
912
 
913
function TForm1.CurScene: PSceneDef;
914
begin
915
  if ListBox1.Count = 0 then raise Exception.Create('No scene available. Please create one.');
916
  if ListBox1.ItemIndex = -1 then raise Exception.Create('No scene selected. Please select one.');
917
  result := @Game.scenes[ListBox1.ItemIndex];
918
end;
919
 
920
procedure TForm1.ListBox1Click(Sender: TObject);
921
begin
922
  LoadScene;
923
end;
924
 
925
procedure TForm1.ListBox1DblClick(Sender: TObject);
926
begin
927
  Button16Click(Button16);
928
end;
929
 
11 daniel-mar 930
procedure TForm1.CheckBox1Click(Sender: TObject);
931
begin
932
  RedrawDecisionBitmap;
933
end;
934
 
2 daniel-mar 935
procedure TForm1.Close1Click(Sender: TObject);
936
begin
937
  Close;
938
end;
939
 
940
function TForm1.CurPicture: PPictureDef;
941
begin
942
  if ListBox2.Count = 0 then raise Exception.Create('No pictures available. Please create one.');
943
  if ListBox2.ItemIndex = -1 then raise Exception.Create('No pictures selected. Please select one.');
944
  result := @Game.pictures[CurScene^.pictureIndex + ListBox2.ItemIndex]
945
end;
946
 
947
function TForm1.CurPictureTimepos: Cardinal;
948
var
949
  i: integer;
950
begin
951
  result := 0;
952
  for i := curScene^.pictureIndex to curScene^.pictureIndex + ListBox2.ItemIndex - 1 do
953
  begin
954
    Inc(result, Game.pictures[i].duration);
955
  end;
956
end;
957
 
6 daniel-mar 958
class procedure TForm1.AspectRatio(image: TImage; panel: TControl);
959
var
960
  wi, hi, ws, hs: integer;
961
  ri, rs: double;
962
begin
963
  wi := image.Picture.Width;
964
  hi := image.Picture.Height;
965
  ri := wi / hi;
966
 
967
  ws := panel.Width;
968
  hs := panel.Height;
969
  rs := ws / hs;
970
 
971
  if rs > ri then
972
  begin
973
    image.Width  := Round(wi * hs/hi);
974
    image.Height := hs;
975
  end
976
  else
977
  begin
978
    image.Width  := ws;
979
    image.Height := Round(hi * ws/wi);
980
  end;
981
 
982
  image.Left := Round(panel.Width  / 2 - image.Width  / 2);
983
  image.Top  := Round(panel.Height / 2 - image.Height / 2);
984
end;
985
 
2 daniel-mar 986
procedure TForm1.ListBox2Click(Sender: TObject);
10 daniel-mar 987
var
988
  bakEvent: TNotifyEvent;
2 daniel-mar 989
begin
10 daniel-mar 990
  if CurScene^.numPics = 0 then
991
  begin
992
    SpinEdit13.Value := 0;
993
 
994
    bakEvent := Edit3.OnChange;
995
    try
996
      Edit3.OnChange := nil;
997
      Edit3.Text := '';
998
    finally
999
      Edit3.OnChange := bakEvent;
1000
    end;
1001
 
1002
    Label18.Caption := '';
1003
    Image2.Picture := nil;
1004
    exit;
1005
  end;
1006
 
2 daniel-mar 1007
  SpinEdit13.Value := CurPicture^.duration;
1008
  Edit3.Text := string(CurPicture^.szBitmapFile);
1009
 
8 daniel-mar 1010
  ShowSceneBmp;
2 daniel-mar 1011
 
1012
  Label18.Caption := _DecisecondToTime(CurPictureTimepos);
1013
 
1014
  if PlayStart <> 0 then
1015
  begin
1016
    Button15Click(Button15);
1017
  end;
10 daniel-mar 1018
 
1019
  RecalcStats;
2 daniel-mar 1020
end;
1021
 
1022
procedure TForm1.ListBox2DblClick(Sender: TObject);
1023
begin
1024
  Button15Click(Button15);
1025
end;
1026
 
8 daniel-mar 1027
procedure TForm1.ListBox3Click(Sender: TObject);
1028
var
1029
  fileName: string;
1030
begin
1031
  if ListBox3.ItemIndex = -1 then exit;
1032
  fileName := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + ListBox3.Items[ListBox3.ItemIndex];
1033
  Image3.Visible := FileExists(FileName);
1034
  if not FileExists(FileName) then exit;
1035
  Image3.Picture.LoadFromFile(Filename);
1036
  AspectRatio(Image3, Panel3);
1037
end;
1038
 
2 daniel-mar 1039
procedure TForm1.ListBox3DblClick(Sender: TObject);
1040
var
1041
  fileName: string;
1042
begin
1043
  if ListBox3.ItemIndex = -1 then exit;
1044
  fileName := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + ListBox3.Items[ListBox3.ItemIndex];
1045
  if not FileExists(FileName) then exit;
1046
  ShellExecute(Application.Handle, 'open', PChar(fileName), '', '', SW_NORMAL);
1047
end;
1048
 
1049
procedure TForm1.ListBox3MouseDown(Sender: TObject; Button: TMouseButton;
1050
  Shift: TShiftState; X, Y: Integer);
1051
var
1052
  APoint: TPoint;
1053
  Index: integer;
1054
begin
1055
  if Button = mbRight then
1056
  begin
1057
    APoint.X := X;
1058
    APoint.Y := Y;
1059
    Index := TListbox(Sender).ItemAtPos(APoint, True);
1060
    if Index > -1 then TListbox(Sender).Selected[Index] := True;
1061
  end;
1062
end;
1063
 
1064
procedure TForm1.SetupGUIAfterLoad;
1065
var
1066
  i: integer;
1067
begin
1068
  ListBox1.Clear;
1069
  for i := 0 to Game.numScenes - 1 do
1070
  begin
1071
    ListBox1.Items.Add(string(Game.scenes[i].szSceneFolder));
1072
  end;
1073
  (*
1074
  if ListBox1.Items.Count = 0 then
1075
  begin
1076
    NewScene;
1077
  end;
1078
  *)
1079
 
1080
  ReloadActionSceneLists;
1081
  HandlePossibleEmptySceneList;
1082
 
1083
  if ListBox1.Count > 0 then
1084
  begin
1085
    ListBox1.ItemIndex := 0;
1086
    ListBox1Click(Listbox1);
1087
  end;
1088
end;
1089
 
1090
procedure TForm1.New;
1091
begin
11 daniel-mar 1092
  PageControl1.ActivePageIndex := 0;
1093
  PageControl2.ActivePageIndex := 0;
1094
  PageControl3.ActivePageIndex := 0;
1095
  Label10.Caption := '';
1096
  Label21.Caption := '';
1097
  Label23.Caption := '';
1098
 
2 daniel-mar 1099
  ZeroMemory(@Game, SizeOf(Game));
10 daniel-mar 1100
  ZeroMemory(@GameBak, SizeOf(Game));
2 daniel-mar 1101
 
1102
  SetupGUIAfterLoad;
1103
end;
1104
 
1105
procedure TForm1.Load;
1106
var
1107
  fs: TFileStream;
1108
begin
1109
  fs := TFileStream.Create('GAME.BIN', fmOpenRead);
1110
  try
1111
    fs.ReadBuffer(Game, SizeOf(Game));
1112
  finally
1113
    FreeAndNil(fs);
1114
  end;
1115
 
11 daniel-mar 1116
  CopyMemory(@GameBak, @Game, SizeOf(Game));
1117
 
10 daniel-mar 1118
  if Game.RealPictureCount <> Game.numPics then
1119
  begin
1120
    MessageDlg('Picture count was wrong. Value was corrected.', mtInformation, [mbOk], 0);
1121
    Game.numPics := Game.RealPictureCount;
1122
  end;
1123
 
2 daniel-mar 1124
  SetupGUIAfterLoad;
1125
end;
1126
 
1127
function TForm1.FindSceneIndex(sceneID: integer): integer;
1128
var
1129
  i: Integer;
1130
  sSceneID: string;
1131
begin
1132
  sSceneID := Format('SC%.2d', [sceneID]);
1133
  for i := 0 to ListBox1.Count - 1 do
1134
  begin
1135
    if ListBox1.Items.Strings[i] = sSceneID then
1136
    begin
1137
      result := i;
1138
      exit;
1139
    end;
1140
  end;
1141
  result := -1;
1142
end;
1143
 
1144
procedure TForm1.RecalcSlideshowLength;
1145
var
1146
  i: integer;
1147
  Sum: integer;
1148
begin
1149
  Sum := 0;
1150
  for i := CurScene^.pictureIndex to CurScene^.pictureIndex + CurScene^.numPics - 1 do
1151
  begin
1152
    Inc(Sum, Game.pictures[i].duration);
1153
  end;
1154
  Label21.Caption := _DecisecondToTime(Sum);
1155
end;
1156
 
1157
procedure TForm1.RecalcUnusedFiles;
1158
var
1159
  i, idx: integer;
1160
  SR: TSearchRec;
6 daniel-mar 1161
  ext: string;
2 daniel-mar 1162
begin
6 daniel-mar 1163
  ListBox3.Items.BeginUpdate;
1164
  try
1165
    ListBox3.Clear;
2 daniel-mar 1166
 
8 daniel-mar 1167
    Image3.Visible := false;
1168
 
6 daniel-mar 1169
    if FindFirst(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + '*.*', faArchive, SR) = 0 then
1170
    begin
1171
      repeat
1172
        ext := UpperCase(ExtractFileExt(SR.Name));
1173
        if ((ext <> '.PK' {Adobe Audition}) and (ext <> '.DB' {Windows Thumbnail})) then
1174
        begin
1175
          ListBox3.Items.Add(SR.Name); //Fill the list
1176
        end;
1177
      until FindNext(SR) <> 0;
1178
      FindClose(SR);
1179
    end;
2 daniel-mar 1180
 
6 daniel-mar 1181
    // Remove the entries which are present
1182
    for i := CurScene^.pictureIndex to CurScene^.pictureIndex+CurScene^.numPics-1 do
1183
    begin
1184
      idx := ListBox3.Items.IndexOf(Game.pictures[i].szBitmapFile);
1185
      if idx <> -1 then ListBox3.Items.Delete(idx);
1186
    end;
1187
 
1188
    idx := ListBox3.Items.IndexOf(Edit1.Text);
2 daniel-mar 1189
    if idx <> -1 then ListBox3.Items.Delete(idx);
6 daniel-mar 1190
    idx := ListBox3.Items.IndexOf('E'+Edit1.Text);
1191
    if idx <> -1 then ListBox3.Items.Delete(idx);
2 daniel-mar 1192
 
6 daniel-mar 1193
    idx := ListBox3.Items.IndexOf(Edit2.Text);
1194
    if idx <> -1 then ListBox3.Items.Delete(idx);
2 daniel-mar 1195
 
6 daniel-mar 1196
    idx := ListBox3.Items.IndexOf(Edit3.Text);
1197
    if idx <> -1 then ListBox3.Items.Delete(idx);
1198
  finally
1199
    ListBox3.Items.EndUpdate;
1200
  end;
2 daniel-mar 1201
end;
1202
 
1203
procedure TForm1.RecalcSoundtrackLength;
1204
var
1205
  FileName: string;
1206
begin
1207
  if MediaPlayer1.Mode = mpPlaying then exit;
1208
 
1209
  FileName := IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + CurScene^.szDialogWav;
1210
  if not FileExists(FileName) then
1211
  begin
1212
    Label23.Caption := 'n/a';
1213
    exit;
1214
  end;
1215
  MediaPlayer1.FileName := FileName;
1216
  MediaPlayer1.TimeFormat := tfMilliseconds;
1217
  MediaPlayer1.Open;
1218
  Label23.Caption := _DecisecondToTime(MediaPlayer1.Length div 100);
1219
  MediaPlayer1.Close;
1220
end;
1221
 
1222
procedure TForm1.LoadScene;
1223
 
1224
  procedure _SelectActionComboBox(ComboBox: TComboBox; sceneID: SmallInt);
1225
  var
1226
    idx: Integer;
1227
  begin
1228
    if sceneID = SCENEID_ENDGAME then
1229
      ComboBox.ItemIndex := 0
1230
    else if sceneID = SCENEID_PREVDECISION then
1231
      ComboBox.ItemIndex := 1
1232
    else
1233
    begin
1234
      idx := FindSceneIndex(sceneID);
1235
      if idx = -1 then
1236
        ComboBox.ItemIndex := -1
1237
      else
1238
        ComboBox.ItemIndex := 2 + idx;
1239
    end;
1240
  end;
1241
 
1242
  procedure _PreparePictureList;
1243
  var
1244
    i: integer;
10 daniel-mar 1245
    //pic: PPictureDef;
2 daniel-mar 1246
  begin
1247
    ListBox2.Clear;
1248
 
1249
    if CurScene^.numPics = 0 then
1250
    begin
10 daniel-mar 1251
      (*
2 daniel-mar 1252
      pic := Game.AddPictureBetween(CurScene^.pictureIndex + Max(ListBox2.ItemIndex,0));
10 daniel-mar 1253
      pic.duration := DEFAULT_DURATION;
1254
      pic.szBitmapFile := DEFAULT_FILENAME;
1255
      *)
2 daniel-mar 1256
    end;
1257
 
1258
    for i := CurScene^.pictureIndex to CurScene^.pictureIndex + CurScene^.numPics - 1 do
1259
    begin
1260
      Listbox2.Items.Add(Format('(%d) %s', [Game.pictures[i].duration, Game.pictures[i].szBitmapFile]));
1261
    end;
1262
  end;
1263
 
1264
begin
1265
  SpinEdit1.Value := GetSceneIDFromName(CurScene^.szSceneFolder);
1266
  Edit1.Text := string(CurScene^.szDialogWav);
1267
  Edit2.Text := string(CurScene^.szDecisionBmp);
1268
 
1269
  _PreparePictureList;
1270
  ListBox2.ItemIndex := 0;
1271
  ListBox2Click(Listbox2);
1272
 
1273
  _SelectActionComboBox(ComboBox1, CurScene^.actions[0].nextSceneID);
1274
  _SelectActionComboBox(ComboBox2, CurScene^.actions[1].nextSceneID);
1275
  _SelectActionComboBox(ComboBox3, CurScene^.actions[2].nextSceneID);
1276
 
1277
  SpinEdit12.Value := CurScene^.numActions;
1278
  SpinEdit12Change(SpinEdit12);
1279
  PageControl1.ActivePageIndex := 0;
1280
 
1281
  SpinEdit3.Value  := CurScene^.actions[0].cHotspotTopLeft.X;
1282
  SpinEdit17.Value := CurScene^.actions[1].cHotspotTopLeft.X;
1283
  SpinEdit7.Value  := CurScene^.actions[2].cHotspotTopLeft.X;
1284
  SpinEdit2.Value  := CurScene^.actions[0].cHotspotTopLeft.Y;
1285
  SpinEdit18.Value := CurScene^.actions[1].cHotspotTopLeft.Y;
1286
  SpinEdit8.Value  := CurScene^.actions[2].cHotspotTopLeft.Y;
1287
  SpinEdit4.Value  := CurScene^.actions[0].cHotspotBottomRight.X;
1288
  SpinEdit19.Value := CurScene^.actions[1].cHotspotBottomRight.X;
1289
  SpinEdit10.Value := CurScene^.actions[2].cHotspotBottomRight.X;
1290
  SpinEdit5.Value  := CurScene^.actions[0].cHotspotBottomRight.Y;
1291
  SpinEdit20.Value := CurScene^.actions[1].cHotspotBottomRight.Y;
1292
  SpinEdit9.Value  := CurScene^.actions[2].cHotspotBottomRight.Y;
1293
  SpinEdit6.Value  := CurScene^.actions[0].scoreDelta;
1294
  SpinEdit21.Value := CurScene^.actions[1].scoreDelta;
1295
  SpinEdit11.Value := CurScene^.actions[2].scoreDelta;
1296
 
1297
  RedrawDecisionBitmap;
1298
 
1299
  RecalcSlideshowLength;
1300
  RecalcSoundtrackLength;
1301
 
1302
  RecalcUnusedFiles;
10 daniel-mar 1303
 
1304
  RecalcStats;
2 daniel-mar 1305
end;
1306
 
10 daniel-mar 1307
procedure TForm1.RecalcStats;
1308
begin
1309
  Label35.Caption := IntToStr(ListBox1.ItemIndex) + ' / ' + IntToStr(Game.numScenes);
1310
 
1311
  if ListBox2.ItemIndex >= 0 then
1312
    Label31.Caption := IntToStr(CurScene^.pictureIndex) + ' + ' + IntToStr(ListBox2.ItemIndex) + ' = ' + IntToStr(CurScene^.pictureIndex+ListBox2.ItemIndex)
1313
  else
1314
    Label31.Caption := IntToStr(CurScene^.pictureIndex);
1315
 
1316
  Label33.Caption := IntToStr(CurScene^.numPics) + ' / ' + IntToStr(Game.numPics);
1317
 
1318
  Label37.Caption := IntToStr(CurScene^.numActions) + ' / ' + IntToStr(Game.RealActionCount);
1319
end;
1320
 
2 daniel-mar 1321
procedure TForm1.ReloadActionSceneLists;
1322
 
1323
  procedure _ReloadActionSceneLists(ComboBox: TComboBox);
1324
  var
1325
    prevSelection: string;
1326
    i: Integer;
1327
  begin
1328
    prevSelection := ComboBox.Text;
1329
    try
1330
      ComboBox.Items.Clear;
1331
      ComboBox.Items.Add('Terminate program');
1332
      ComboBox.Items.Add('Previous decision');
1333
      ComboBox.Items.AddStrings(ListBox1.Items);
1334
    finally
1335
      ComboBox.ItemIndex := 0;
1336
      for i := ComboBox.Items.Count - 1 downto 0 do
1337
      begin
1338
        if ComboBox.Items.Strings[i] = prevSelection then
1339
        begin
1340
          ComboBox.ItemIndex := i;
1341
        end;
1342
      end;
1343
    end;
1344
  end;
1345
 
1346
begin
1347
  _ReloadActionSceneLists(ComboBox1);
1348
  _ReloadActionSceneLists(ComboBox2);
1349
  _ReloadActionSceneLists(ComboBox3);
1350
end;
1351
 
1352
procedure TForm1.SpinEdit12Change(Sender: TObject);
1353
begin
1354
  TabSheet3.TabVisible := SpinEdit12.Value >= 3;
1355
  if PageControl1.ActivePage = TabSheet3 then PageControl1.ActivePage := TabSheet2;
1356
 
1357
  TabSheet2.TabVisible := SpinEdit12.Value >= 2;
1358
  if PageControl1.ActivePage = TabSheet2 then PageControl1.ActivePage := TabSheet1;
1359
 
1360
  // TabSheet1.TabVisible := SpinEdit12.Value >= 1;
1361
 
1362
  CurScene^.numActions := SpinEdit12.Value;
1363
 
1364
  // QUE: zero data of actions which are inactive (numActions<action)?
10 daniel-mar 1365
 
1366
  RecalcStats;
11 daniel-mar 1367
  RedrawDecisionBitmap;
2 daniel-mar 1368
end;
1369
 
1370
procedure TForm1.SpinEdit13Change(Sender: TObject);
1371
begin
1372
  if SpinEdit13.Text = '' then exit;
1373
  CurPicture^.duration := SpinEdit13.Value;
1374
  ListBox2.Items[ListBox2.ItemIndex] := Format('(%d) %s', [CurPicture^.duration, CurPicture^.szBitmapFile]);
1375
  RecalcSlideshowLength;
1376
end;
1377
 
1378
procedure TForm1.SpinEdit1Change(Sender: TObject);
1379
 
1380
  function _CountNumScenes(str: string): integer;
1381
  var
1382
    i: integer;
1383
  begin
1384
    result := 0;
1385
    for i := 0 to ListBox1.Count-1 do
1386
    begin
1387
      if ListBox1.Items[i] = str then Inc(result);
1388
    end;
1389
  end;
1390
 
1391
var
1392
  sNew: string;
1393
begin
1394
  // TODO: warn if dependencies are broken
1395
 
1396
  if SpinEdit1.Text = '' then exit;
1397
  CurScene; // verify that a scene exists and is selected
1398
  sNew := Format('SC%.2d', [SpinEdit1.Value]);
1399
  ListBox1.Items[ListBox1.ItemIndex] := sNew;
1400
  Label17.Visible := _CountNumScenes(sNew) > 1;
1401
  ReloadActionSceneLists;
1402
  _WriteStringToFilename(@CurScene^.szSceneFolder, ListBox1.Items[ListBox1.ItemIndex]);
1403
end;
1404
 
1405
procedure TForm1.Timer1Timer(Sender: TObject);
1406
var
1407
  ms: Cardinal;
1408
begin
1409
  ms := GetTickCount - PlayStart;
1410
  Label18.Caption := FormatDatetime('hh:nn:ss', ms / 1000 / (24*60*60)) + ',' + IntToStr(ms mod 1000 div 100);
1411
end;
1412
 
1413
procedure TForm1.About1Click(Sender: TObject);
1414
begin
10 daniel-mar 1415
  ShowMessage('Plumbers Don''t Wear Ties - GAME.BIN editor (can be also used to create new games based on the "ShowTime" engine!)'+#13#10#13#10+'Written by Daniel Marschall (www.daniel-marschall.de)'+#13#10#13#10+'Published by ViaThinkSoft (www.viathinksoft.com)'+#13#10#13#10+'Current version: ' + CUR_VER);
2 daniel-mar 1416
end;
1417
 
1418
procedure TForm1.ActionSpinEditsChange(Sender: TObject);
1419
begin
1420
  if TSpinEdit(Sender).Text = '' then exit; // user is about to enter a negative value
1421
  if TSpinEdit(Sender).Text = '-' then exit; // user is about to enter a negative value
1422
 
1423
       if Sender = SpinEdit3  then CurScene^.actions[0].cHotspotTopLeft.X := TSpinEdit(Sender).Value
1424
  else if Sender = SpinEdit17 then CurScene^.actions[1].cHotspotTopLeft.X := TSpinEdit(Sender).Value
1425
  else if Sender = SpinEdit7  then CurScene^.actions[2].cHotspotTopLeft.X := TSpinEdit(Sender).Value
1426
  else if Sender = SpinEdit2  then CurScene^.actions[0].cHotspotTopLeft.Y := TSpinEdit(Sender).Value
1427
  else if Sender = SpinEdit18 then CurScene^.actions[1].cHotspotTopLeft.Y := TSpinEdit(Sender).Value
1428
  else if Sender = SpinEdit8  then CurScene^.actions[2].cHotspotTopLeft.Y := TSpinEdit(Sender).Value
1429
  else if Sender = SpinEdit4  then CurScene^.actions[0].cHotspotBottomRight.X := TSpinEdit(Sender).Value
1430
  else if Sender = SpinEdit19 then CurScene^.actions[1].cHotspotBottomRight.X := TSpinEdit(Sender).Value
1431
  else if Sender = SpinEdit10 then CurScene^.actions[2].cHotspotBottomRight.X := TSpinEdit(Sender).Value
1432
  else if Sender = SpinEdit5  then CurScene^.actions[0].cHotspotBottomRight.Y := TSpinEdit(Sender).Value
1433
  else if Sender = SpinEdit20 then CurScene^.actions[1].cHotspotBottomRight.Y := TSpinEdit(Sender).Value
1434
  else if Sender = SpinEdit9  then CurScene^.actions[2].cHotspotBottomRight.Y := TSpinEdit(Sender).Value
1435
  else if Sender = SpinEdit6  then CurScene^.actions[0].scoreDelta := TSpinEdit(Sender).Value
1436
  else if Sender = SpinEdit21 then CurScene^.actions[1].scoreDelta := TSpinEdit(Sender).Value
1437
  else if Sender = SpinEdit11 then CurScene^.actions[2].scoreDelta := TSpinEdit(Sender).Value;
1438
 
1439
  RedrawDecisionBitmap;
1440
end;
1441
 
1442
procedure TForm1.RedrawDecisionBitmap;
1443
var
1444
  Filename: string;
1445
begin
1446
  FileName := string(IncludeTrailingPathDelimiter(CurScene^.szSceneFolder) + Edit2.Text);
8 daniel-mar 1447
 
1448
  Image1.Visible := FileExists(FileName);
1449
 
6 daniel-mar 1450
  if not FileExists(FileName) then exit;
2 daniel-mar 1451
 
6 daniel-mar 1452
  Image1.Picture.Bitmap.LoadFromFile(FileName);
1453
  AspectRatio(Image1, Panel1);
1454
 
2 daniel-mar 1455
  Image1.Picture.Bitmap.PixelFormat := pf24bit; // Extend the palette, so we have red, green and blue guaranteed.
1456
 
1457
  Image1.Canvas.Brush.Style := bsDiagCross;
1458
 
11 daniel-mar 1459
  if (CheckBox1.Checked or (CurScene^.numActions >= 1)) and
1460
     (SpinEdit3.Value < SpinEdit4.Value) and (SpinEdit2.Value < SpinEdit5.Value) then
2 daniel-mar 1461
  begin
1462
    Image1.Canvas.Pen.Color := clRed;
1463
    Image1.Canvas.Brush.Color := clRed;
1464
    Image1.Canvas.Rectangle(SpinEdit3.Value,  SpinEdit2.Value,  SpinEdit4.Value,  SpinEdit5.Value);
1465
  end;
1466
 
11 daniel-mar 1467
  if (CheckBox1.Checked or (CurScene^.numActions >= 2)) and
1468
     (SpinEdit17.Value < SpinEdit19.Value) and (SpinEdit18.Value < SpinEdit20.Value) then
2 daniel-mar 1469
  begin
1470
    Image1.Canvas.Pen.Color := clLime;
1471
    Image1.Canvas.Brush.Color := clLime;
1472
    Image1.Canvas.Rectangle(SpinEdit17.Value, SpinEdit18.Value, SpinEdit19.Value, SpinEdit20.Value);
1473
  end;
1474
 
11 daniel-mar 1475
  if (CheckBox1.Checked or (CurScene^.numActions >= 3)) and
1476
     (SpinEdit7.Value < SpinEdit10.Value) and (SpinEdit8.Value < SpinEdit9.Value) then
2 daniel-mar 1477
  begin
1478
    Image1.Canvas.Pen.Color := clBlue;
1479
    Image1.Canvas.Brush.Color := clBlue;
1480
    Image1.Canvas.Rectangle(SpinEdit7.Value,  SpinEdit8.Value,  SpinEdit10.Value, SpinEdit9.Value);
1481
  end;
1482
end;
1483
 
1484
end.