Subversion Repositories plumbers

Rev

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